@internetarchive/bookreader 5.0.0-42 → 5.0.0-43
Sign up to get free protection for your applications and to get access to all the features.
- package/.github/workflows/node.js.yml +14 -14
- package/.github/workflows/npm-publish.yml +4 -4
- package/BookReader/BookReader.css +13 -13
- package/BookReader/BookReader.js +1 -1
- package/BookReader/BookReader.js.map +1 -1
- package/BookReader/ia-bookreader-bundle.js +87 -87
- package/BookReader/ia-bookreader-bundle.js.map +1 -1
- package/BookReader/icons/pause.svg +1 -1
- package/BookReader/icons/playback-speed.svg +1 -1
- package/BookReader/icons/read-aloud.svg +1 -1
- package/BookReader/images/BRicons.svg +2 -2
- package/BookReader/images/books_graphic.svg +1 -1
- package/BookReader/images/icon_book.svg +1 -1
- package/BookReader/images/icon_gear.svg +1 -1
- package/BookReader/images/icon_info.svg +1 -1
- package/BookReader/images/icon_playback-rate.svg +1 -1
- package/BookReader/images/icon_search_button.svg +1 -1
- package/BookReader/images/icon_share.svg +1 -1
- package/BookReader/images/icon_speaker.svg +1 -1
- package/BookReader/images/icon_speaker_open.svg +1 -1
- package/BookReader/images/marker_chap-off.svg +1 -1
- package/BookReader/images/marker_chap-on.svg +1 -1
- package/BookReader/images/marker_srch-on.svg +1 -1
- package/BookReader/jquery-1.10.1.js +1 -1
- package/BookReader/jquery-1.10.1.js.LICENSE.txt +6 -6
- package/BookReader/plugins/plugin.archive_analytics.js +1 -1
- package/BookReader/plugins/plugin.archive_analytics.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 -1
- package/BookReader/plugins/plugin.text_selection.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/CHANGELOG.md +5 -0
- package/package.json +17 -16
- package/renovate.json +6 -0
- package/scripts/preversion.js +4 -1
- package/src/BookNavigator/search/a-search-result.js +4 -6
- package/src/plugins/search/plugin.search.js +17 -4
- package/src/plugins/search/view.js +1 -3
- package/tests/{karma → jest}/BookNavigator/search/search-provider.test.js +29 -29
- package/tests/{karma → jest}/BookNavigator/search/search-results.test.js +57 -56
- package/tests/jest/plugins/search/plugin.search.test.js +40 -23
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"plugins/plugin.text_selection.js","mappings":"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","sources":["webpack://@internetarchive/bookreader/./src/util/strings.js","webpack://@internetarchive/bookreader/./src/plugins/plugin.text_selection.js","webpack://@internetarchive/bookreader/./src/util/browserSniffing.js","webpack://@internetarchive/bookreader/./node_modules/core-js/internals/number-parse-float.js","webpack://@internetarchive/bookreader/./node_modules/core-js/internals/string-trim-forced.js","webpack://@internetarchive/bookreader/./node_modules/core-js/modules/es.parse-float.js","webpack://@internetarchive/bookreader/./node_modules/core-js/modules/es.string.trim.js"],"sourcesContent":["/**\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 * @param {StringWithVars|String} template\n * @param { {[varName: string]: { toString: () => string} } } vars\n * @param { {[varName: string]: { toString: () => string} } } [overrides]\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","//@ts-check\nimport { createSVGPageLayer } from '../BookReader/PageContainer.js';\nimport { isFirefox, isSafari } from '../util/browserSniffing.js';\nimport { applyVariables } from '../util/strings.js';\n/** @typedef {import('../util/strings.js').StringWithVars} StringWithVars */\n/** @typedef {import('../BookReader/PageContainer.js').PageContainer} PageContainer */\n\nconst BookReader = /** @type {typeof import('../BookReader').default} */(window.BookReader);\n\nexport const DEFAULT_OPTIONS = {\n enabled: true,\n /** @type {StringWithVars} The URL to fetch the entire DJVU xml. Supports options.vars */\n fullDjvuXmlUrl: null,\n /** @type {StringWithVars} The URL to fetch a single page of the DJVU xml. Supports options.vars. Also has {{pageIndex}} */\n singlePageDjvuXmlUrl: null,\n};\n/** @typedef {typeof DEFAULT_OPTIONS} TextSelectionPluginOptions */\n\n/**\n * @template T\n */\nexport class Cache {\n constructor(maxSize = 10) {\n this.maxSize = maxSize;\n /** @type {T[]} */\n this.entries = [];\n }\n\n /**\n * @param {T} entry\n */\n add(entry) {\n if (this.entries.length >= this.maxSize) {\n this.entries.shift();\n }\n this.entries.push(entry);\n }\n}\n\nexport class TextSelectionPlugin {\n\n constructor(options = DEFAULT_OPTIONS, optionVariables, avoidTspans = isFirefox(), pointerEventsOnParagraph = isSafari()) {\n this.options = options;\n this.optionVariables = optionVariables;\n /**@type {PromiseLike<JQuery<HTMLElement>|undefined>} */\n this.djvuPagesPromise = null;\n // Using text elements instead of tspans for words because Firefox does not allow svg tspan stretch.\n // Tspans are necessary on Chrome because they prevent newline character after every word when copying\n this.svgParagraphElement = \"text\";\n this.svgWordElement = \"tspan\";\n this.insertNewlines = avoidTspans;\n // Safari has a bug where `pointer-events` doesn't work on `<tspans>`. So\n // there we will set `pointer-events: all` on the paragraph element. We don't\n // do this everywhere, because it's a worse experience. Thanks Safari :/\n this.pointerEventsOnParagraph = pointerEventsOnParagraph;\n if (avoidTspans) {\n this.svgParagraphElement = \"g\";\n this.svgWordElement = \"text\";\n }\n\n /** @type {Cache<{index: number, response: any}>} */\n this.pageTextCache = new Cache();\n\n /**\n * Sometimes there are too many words on a page, and the browser becomes near\n * unusable. For now don't render text layer for pages with too many words.\n */\n this.maxWordRendered = 2500;\n }\n\n init() {\n // Only fetch the full djvu xml if the single page url isn't there\n if (this.options.singlePageDjvuXmlUrl) return;\n this.djvuPagesPromise = $.ajax({\n type: \"GET\",\n url: applyVariables(this.options.fullDjvuXmlUrl, this.optionVariables),\n dataType: \"html\",\n error: (e) => undefined\n }).then((res) => {\n try {\n const xmlMap = $.parseXML(res);\n return xmlMap && $(xmlMap).find(\"OBJECT\");\n } catch (e) {\n return undefined;\n }\n });\n }\n\n /**\n * @param {number} index\n * @returns {Promise<HTMLElement|undefined>}\n */\n async getPageText(index) {\n if (this.options.singlePageDjvuXmlUrl) {\n const cachedEntry = this.pageTextCache.entries.find(x => x.index == index);\n if (cachedEntry) {\n return cachedEntry.response;\n }\n const res = await $.ajax({\n type: \"GET\",\n url: applyVariables(this.options.singlePageDjvuXmlUrl, this.optionVariables, { pageIndex: index }),\n dataType: \"html\",\n error: (e) => undefined,\n });\n try {\n const xmlDoc = $.parseXML(res);\n const result = xmlDoc && $(xmlDoc).find(\"OBJECT\")[0];\n this.pageTextCache.add({ index, response: result });\n return result;\n } catch (e) {\n return undefined;\n }\n } else {\n const XMLpagesArr = await this.djvuPagesPromise;\n if (XMLpagesArr) return XMLpagesArr[index];\n }\n }\n\n /**\n * Intercept copied text to remove any styling applied to it\n * @param {JQuery} $container\n */\n interceptCopy($container) {\n $container[0].addEventListener('copy', (event) => {\n const selection = document.getSelection();\n event.clipboardData.setData('text/plain', selection.toString());\n event.preventDefault();\n });\n }\n\n /**\n * Applies mouse events when in default mode\n * @param {SVGElement} svg\n */\n defaultMode(svg) {\n svg.classList.remove(\"selectingSVG\");\n $(svg).on(\"mousedown.textSelectPluginHandler\", (event) => {\n if (!$(event.target).is(\".BRwordElement\")) return;\n event.stopPropagation();\n svg.classList.add(\"selectingSVG\");\n $(svg).one(\"mouseup.textSelectPluginHandler\", (event) => {\n if (window.getSelection().toString() != \"\") {\n event.stopPropagation();\n $(svg).off(\".textSelectPluginHandler\");\n this.textSelectingMode(svg);\n }\n else svg.classList.remove(\"selectingSVG\");\n });\n });\n }\n\n /**\n * Applies mouse events when in textSelecting mode\n * @param {SVGElement} svg\n */\n textSelectingMode(svg) {\n $(svg).on('mousedown.textSelectPluginHandler', (event) => {\n if (!$(event.target).is(\".BRwordElement\")) {\n if (window.getSelection().toString() != \"\") window.getSelection().removeAllRanges();\n }\n event.stopPropagation();\n });\n $(svg).on('mouseup.textSelectPluginHandler', (event) => {\n event.stopPropagation();\n if (window.getSelection().toString() == \"\") {\n $(svg).off(\".textSelectPluginHandler\");\n this.defaultMode(svg); }\n });\n }\n\n /**\n * Initializes text selection modes if there is an svg on the page\n * @param {JQuery} $container\n */\n stopPageFlip($container) {\n /** @type {JQuery<SVGElement>} */\n const $svg = $container.find('svg.textSelectionSVG');\n if (!$svg.length) return;\n $svg.each((i, s) => this.defaultMode(s));\n this.interceptCopy($container);\n }\n\n /**\n * @param {PageContainer} pageContainer\n */\n async createTextLayer(pageContainer) {\n const pageIndex = pageContainer.page.index;\n const $container = pageContainer.$container;\n const $svgLayers = $container.find('.textSelectionSVG');\n if ($svgLayers.length) return;\n const XMLpage = await this.getPageText(pageIndex);\n if (!XMLpage) return;\n\n const totalWords = $(XMLpage).find(\"WORD\").length;\n if (totalWords > this.maxWordRendered) {\n console.log(`Page ${pageIndex} has too many words (${totalWords} > ${this.maxWordRendered}). Not rendering text layer.`);\n return;\n }\n\n const svg = createSVGPageLayer(pageContainer.page, 'textSelectionSVG');\n $container.append(svg);\n\n $(XMLpage).find(\"PARAGRAPH\").each((i, paragraph) => {\n // Adding text element for each paragraph in the page\n const words = $(paragraph).find(\"WORD\");\n if (!words.length) return;\n const paragSvg = document.createElementNS(\"http://www.w3.org/2000/svg\", this.svgParagraphElement);\n paragSvg.setAttribute(\"class\", \"BRparagElement\");\n if (this.pointerEventsOnParagraph) {\n paragSvg.style.pointerEvents = \"all\";\n }\n\n const wordHeightArr = [];\n\n for (let i = 0; i < words.length; i++) {\n // Adding tspan for each word in paragraph\n const currWord = words[i];\n // eslint-disable-next-line no-unused-vars\n const [left, bottom, right, top] = $(currWord).attr(\"coords\").split(',').map(parseFloat);\n const wordHeight = bottom - top;\n wordHeightArr.push(wordHeight);\n\n const wordTspan = document.createElementNS(\"http://www.w3.org/2000/svg\", this.svgWordElement);\n wordTspan.setAttribute(\"class\", \"BRwordElement\");\n wordTspan.setAttribute(\"x\", left.toString());\n wordTspan.setAttribute(\"y\", bottom.toString());\n wordTspan.setAttribute(\"textLength\", (right - left).toString());\n wordTspan.setAttribute(\"lengthAdjust\", \"spacingAndGlyphs\");\n wordTspan.textContent = currWord.textContent;\n paragSvg.appendChild(wordTspan);\n\n // Adding spaces after words except at the end of the paragraph\n // TODO: assumes left-to-right text\n if (i < words.length - 1) {\n const nextWord = words[i + 1];\n // eslint-disable-next-line no-unused-vars\n const [leftNext, bottomNext, rightNext, topNext] = $(nextWord).attr(\"coords\").split(',').map(parseFloat);\n const spaceTspan = document.createElementNS(\"http://www.w3.org/2000/svg\", this.svgWordElement);\n spaceTspan.setAttribute(\"class\", \"BRwordElement\");\n spaceTspan.setAttribute(\"x\", right.toString());\n spaceTspan.setAttribute(\"y\", bottom.toString());\n if ((leftNext - right) > 0) spaceTspan.setAttribute(\"textLength\", (leftNext - right).toString());\n spaceTspan.setAttribute(\"lengthAdjust\", \"spacingAndGlyphs\");\n spaceTspan.textContent = \" \";\n paragSvg.appendChild(spaceTspan);\n }\n\n // Adds newline at the end of paragraph on Firefox\n if ((i == words.length - 1 && (this.insertNewlines))) {\n paragSvg.appendChild(document.createTextNode(\"\\n\"));\n }\n }\n\n wordHeightArr.sort();\n const paragWordHeight = wordHeightArr[Math.floor(wordHeightArr.length * 0.85)];\n paragSvg.setAttribute(\"font-size\", paragWordHeight.toString());\n svg.appendChild(paragSvg);\n });\n this.stopPageFlip($container);\n }\n}\n\nexport class BookreaderWithTextSelection extends BookReader {\n init() {\n const options = Object.assign({}, DEFAULT_OPTIONS, this.options.plugins.textSelection);\n if (options.enabled) {\n this.textSelectionPlugin = new TextSelectionPlugin(options, this.options.vars);\n // Write this back; this way the plugin is the source of truth, and BR just\n // contains a reference to it.\n this.options.plugins.textSelection = options;\n this.textSelectionPlugin.init();\n }\n super.init();\n }\n\n /**\n * @param {number} index\n */\n _createPageContainer(index) {\n const pageContainer = super._createPageContainer(index);\n // Disable if thumb mode; it's too janky\n // .page can be null for \"pre-cover\" region\n if (this.mode !== this.constModeThumb && pageContainer.page) {\n this.textSelectionPlugin?.createTextLayer(pageContainer);\n }\n return pageContainer;\n }\n}\nwindow.BookReader = BookreaderWithTextSelection;\nexport default BookreaderWithTextSelection;\n","\n/**\n * Checks whether the current browser is a Chrome/Chromium browser\n * Code from https://stackoverflow.com/a/4565120/2317712\n * @param {string} [userAgent]\n * @param {string} [vendor]\n * @return {boolean}\n */\nexport function isChrome(userAgent = navigator.userAgent, vendor = navigator.vendor) {\n return /chrome/i.test(userAgent) && /google inc/i.test(vendor);\n}\n\n/**\n * Checks whether the current browser is firefox\n * @param {string} [userAgent]\n * @return {boolean}\n */\nexport function isFirefox(userAgent = navigator.userAgent) {\n return /firefox/i.test(userAgent);\n}\n\n/**\n * Checks whether the current browser is safari\n * https://developer.mozilla.org/en-US/docs/Web/HTTP/Browser_detection_using_the_user_agent#Browser_Name\n * @param {string} [userAgent]\n * @return {boolean}\n */\nexport function isSafari(userAgent = navigator.userAgent) {\n return /safari/i.test(userAgent) && !/chrome|chromium/i.test(userAgent);\n}\n","var global = require('../internals/global');\nvar toString = require('../internals/to-string');\nvar trim = require('../internals/string-trim').trim;\nvar whitespaces = require('../internals/whitespaces');\n\nvar $parseFloat = global.parseFloat;\nvar FORCED = 1 / $parseFloat(whitespaces + '-0') !== -Infinity;\n\n// `parseFloat` method\n// https://tc39.es/ecma262/#sec-parsefloat-string\nmodule.exports = FORCED ? function parseFloat(string) {\n var trimmedString = trim(toString(string));\n var result = $parseFloat(trimmedString);\n return result === 0 && trimmedString.charAt(0) == '-' ? -0 : result;\n} : $parseFloat;\n","var 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]() || non[METHOD_NAME]() != non || whitespaces[METHOD_NAME].name !== METHOD_NAME;\n });\n};\n","var $ = require('../internals/export');\nvar parseFloatImplementation = require('../internals/number-parse-float');\n\n// `parseFloat` method\n// https://tc39.es/ecma262/#sec-parsefloat-string\n$({ global: true, forced: parseFloat != parseFloatImplementation }, {\n parseFloat: parseFloatImplementation\n});\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"],"names":["applyVariables","template","vars","overrides","possibleFilters","APPLY_FILTERS","replace","$0","$1","split","map","x","trim","varName","filterNames","value","n","reduce","acc","cur","toString","urlencode","encodeURIComponent","BookReader","window","DEFAULT_OPTIONS","enabled","fullDjvuXmlUrl","singlePageDjvuXmlUrl","Cache","maxSize","this","entries","entry","length","shift","push","TextSelectionPlugin","options","optionVariables","avoidTspans","isFirefox","pointerEventsOnParagraph","isSafari","djvuPagesPromise","svgParagraphElement","svgWordElement","insertNewlines","pageTextCache","maxWordRendered","$","ajax","type","url","dataType","error","e","then","res","xmlMap","parseXML","find","index","cachedEntry","response","pageIndex","xmlDoc","result","add","undefined","XMLpagesArr","$container","addEventListener","event","selection","document","getSelection","clipboardData","setData","preventDefault","svg","classList","remove","on","target","is","stopPropagation","one","off","textSelectingMode","removeAllRanges","defaultMode","$svg","each","i","s","interceptCopy","pageContainer","page","getPageText","XMLpage","totalWords","console","log","createSVGPageLayer","append","paragraph","words","paragSvg","createElementNS","setAttribute","style","pointerEvents","wordHeightArr","currWord","attr","parseFloat","left","bottom","right","wordHeight","wordTspan","textContent","appendChild","nextWord","leftNext","spaceTspan","createTextNode","sort","paragWordHeight","Math","floor","stopPageFlip","BookreaderWithTextSelection","Object","assign","plugins","textSelection","textSelectionPlugin","init","mode","constModeThumb","createTextLayer","isChrome","userAgent","navigator","vendor","test","global","whitespaces","$parseFloat","FORCED","module","exports","string","trimmedString","charAt","fails","METHOD_NAME","name","parseFloatImplementation","forced","$trim","proto","forcedStringTrimMethod"],"sourceRoot":""}
|
1
|
+
{"version":3,"file":"plugins/plugin.text_selection.js","mappings":"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","sources":["webpack://@internetarchive/bookreader/./src/util/strings.js","webpack://@internetarchive/bookreader/./src/plugins/plugin.text_selection.js","webpack://@internetarchive/bookreader/./src/util/browserSniffing.js","webpack://@internetarchive/bookreader/./node_modules/core-js/internals/number-parse-float.js","webpack://@internetarchive/bookreader/./node_modules/core-js/internals/string-trim-forced.js","webpack://@internetarchive/bookreader/./node_modules/core-js/modules/es.parse-float.js","webpack://@internetarchive/bookreader/./node_modules/core-js/modules/es.string.trim.js"],"sourcesContent":["/**\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 * @param {StringWithVars|String} template\n * @param { {[varName: string]: { toString: () => string} } } vars\n * @param { {[varName: string]: { toString: () => string} } } [overrides]\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","//@ts-check\nimport { createSVGPageLayer } from '../BookReader/PageContainer.js';\nimport { isFirefox, isSafari } from '../util/browserSniffing.js';\nimport { applyVariables } from '../util/strings.js';\n/** @typedef {import('../util/strings.js').StringWithVars} StringWithVars */\n/** @typedef {import('../BookReader/PageContainer.js').PageContainer} PageContainer */\n\nconst BookReader = /** @type {typeof import('../BookReader').default} */(window.BookReader);\n\nexport const DEFAULT_OPTIONS = {\n enabled: true,\n /** @type {StringWithVars} The URL to fetch the entire DJVU xml. Supports options.vars */\n fullDjvuXmlUrl: null,\n /** @type {StringWithVars} The URL to fetch a single page of the DJVU xml. Supports options.vars. Also has {{pageIndex}} */\n singlePageDjvuXmlUrl: null,\n};\n/** @typedef {typeof DEFAULT_OPTIONS} TextSelectionPluginOptions */\n\n/**\n * @template T\n */\nexport class Cache {\n constructor(maxSize = 10) {\n this.maxSize = maxSize;\n /** @type {T[]} */\n this.entries = [];\n }\n\n /**\n * @param {T} entry\n */\n add(entry) {\n if (this.entries.length >= this.maxSize) {\n this.entries.shift();\n }\n this.entries.push(entry);\n }\n}\n\nexport class TextSelectionPlugin {\n\n constructor(options = DEFAULT_OPTIONS, optionVariables, avoidTspans = isFirefox(), pointerEventsOnParagraph = isSafari()) {\n this.options = options;\n this.optionVariables = optionVariables;\n /**@type {PromiseLike<JQuery<HTMLElement>|undefined>} */\n this.djvuPagesPromise = null;\n // Using text elements instead of tspans for words because Firefox does not allow svg tspan stretch.\n // Tspans are necessary on Chrome because they prevent newline character after every word when copying\n this.svgParagraphElement = \"text\";\n this.svgWordElement = \"tspan\";\n this.insertNewlines = avoidTspans;\n // Safari has a bug where `pointer-events` doesn't work on `<tspans>`. So\n // there we will set `pointer-events: all` on the paragraph element. We don't\n // do this everywhere, because it's a worse experience. Thanks Safari :/\n this.pointerEventsOnParagraph = pointerEventsOnParagraph;\n if (avoidTspans) {\n this.svgParagraphElement = \"g\";\n this.svgWordElement = \"text\";\n }\n\n /** @type {Cache<{index: number, response: any}>} */\n this.pageTextCache = new Cache();\n\n /**\n * Sometimes there are too many words on a page, and the browser becomes near\n * unusable. For now don't render text layer for pages with too many words.\n */\n this.maxWordRendered = 2500;\n }\n\n init() {\n // Only fetch the full djvu xml if the single page url isn't there\n if (this.options.singlePageDjvuXmlUrl) return;\n this.djvuPagesPromise = $.ajax({\n type: \"GET\",\n url: applyVariables(this.options.fullDjvuXmlUrl, this.optionVariables),\n dataType: \"html\",\n error: (e) => undefined\n }).then((res) => {\n try {\n const xmlMap = $.parseXML(res);\n return xmlMap && $(xmlMap).find(\"OBJECT\");\n } catch (e) {\n return undefined;\n }\n });\n }\n\n /**\n * @param {number} index\n * @returns {Promise<HTMLElement|undefined>}\n */\n async getPageText(index) {\n if (this.options.singlePageDjvuXmlUrl) {\n const cachedEntry = this.pageTextCache.entries.find(x => x.index == index);\n if (cachedEntry) {\n return cachedEntry.response;\n }\n const res = await $.ajax({\n type: \"GET\",\n url: applyVariables(this.options.singlePageDjvuXmlUrl, this.optionVariables, { pageIndex: index }),\n dataType: \"html\",\n error: (e) => undefined,\n });\n try {\n const xmlDoc = $.parseXML(res);\n const result = xmlDoc && $(xmlDoc).find(\"OBJECT\")[0];\n this.pageTextCache.add({ index, response: result });\n return result;\n } catch (e) {\n return undefined;\n }\n } else {\n const XMLpagesArr = await this.djvuPagesPromise;\n if (XMLpagesArr) return XMLpagesArr[index];\n }\n }\n\n /**\n * Intercept copied text to remove any styling applied to it\n * @param {JQuery} $container\n */\n interceptCopy($container) {\n $container[0].addEventListener('copy', (event) => {\n const selection = document.getSelection();\n event.clipboardData.setData('text/plain', selection.toString());\n event.preventDefault();\n });\n }\n\n /**\n * Applies mouse events when in default mode\n * @param {SVGElement} svg\n */\n defaultMode(svg) {\n svg.classList.remove(\"selectingSVG\");\n $(svg).on(\"mousedown.textSelectPluginHandler\", (event) => {\n if (!$(event.target).is(\".BRwordElement\")) return;\n event.stopPropagation();\n svg.classList.add(\"selectingSVG\");\n $(svg).one(\"mouseup.textSelectPluginHandler\", (event) => {\n if (window.getSelection().toString() != \"\") {\n event.stopPropagation();\n $(svg).off(\".textSelectPluginHandler\");\n this.textSelectingMode(svg);\n }\n else svg.classList.remove(\"selectingSVG\");\n });\n });\n }\n\n /**\n * Applies mouse events when in textSelecting mode\n * @param {SVGElement} svg\n */\n textSelectingMode(svg) {\n $(svg).on('mousedown.textSelectPluginHandler', (event) => {\n if (!$(event.target).is(\".BRwordElement\")) {\n if (window.getSelection().toString() != \"\") window.getSelection().removeAllRanges();\n }\n event.stopPropagation();\n });\n $(svg).on('mouseup.textSelectPluginHandler', (event) => {\n event.stopPropagation();\n if (window.getSelection().toString() == \"\") {\n $(svg).off(\".textSelectPluginHandler\");\n this.defaultMode(svg); }\n });\n }\n\n /**\n * Initializes text selection modes if there is an svg on the page\n * @param {JQuery} $container\n */\n stopPageFlip($container) {\n /** @type {JQuery<SVGElement>} */\n const $svg = $container.find('svg.textSelectionSVG');\n if (!$svg.length) return;\n $svg.each((i, s) => this.defaultMode(s));\n this.interceptCopy($container);\n }\n\n /**\n * @param {PageContainer} pageContainer\n */\n async createTextLayer(pageContainer) {\n const pageIndex = pageContainer.page.index;\n const $container = pageContainer.$container;\n const $svgLayers = $container.find('.textSelectionSVG');\n if ($svgLayers.length) return;\n const XMLpage = await this.getPageText(pageIndex);\n if (!XMLpage) return;\n\n const totalWords = $(XMLpage).find(\"WORD\").length;\n if (totalWords > this.maxWordRendered) {\n console.log(`Page ${pageIndex} has too many words (${totalWords} > ${this.maxWordRendered}). Not rendering text layer.`);\n return;\n }\n\n const svg = createSVGPageLayer(pageContainer.page, 'textSelectionSVG');\n $container.append(svg);\n\n $(XMLpage).find(\"PARAGRAPH\").each((i, paragraph) => {\n // Adding text element for each paragraph in the page\n const words = $(paragraph).find(\"WORD\");\n if (!words.length) return;\n const paragSvg = document.createElementNS(\"http://www.w3.org/2000/svg\", this.svgParagraphElement);\n paragSvg.setAttribute(\"class\", \"BRparagElement\");\n if (this.pointerEventsOnParagraph) {\n paragSvg.style.pointerEvents = \"all\";\n }\n\n const wordHeightArr = [];\n\n for (let i = 0; i < words.length; i++) {\n // Adding tspan for each word in paragraph\n const currWord = words[i];\n // eslint-disable-next-line no-unused-vars\n const [left, bottom, right, top] = $(currWord).attr(\"coords\").split(',').map(parseFloat);\n const wordHeight = bottom - top;\n wordHeightArr.push(wordHeight);\n\n const wordTspan = document.createElementNS(\"http://www.w3.org/2000/svg\", this.svgWordElement);\n wordTspan.setAttribute(\"class\", \"BRwordElement\");\n wordTspan.setAttribute(\"x\", left.toString());\n wordTspan.setAttribute(\"y\", bottom.toString());\n wordTspan.setAttribute(\"textLength\", (right - left).toString());\n wordTspan.setAttribute(\"lengthAdjust\", \"spacingAndGlyphs\");\n wordTspan.textContent = currWord.textContent;\n paragSvg.appendChild(wordTspan);\n\n // Adding spaces after words except at the end of the paragraph\n // TODO: assumes left-to-right text\n if (i < words.length - 1) {\n const nextWord = words[i + 1];\n // eslint-disable-next-line no-unused-vars\n const [leftNext, bottomNext, rightNext, topNext] = $(nextWord).attr(\"coords\").split(',').map(parseFloat);\n const spaceTspan = document.createElementNS(\"http://www.w3.org/2000/svg\", this.svgWordElement);\n spaceTspan.setAttribute(\"class\", \"BRwordElement\");\n spaceTspan.setAttribute(\"x\", right.toString());\n spaceTspan.setAttribute(\"y\", bottom.toString());\n if ((leftNext - right) > 0) spaceTspan.setAttribute(\"textLength\", (leftNext - right).toString());\n spaceTspan.setAttribute(\"lengthAdjust\", \"spacingAndGlyphs\");\n spaceTspan.textContent = \" \";\n paragSvg.appendChild(spaceTspan);\n }\n\n // Adds newline at the end of paragraph on Firefox\n if ((i == words.length - 1 && (this.insertNewlines))) {\n paragSvg.appendChild(document.createTextNode(\"\\n\"));\n }\n }\n\n wordHeightArr.sort();\n const paragWordHeight = wordHeightArr[Math.floor(wordHeightArr.length * 0.85)];\n paragSvg.setAttribute(\"font-size\", paragWordHeight.toString());\n svg.appendChild(paragSvg);\n });\n this.stopPageFlip($container);\n }\n}\n\nexport class BookreaderWithTextSelection extends BookReader {\n init() {\n const options = Object.assign({}, DEFAULT_OPTIONS, this.options.plugins.textSelection);\n if (options.enabled) {\n this.textSelectionPlugin = new TextSelectionPlugin(options, this.options.vars);\n // Write this back; this way the plugin is the source of truth, and BR just\n // contains a reference to it.\n this.options.plugins.textSelection = options;\n this.textSelectionPlugin.init();\n }\n super.init();\n }\n\n /**\n * @param {number} index\n */\n _createPageContainer(index) {\n const pageContainer = super._createPageContainer(index);\n // Disable if thumb mode; it's too janky\n // .page can be null for \"pre-cover\" region\n if (this.mode !== this.constModeThumb && pageContainer.page) {\n this.textSelectionPlugin?.createTextLayer(pageContainer);\n }\n return pageContainer;\n }\n}\nwindow.BookReader = BookreaderWithTextSelection;\nexport default BookreaderWithTextSelection;\n","\n/**\n * Checks whether the current browser is a Chrome/Chromium browser\n * Code from https://stackoverflow.com/a/4565120/2317712\n * @param {string} [userAgent]\n * @param {string} [vendor]\n * @return {boolean}\n */\nexport function isChrome(userAgent = navigator.userAgent, vendor = navigator.vendor) {\n return /chrome/i.test(userAgent) && /google inc/i.test(vendor);\n}\n\n/**\n * Checks whether the current browser is firefox\n * @param {string} [userAgent]\n * @return {boolean}\n */\nexport function isFirefox(userAgent = navigator.userAgent) {\n return /firefox/i.test(userAgent);\n}\n\n/**\n * Checks whether the current browser is safari\n * https://developer.mozilla.org/en-US/docs/Web/HTTP/Browser_detection_using_the_user_agent#Browser_Name\n * @param {string} [userAgent]\n * @return {boolean}\n */\nexport function isSafari(userAgent = navigator.userAgent) {\n return /safari/i.test(userAgent) && !/chrome|chromium/i.test(userAgent);\n}\n","var global = require('../internals/global');\nvar fails = require('../internals/fails');\nvar uncurryThis = require('../internals/function-uncurry-this');\nvar toString = require('../internals/to-string');\nvar trim = require('../internals/string-trim').trim;\nvar whitespaces = require('../internals/whitespaces');\n\nvar charAt = uncurryThis(''.charAt);\nvar n$ParseFloat = global.parseFloat;\nvar Symbol = global.Symbol;\nvar ITERATOR = Symbol && Symbol.iterator;\nvar FORCED = 1 / n$ParseFloat(whitespaces + '-0') !== -Infinity\n // MS Edge 18- broken with boxed symbols\n || (ITERATOR && !fails(function () { n$ParseFloat(Object(ITERATOR)); }));\n\n// `parseFloat` method\n// https://tc39.es/ecma262/#sec-parsefloat-string\nmodule.exports = FORCED ? function parseFloat(string) {\n var trimmedString = trim(toString(string));\n var result = n$ParseFloat(trimmedString);\n return result === 0 && charAt(trimmedString, 0) == '-' ? -0 : result;\n} : n$ParseFloat;\n","var 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","var $ = require('../internals/export');\nvar $parseFloat = require('../internals/number-parse-float');\n\n// `parseFloat` method\n// https://tc39.es/ecma262/#sec-parsefloat-string\n$({ global: true, forced: parseFloat != $parseFloat }, {\n parseFloat: $parseFloat\n});\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"],"names":["applyVariables","template","vars","overrides","possibleFilters","APPLY_FILTERS","replace","$0","$1","split","map","x","trim","varName","filterNames","value","n","reduce","acc","cur","toString","urlencode","encodeURIComponent","BookReader","window","DEFAULT_OPTIONS","enabled","fullDjvuXmlUrl","singlePageDjvuXmlUrl","Cache","maxSize","this","entries","entry","length","shift","push","TextSelectionPlugin","options","optionVariables","avoidTspans","isFirefox","pointerEventsOnParagraph","isSafari","djvuPagesPromise","svgParagraphElement","svgWordElement","insertNewlines","pageTextCache","maxWordRendered","$","ajax","type","url","dataType","error","e","then","res","xmlMap","parseXML","find","index","cachedEntry","response","pageIndex","xmlDoc","result","add","undefined","XMLpagesArr","$container","addEventListener","event","selection","document","getSelection","clipboardData","setData","preventDefault","svg","classList","remove","on","target","is","stopPropagation","one","off","textSelectingMode","removeAllRanges","defaultMode","$svg","each","i","s","interceptCopy","pageContainer","page","getPageText","XMLpage","totalWords","console","log","createSVGPageLayer","append","paragraph","words","paragSvg","createElementNS","setAttribute","style","pointerEvents","wordHeightArr","currWord","attr","parseFloat","left","bottom","right","wordHeight","wordTspan","textContent","appendChild","nextWord","leftNext","spaceTspan","createTextNode","sort","paragWordHeight","Math","floor","stopPageFlip","BookreaderWithTextSelection","Object","assign","plugins","textSelection","textSelectionPlugin","init","mode","constModeThumb","createTextLayer","isChrome","userAgent","navigator","vendor","test","global","fails","uncurryThis","whitespaces","charAt","n$ParseFloat","Symbol","ITERATOR","iterator","FORCED","module","exports","string","trimmedString","PROPER_FUNCTION_NAME","METHOD_NAME","name","$parseFloat","forced","$trim","proto","forcedStringTrimMethod"],"sourceRoot":""}
|