@internetarchive/bookreader 5.0.0-12-fixsorting-7 → 5.0.0-120

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.
Files changed (420) hide show
  1. package/BookReader/474.js +2 -0
  2. package/BookReader/474.js.map +1 -0
  3. package/BookReader/BookReader.css +670 -1190
  4. package/BookReader/bergamot-translator-worker.js +2966 -0
  5. package/BookReader/bergamot-translator-worker.wasm +0 -0
  6. package/BookReader/hypothesis/LICENSE +50 -0
  7. package/BookReader/hypothesis/README.md +55 -0
  8. package/BookReader/hypothesis/build/boot-template.js +1 -0
  9. package/BookReader/hypothesis/build/boot.js +1 -0
  10. package/BookReader/hypothesis/build/manifest.json +20 -0
  11. package/BookReader/hypothesis/build/scripts/annotator.bundle.js +199 -0
  12. package/BookReader/hypothesis/build/scripts/annotator.bundle.js.map +1 -0
  13. package/BookReader/hypothesis/build/scripts/sidebar.bundle.js +811 -0
  14. package/BookReader/hypothesis/build/scripts/sidebar.bundle.js.map +1 -0
  15. package/BookReader/hypothesis/build/scripts/ui-playground.bundle.js +437 -0
  16. package/BookReader/hypothesis/build/scripts/ui-playground.bundle.js.map +1 -0
  17. package/BookReader/hypothesis/build/styles/annotator.css +4 -0
  18. package/BookReader/hypothesis/build/styles/annotator.css.map +1 -0
  19. package/BookReader/hypothesis/build/styles/fonts/KaTeX_AMS-Regular.woff2 +0 -0
  20. package/BookReader/hypothesis/build/styles/fonts/KaTeX_Caligraphic-Bold.woff2 +0 -0
  21. package/BookReader/hypothesis/build/styles/fonts/KaTeX_Caligraphic-Regular.woff2 +0 -0
  22. package/BookReader/hypothesis/build/styles/fonts/KaTeX_Fraktur-Bold.woff2 +0 -0
  23. package/BookReader/hypothesis/build/styles/fonts/KaTeX_Fraktur-Regular.woff2 +0 -0
  24. package/BookReader/hypothesis/build/styles/fonts/KaTeX_Main-Bold.woff2 +0 -0
  25. package/BookReader/hypothesis/build/styles/fonts/KaTeX_Main-BoldItalic.woff2 +0 -0
  26. package/BookReader/hypothesis/build/styles/fonts/KaTeX_Main-Italic.woff2 +0 -0
  27. package/BookReader/hypothesis/build/styles/fonts/KaTeX_Main-Regular.woff2 +0 -0
  28. package/BookReader/hypothesis/build/styles/fonts/KaTeX_Math-BoldItalic.woff2 +0 -0
  29. package/BookReader/hypothesis/build/styles/fonts/KaTeX_Math-Italic.woff2 +0 -0
  30. package/BookReader/hypothesis/build/styles/fonts/KaTeX_SansSerif-Bold.woff2 +0 -0
  31. package/BookReader/hypothesis/build/styles/fonts/KaTeX_SansSerif-Italic.woff2 +0 -0
  32. package/BookReader/hypothesis/build/styles/fonts/KaTeX_SansSerif-Regular.woff2 +0 -0
  33. package/BookReader/hypothesis/build/styles/fonts/KaTeX_Script-Regular.woff2 +0 -0
  34. package/BookReader/hypothesis/build/styles/fonts/KaTeX_Size1-Regular.woff2 +0 -0
  35. package/BookReader/hypothesis/build/styles/fonts/KaTeX_Size2-Regular.woff2 +0 -0
  36. package/BookReader/hypothesis/build/styles/fonts/KaTeX_Size3-Regular.woff2 +0 -0
  37. package/BookReader/hypothesis/build/styles/fonts/KaTeX_Size4-Regular.woff2 +0 -0
  38. package/BookReader/hypothesis/build/styles/fonts/KaTeX_Typewriter-Regular.woff2 +0 -0
  39. package/BookReader/hypothesis/build/styles/highlights.css +2 -0
  40. package/BookReader/hypothesis/build/styles/highlights.css.map +1 -0
  41. package/BookReader/hypothesis/build/styles/katex.min.css +3 -0
  42. package/BookReader/hypothesis/build/styles/katex.min.css.map +1 -0
  43. package/BookReader/hypothesis/build/styles/pdfjs-overrides.css +14 -0
  44. package/BookReader/hypothesis/build/styles/pdfjs-overrides.css.map +1 -0
  45. package/BookReader/hypothesis/build/styles/sidebar.css +4 -0
  46. package/BookReader/hypothesis/build/styles/sidebar.css.map +1 -0
  47. package/BookReader/hypothesis/build/styles/ui-playground.css +4 -0
  48. package/BookReader/hypothesis/build/styles/ui-playground.css.map +1 -0
  49. package/BookReader/hypothesis/package.json +126 -0
  50. package/BookReader/ia-bookreader.js +1886 -0
  51. package/BookReader/{BookReader.js.LICENSE.txt → ia-bookreader.js.LICENSE.txt} +26 -20
  52. package/BookReader/ia-bookreader.js.map +1 -0
  53. package/BookReader/icons/1up.svg +1 -12
  54. package/BookReader/icons/2up.svg +1 -15
  55. package/BookReader/icons/advance.svg +3 -26
  56. package/BookReader/icons/chevron-right.svg +1 -1
  57. package/BookReader/icons/close-circle-dark.svg +1 -1
  58. package/BookReader/icons/close-circle.svg +1 -1
  59. package/BookReader/icons/fullscreen.svg +1 -17
  60. package/BookReader/icons/fullscreen_exit.svg +1 -17
  61. package/BookReader/icons/hamburger.svg +1 -15
  62. package/BookReader/icons/left-arrow.svg +1 -12
  63. package/BookReader/icons/magnify-minus.svg +1 -16
  64. package/BookReader/icons/magnify-plus.svg +1 -17
  65. package/BookReader/icons/magnify.svg +1 -15
  66. package/BookReader/icons/pause.svg +1 -23
  67. package/BookReader/icons/play.svg +1 -22
  68. package/BookReader/icons/playback-speed.svg +1 -34
  69. package/BookReader/icons/read-aloud.svg +1 -22
  70. package/BookReader/icons/review.svg +3 -22
  71. package/BookReader/icons/slider-toggle.svg +1 -0
  72. package/BookReader/icons/thumbnails.svg +1 -17
  73. package/BookReader/icons/voice.svg +1 -0
  74. package/BookReader/icons/volume-full.svg +1 -22
  75. package/BookReader/images/BRicons.svg +5 -94
  76. package/BookReader/images/books_graphic.svg +1 -177
  77. package/BookReader/images/hypothesis.ico +0 -0
  78. package/BookReader/images/icon_book.svg +1 -12
  79. package/BookReader/images/icon_bookmark.svg +1 -12
  80. package/BookReader/images/icon_experiment.svg +1 -0
  81. package/BookReader/images/icon_gear.svg +1 -14
  82. package/BookReader/images/icon_hamburger.svg +1 -20
  83. package/BookReader/images/icon_home.svg +1 -21
  84. package/BookReader/images/icon_info.svg +1 -11
  85. package/BookReader/images/icon_one_page.svg +1 -8
  86. package/BookReader/images/icon_pause.svg +1 -1
  87. package/BookReader/images/icon_play.svg +1 -1
  88. package/BookReader/images/icon_playback-rate.svg +1 -15
  89. package/BookReader/images/icon_search_button.svg +1 -8
  90. package/BookReader/images/icon_share.svg +1 -9
  91. package/BookReader/images/icon_skip-ahead.svg +1 -6
  92. package/BookReader/images/icon_skip-back.svg +2 -13
  93. package/BookReader/images/icon_speaker.svg +1 -18
  94. package/BookReader/images/icon_speaker_open.svg +1 -10
  95. package/BookReader/images/icon_thumbnails.svg +1 -12
  96. package/BookReader/images/icon_toc.svg +1 -5
  97. package/BookReader/images/icon_two_pages.svg +1 -9
  98. package/BookReader/images/marker_chap-off.svg +1 -11
  99. package/BookReader/images/marker_chap-on.svg +1 -11
  100. package/BookReader/images/marker_srch-on.svg +1 -11
  101. package/BookReader/images/translate.svg +1 -0
  102. package/BookReader/images/unviewable_page.png +0 -0
  103. package/BookReader/jquery-3.js +2 -0
  104. package/BookReader/jquery-3.js.LICENSE.txt +24 -0
  105. package/BookReader/plugins/plugin.archive_analytics.js +1 -172
  106. package/BookReader/plugins/plugin.archive_analytics.js.map +1 -1
  107. package/BookReader/plugins/plugin.autoplay.js +1 -165
  108. package/BookReader/plugins/plugin.autoplay.js.map +1 -1
  109. package/BookReader/plugins/plugin.chapters.js +19 -301
  110. package/BookReader/plugins/plugin.chapters.js.LICENSE.txt +1 -0
  111. package/BookReader/plugins/plugin.chapters.js.map +1 -1
  112. package/BookReader/plugins/plugin.experiments.js +3 -0
  113. package/BookReader/plugins/plugin.experiments.js.LICENSE.txt +1 -0
  114. package/BookReader/plugins/plugin.experiments.js.map +1 -0
  115. package/BookReader/plugins/plugin.iframe.js +1 -74
  116. package/BookReader/plugins/plugin.iframe.js.map +1 -1
  117. package/BookReader/plugins/plugin.iiif.js +2 -0
  118. package/BookReader/plugins/plugin.iiif.js.map +1 -0
  119. package/BookReader/plugins/plugin.resume.js +1 -368
  120. package/BookReader/plugins/plugin.resume.js.map +1 -1
  121. package/BookReader/plugins/plugin.search.js +2 -1385
  122. package/BookReader/plugins/plugin.search.js.LICENSE.txt +1 -0
  123. package/BookReader/plugins/plugin.search.js.map +1 -1
  124. package/BookReader/plugins/plugin.text_selection.js +2 -1080
  125. package/BookReader/plugins/plugin.text_selection.js.LICENSE.txt +1 -0
  126. package/BookReader/plugins/plugin.text_selection.js.map +1 -1
  127. package/BookReader/plugins/plugin.translate.js +3 -0
  128. package/BookReader/plugins/plugin.translate.js.LICENSE.txt +1 -0
  129. package/BookReader/plugins/plugin.translate.js.map +1 -0
  130. package/BookReader/plugins/plugin.tts.js +2 -9193
  131. package/BookReader/plugins/plugin.tts.js.LICENSE.txt +2 -0
  132. package/BookReader/plugins/plugin.tts.js.map +1 -1
  133. package/BookReader/plugins/plugin.url.js +1 -269
  134. package/BookReader/plugins/plugin.url.js.map +1 -1
  135. package/BookReader/plugins/plugin.vendor-fullscreen.js +1 -379
  136. package/BookReader/plugins/plugin.vendor-fullscreen.js.map +1 -1
  137. package/BookReader/plugins/translator-worker.js +2 -0
  138. package/BookReader/plugins/translator-worker.js.map +1 -0
  139. package/BookReader/silence.mp3 +0 -0
  140. package/BookReader/translator-worker.js +475 -0
  141. package/BookReader/webcomponents-bundle.js +3 -0
  142. package/BookReader/webcomponents-bundle.js.LICENSE.txt +9 -0
  143. package/BookReader/webcomponents-bundle.js.map +1 -0
  144. package/README.md +17 -4
  145. package/dist/esm/ia-bookreader.js +3 -0
  146. package/dist/esm/ia-bookreader.js.LICENSE.txt +17 -0
  147. package/dist/esm/ia-bookreader.js.map +1 -0
  148. package/dist/esm/plugins/plugin.archive_analytics.js +2 -0
  149. package/dist/esm/plugins/plugin.archive_analytics.js.map +1 -0
  150. package/dist/esm/plugins/plugin.autoplay.js +2 -0
  151. package/dist/esm/plugins/plugin.autoplay.js.map +1 -0
  152. package/dist/esm/plugins/plugin.chapters.js +2 -0
  153. package/dist/esm/plugins/plugin.chapters.js.map +1 -0
  154. package/dist/esm/plugins/plugin.experiments.js +2 -0
  155. package/dist/esm/plugins/plugin.experiments.js.map +1 -0
  156. package/dist/esm/plugins/plugin.iframe.js +2 -0
  157. package/dist/esm/plugins/plugin.iframe.js.map +1 -0
  158. package/dist/esm/plugins/plugin.iiif.js +2 -0
  159. package/dist/esm/plugins/plugin.iiif.js.map +1 -0
  160. package/dist/esm/plugins/plugin.resume.js +2 -0
  161. package/dist/esm/plugins/plugin.resume.js.map +1 -0
  162. package/dist/esm/plugins/plugin.search.js +2 -0
  163. package/dist/esm/plugins/plugin.search.js.map +1 -0
  164. package/dist/esm/plugins/plugin.text_selection.js +2 -0
  165. package/dist/esm/plugins/plugin.text_selection.js.map +1 -0
  166. package/dist/esm/plugins/plugin.translate.js +2 -0
  167. package/dist/esm/plugins/plugin.translate.js.map +1 -0
  168. package/dist/esm/plugins/plugin.tts.js +2 -0
  169. package/dist/esm/plugins/plugin.tts.js.map +1 -0
  170. package/dist/esm/plugins/plugin.url.js +2 -0
  171. package/dist/esm/plugins/plugin.url.js.map +1 -0
  172. package/dist/esm/plugins/plugin.vendor-fullscreen.js +2 -0
  173. package/dist/esm/plugins/plugin.vendor-fullscreen.js.map +1 -0
  174. package/jsconfig.json +18 -0
  175. package/package.json +113 -71
  176. package/src/BookReader/BookModel.js +92 -46
  177. package/src/BookReader/DragScrollable.js +233 -0
  178. package/src/BookReader/ImageCache.js +49 -16
  179. package/src/BookReader/Mode1Up.js +66 -365
  180. package/src/BookReader/Mode1UpLit.js +392 -0
  181. package/src/BookReader/Mode2Up.js +87 -1315
  182. package/src/BookReader/Mode2UpLit.js +786 -0
  183. package/src/BookReader/ModeAbstract.js +43 -0
  184. package/src/BookReader/ModeCoordinateSpace.js +29 -0
  185. package/src/BookReader/ModeSmoothZoom.js +312 -0
  186. package/src/BookReader/ModeThumb.js +29 -15
  187. package/src/BookReader/Navbar/Navbar.js +204 -84
  188. package/src/BookReader/PageContainer.js +120 -23
  189. package/src/BookReader/ReduceSet.js +2 -2
  190. package/src/BookReader/Toolbar/Toolbar.js +18 -40
  191. package/src/BookReader/events.js +3 -3
  192. package/src/BookReader/options.js +105 -18
  193. package/src/BookReader/utils/HTMLDimensionsCacher.js +44 -0
  194. package/src/BookReader/utils/ScrollClassAdder.js +31 -0
  195. package/src/BookReader/utils/SelectionObserver.js +72 -0
  196. package/src/BookReader/utils/classes.js +1 -1
  197. package/src/BookReader/utils.js +136 -12
  198. package/src/BookReader.js +732 -1231
  199. package/src/BookReaderPlugin.js +52 -0
  200. package/src/assets/icons/magnify-minus.svg +3 -7
  201. package/src/assets/icons/magnify-plus.svg +3 -7
  202. package/src/assets/icons/slider-toggle.svg +1 -0
  203. package/src/assets/icons/voice.svg +1 -0
  204. package/src/assets/images/hypothesis.ico +0 -0
  205. package/src/assets/images/icon_experiment.svg +1 -0
  206. package/src/assets/images/translate.svg +1 -0
  207. package/src/assets/images/unviewable_page.png +0 -0
  208. package/src/assets/silence.mp3 +0 -0
  209. package/src/css/BookReader.scss +1 -5
  210. package/src/css/_BRBookmarks.scss +1 -1
  211. package/src/css/_BRComponent.scss +1 -1
  212. package/src/css/_BRicon.scss +8 -2
  213. package/src/css/_BRmain.scss +16 -3
  214. package/src/css/_BRnav.scss +74 -70
  215. package/src/css/_BRpages.scss +174 -42
  216. package/src/css/_BRsearch.scss +69 -30
  217. package/src/css/_BRtoolbar.scss +5 -5
  218. package/src/css/_TextSelection.scss +249 -25
  219. package/src/css/_colorbox.scss +2 -2
  220. package/src/css/_controls.scss +24 -7
  221. package/src/css/_icons.scss +8 -1
  222. package/src/{BookNavigator/assets → css}/button-base.js +2 -2
  223. package/src/css/icon_checkmark.js +9 -0
  224. package/src/css/sharedStyles.js +15 -0
  225. package/src/ia-bookreader/downloads/downloads-provider.js +81 -0
  226. package/src/{BookNavigator → ia-bookreader}/downloads/downloads.js +25 -5
  227. package/src/ia-bookreader/ia-bookreader.js +686 -0
  228. package/src/ia-bookreader/sharing.js +27 -0
  229. package/src/ia-bookreader/viewable-files.js +98 -0
  230. package/src/{BookNavigator → ia-bookreader}/visual-adjustments/visual-adjustments-provider.js +17 -17
  231. package/src/{BookNavigator → ia-bookreader}/visual-adjustments/visual-adjustments.js +75 -67
  232. package/src/{BookNavigator → plugins}/bookmarks/bookmark-button.js +4 -3
  233. package/src/{BookNavigator/assets → plugins/bookmarks}/bookmark-colors.js +1 -1
  234. package/src/{BookNavigator → plugins}/bookmarks/bookmark-edit.js +43 -31
  235. package/src/{BookNavigator → plugins}/bookmarks/bookmarks-list.js +48 -49
  236. package/src/{BookNavigator → plugins}/bookmarks/bookmarks-loginCTA.js +3 -3
  237. package/src/plugins/bookmarks/bookmarks-provider.js +63 -0
  238. package/src/{BookNavigator → plugins/bookmarks}/delete-modal-actions.js +1 -1
  239. package/src/{BookNavigator → plugins}/bookmarks/ia-bookmarks.js +117 -68
  240. package/src/plugins/plugin.archive_analytics.js +84 -78
  241. package/src/plugins/plugin.autoplay.js +99 -104
  242. package/src/plugins/plugin.chapters.js +323 -205
  243. package/src/plugins/plugin.experiments.js +375 -0
  244. package/src/plugins/plugin.iframe.js +36 -37
  245. package/src/plugins/plugin.iiif.js +147 -0
  246. package/src/plugins/plugin.resume.js +54 -51
  247. package/src/plugins/plugin.text_selection.js +464 -219
  248. package/src/plugins/plugin.vendor-fullscreen.js +5 -5
  249. package/src/plugins/search/plugin.search.js +347 -397
  250. package/src/{BookNavigator → plugins}/search/search-provider.js +59 -27
  251. package/src/{BookNavigator → plugins}/search/search-results.js +105 -76
  252. package/src/plugins/search/utils.js +50 -0
  253. package/src/plugins/search/view.js +51 -69
  254. package/src/plugins/translate/TranslationManager.js +164 -0
  255. package/src/plugins/translate/plugin.translate.js +559 -0
  256. package/src/plugins/tts/AbstractTTSEngine.js +78 -49
  257. package/src/plugins/tts/FestivalTTSEngine.js +20 -30
  258. package/src/plugins/tts/PageChunk.js +117 -23
  259. package/src/plugins/tts/PageChunkIterator.js +11 -17
  260. package/src/plugins/tts/WebTTSEngine.js +132 -92
  261. package/src/plugins/tts/plugin.tts.js +341 -351
  262. package/src/plugins/tts/utils.js +76 -67
  263. package/src/plugins/url/UrlPlugin.js +213 -0
  264. package/src/plugins/{plugin.url.js → url/plugin.url.js} +54 -18
  265. package/src/util/TextSelectionManager.js +1464 -0
  266. package/src/util/browserSniffing.js +42 -1
  267. package/src/util/cache.js +20 -0
  268. package/src/util/docCookies.js +21 -2
  269. package/src/util/dom.js +88 -0
  270. package/src/util/generators.js +89 -0
  271. package/src/util/lit.js +15 -0
  272. package/src/util/strings.js +11 -0
  273. package/.babelrc +0 -12
  274. package/.dependabot/config.yml +0 -6
  275. package/.eslintrc.js +0 -50
  276. package/.gitattributes +0 -2
  277. package/.github/ISSUE_TEMPLATE/bug.md +0 -32
  278. package/.github/ISSUE_TEMPLATE/feature-request.md +0 -30
  279. package/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md +0 -15
  280. package/.github/workflows/node.js.yml +0 -37
  281. package/.github/workflows/npm-publish.yml +0 -47
  282. package/.testcaferc.json +0 -5
  283. package/BookReader/BookReader.js +0 -21613
  284. package/BookReader/BookReader.js.map +0 -1
  285. package/BookReader/bookreader-component-bundle.js +0 -14497
  286. package/BookReader/bookreader-component-bundle.js.LICENSE.txt +0 -38
  287. package/BookReader/bookreader-component-bundle.js.map +0 -1
  288. package/BookReader/jquery-1.10.1.js +0 -108
  289. package/BookReader/jquery-1.10.1.js.LICENSE.txt +0 -24
  290. package/BookReader/plugins/plugin.menu_toggle.js +0 -369
  291. package/BookReader/plugins/plugin.menu_toggle.js.map +0 -1
  292. package/BookReader/plugins/plugin.mobile_nav.js +0 -335
  293. package/BookReader/plugins/plugin.mobile_nav.js.map +0 -1
  294. package/BookReaderDemo/BookReaderDemo.css +0 -41
  295. package/BookReaderDemo/BookReaderJSAdvanced.js +0 -115
  296. package/BookReaderDemo/BookReaderJSAutoplay.js +0 -56
  297. package/BookReaderDemo/BookReaderJSSimple.js +0 -55
  298. package/BookReaderDemo/IIIFBookReader.js +0 -207
  299. package/BookReaderDemo/assets/v5/Bookreader-logo-cool-grad.svg +0 -1
  300. package/BookReaderDemo/assets/v5/Bookreader-logo-flat.svg +0 -1
  301. package/BookReaderDemo/assets/v5/Bookreader-logo-hex-cool-grad.png +0 -0
  302. package/BookReaderDemo/assets/v5/Bookreader-logo-hex-flat.png +0 -0
  303. package/BookReaderDemo/assets/v5/Bookreader-logo-lines.png +0 -0
  304. package/BookReaderDemo/assets/v5/Bookreader-logo-lines.svg +0 -1
  305. package/BookReaderDemo/assets/v5/Bookreader-logo-warm.svg +0 -1
  306. package/BookReaderDemo/assets/v5/bookreader-logo-renders@1x.png +0 -0
  307. package/BookReaderDemo/assets/v5/bookreader-logo-renders@2x.png +0 -0
  308. package/BookReaderDemo/assets/v5/bookreader-v5-screenshot.png +0 -0
  309. package/BookReaderDemo/bookreader-template-bundle.js +0 -7178
  310. package/BookReaderDemo/demo-advanced.html +0 -33
  311. package/BookReaderDemo/demo-autoplay.html +0 -38
  312. package/BookReaderDemo/demo-embed-iframe-src.html +0 -84
  313. package/BookReaderDemo/demo-embed.html +0 -26
  314. package/BookReaderDemo/demo-fullscreen-mobile.html +0 -36
  315. package/BookReaderDemo/demo-fullscreen.html +0 -33
  316. package/BookReaderDemo/demo-iiif.html +0 -34
  317. package/BookReaderDemo/demo-iiif.js +0 -26
  318. package/BookReaderDemo/demo-internetarchive.html +0 -74
  319. package/BookReaderDemo/demo-multiple.html +0 -43
  320. package/BookReaderDemo/demo-plugin-menu-toggle.html +0 -34
  321. package/BookReaderDemo/demo-preview-pages.html +0 -1092
  322. package/BookReaderDemo/demo-simple.html +0 -34
  323. package/BookReaderDemo/demo-vendor-fullscreen.html +0 -36
  324. package/BookReaderDemo/immersion-1up.html +0 -64
  325. package/BookReaderDemo/immersion-mode.html +0 -35
  326. package/BookReaderDemo/toggle_controls.html +0 -53
  327. package/BookReaderDemo/view_mode.html +0 -39
  328. package/BookReaderDemo/viewmode-cycle.html +0 -41
  329. package/CHANGELOG.md +0 -499
  330. package/CONTRIBUTING.md +0 -7
  331. package/codecov.yml +0 -17
  332. package/index.html +0 -31
  333. package/karma.conf.js +0 -23
  334. package/screenshot.png +0 -0
  335. package/scripts/postversion.js +0 -10
  336. package/scripts/preversion.js +0 -14
  337. package/scripts/version.js +0 -26
  338. package/src/BookNavigator/BookModel.js +0 -14
  339. package/src/BookNavigator/BookNavigator.js +0 -459
  340. package/src/BookNavigator/assets/book-loader.js +0 -27
  341. package/src/BookNavigator/assets/icon_checkmark.js +0 -6
  342. package/src/BookNavigator/assets/icon_close.js +0 -3
  343. package/src/BookNavigator/assets/icon_sort_ascending.js +0 -5
  344. package/src/BookNavigator/assets/icon_sort_descending.js +0 -5
  345. package/src/BookNavigator/assets/icon_sort_neutral.js +0 -5
  346. package/src/BookNavigator/assets/icon_volumes.js +0 -11
  347. package/src/BookNavigator/bookmarks/bookmarks-provider.js +0 -53
  348. package/src/BookNavigator/br-fullscreen-mgr.js +0 -83
  349. package/src/BookNavigator/downloads/downloads-provider.js +0 -66
  350. package/src/BookNavigator/search/a-search-result.js +0 -55
  351. package/src/BookNavigator/volumes/volumes-provider.js +0 -83
  352. package/src/BookNavigator/volumes/volumes.js +0 -178
  353. package/src/BookReader/DebugConsole.js +0 -54
  354. package/src/BookReaderComponent/BookReaderComponent.js +0 -112
  355. package/src/ItemNavigator/ItemNavigator.js +0 -376
  356. package/src/ItemNavigator/providers/sharing.js +0 -33
  357. package/src/css/_MobileNav.scss +0 -194
  358. package/src/dragscrollable-br.js +0 -261
  359. package/src/plugins/menu_toggle/plugin.menu_toggle.js +0 -324
  360. package/src/plugins/plugin.mobile_nav.js +0 -287
  361. package/tests/BookReader/BookModel.test.js +0 -312
  362. package/tests/BookReader/BookReaderPublicFunctions.test.js +0 -171
  363. package/tests/BookReader/DebugConsole.test.js +0 -25
  364. package/tests/BookReader/ImageCache.test.js +0 -150
  365. package/tests/BookReader/Mode1Up.test.js +0 -164
  366. package/tests/BookReader/Mode2Up.test.js +0 -247
  367. package/tests/BookReader/Navbar/Navbar.test.js +0 -169
  368. package/tests/BookReader/PageContainer.test.js +0 -115
  369. package/tests/BookReader/ReduceSet.test.js +0 -38
  370. package/tests/BookReader/Toolbar/Toolbar.test.js +0 -26
  371. package/tests/BookReader/utils/classes.test.js +0 -88
  372. package/tests/BookReader/utils.test.js +0 -109
  373. package/tests/BookReader.options.test.js +0 -39
  374. package/tests/BookReader.test.js +0 -301
  375. package/tests/e2e/README.md +0 -75
  376. package/tests/e2e/autoplay.test.js +0 -13
  377. package/tests/e2e/base.test.js +0 -35
  378. package/tests/e2e/helpers/base.js +0 -263
  379. package/tests/e2e/helpers/debug.js +0 -13
  380. package/tests/e2e/helpers/desktopSearch.js +0 -72
  381. package/tests/e2e/helpers/mobileSearch.js +0 -85
  382. package/tests/e2e/helpers/mockSearch.js +0 -93
  383. package/tests/e2e/helpers/rightToLeft.js +0 -29
  384. package/tests/e2e/ia-production/ia-prod-base.js +0 -17
  385. package/tests/e2e/models/BookReader.js +0 -11
  386. package/tests/e2e/models/Navigation.js +0 -56
  387. package/tests/e2e/rightToLeft.test.js +0 -20
  388. package/tests/e2e/viewmode.test.js +0 -37
  389. package/tests/karma/BookNavigator/book-navigator.test.js +0 -139
  390. package/tests/karma/BookNavigator/bookmarks/bookmark-edit.test.js +0 -133
  391. package/tests/karma/BookNavigator/bookmarks/bookmarks-list.test.js +0 -222
  392. package/tests/karma/BookNavigator/search/search-provider.test.js +0 -23
  393. package/tests/karma/BookNavigator/search/search-results.test.js +0 -240
  394. package/tests/karma/BookNavigator/sharing/sharing-provider.test.js +0 -40
  395. package/tests/karma/BookNavigator/visual-adjustments.test.js +0 -201
  396. package/tests/karma/BookNavigator/volumes/volumes-provider.test.js +0 -141
  397. package/tests/karma/BookNavigator/volumes/volumes.test.js +0 -98
  398. package/tests/plugins/menu_toggle/plugin.menu_toggle.test.js +0 -68
  399. package/tests/plugins/plugin.archive_analytics.test.js +0 -23
  400. package/tests/plugins/plugin.autoplay.test.js +0 -52
  401. package/tests/plugins/plugin.chapters.test.js +0 -130
  402. package/tests/plugins/plugin.iframe.test.js +0 -42
  403. package/tests/plugins/plugin.mobile_nav.test.js +0 -66
  404. package/tests/plugins/plugin.resume.test.js +0 -98
  405. package/tests/plugins/plugin.text_selection.test.js +0 -203
  406. package/tests/plugins/plugin.url.test.js +0 -129
  407. package/tests/plugins/plugin.vendor-fullscreen.test.js +0 -65
  408. package/tests/plugins/search/plugin.search.test.js +0 -173
  409. package/tests/plugins/search/plugin.search.view.test.js +0 -106
  410. package/tests/plugins/tts/AbstractTTSEngine.test.js +0 -153
  411. package/tests/plugins/tts/FestivalTTSEngine.test.js +0 -59
  412. package/tests/plugins/tts/PageChunk.test.js +0 -57
  413. package/tests/plugins/tts/PageChunkIterator.test.js +0 -179
  414. package/tests/plugins/tts/WebTTSEngine.test.js +0 -126
  415. package/tests/plugins/tts/utils.test.js +0 -133
  416. package/tests/util/browserSniffing.test.js +0 -56
  417. package/tests/util/docCookies.test.js +0 -15
  418. package/tests/util/strings.test.js +0 -63
  419. package/tests/utils.js +0 -42
  420. package/webpack.config.js +0 -86
@@ -1,91 +1,100 @@
1
- import langs from 'iso-language-codes/js/data.js';
1
+ // @ts-check
2
+ import langs from 'iso-language-codes';
2
3
 
3
- /**
4
- * Convert a EventTarget style event into a promise
5
- * @param {EventTarget} target
6
- * @param {string} eventType
7
- * @return {Promise<Event>}
8
- */
9
- export function promisifyEvent(target, eventType) {
10
- return new Promise(res => {
11
- const resolver = ev => {
12
- target.removeEventListener(eventType, resolver);
13
- res(ev);
14
- };
15
- target.addEventListener(eventType, resolver);
16
- });
17
- }
18
-
19
- /**
20
- * Use regex to approximate word count in a string
21
- * @param {string} text
22
- * @return {number}
23
- */
24
- export function approximateWordCount(text) {
25
- const m = text.match(/\S+/g);
26
- return m ? m.length : 0;
27
- }
28
-
29
- /**
30
- * Waits the provided number of ms and then resolves with a promise
31
- * @param {number} ms
32
- * @return {Promise}
33
- */
34
- export function sleep(ms) {
35
- return new Promise(res => setTimeout(res, ms));
36
- }
37
-
38
- /**
39
- * Checks whether the current browser is on android
40
- * @param {string} [userAgent]
41
- * @return {boolean}
42
- */
43
- export function isAndroid(userAgent = navigator.userAgent) {
44
- return /android/i.test(userAgent);
45
- }
4
+ /** @type {{[lang: string]: string}} */
5
+ // Handle odd one-off language pairs that might show up over time
6
+ const specialLangs = {
7
+ "zh-hans": "中文 (Zhōngwén)",
8
+ };
46
9
 
47
10
  /**
48
11
  * @typedef {string} ISO6391
49
12
  * Language code in ISO 639-1 format. e.g. en, fr, zh
50
13
  **/
51
14
 
52
- /** Each lang is an array, with each index mapping to a different property */
53
- const COLUMN_TO_LANG_INDEX = {
54
- 'Name': 0,
55
- 'Endonym': 1,
56
- 'ISO 639-1': 2,
57
- 'ISO 639-2/T': 3,
58
- 'ISO 639-2/B': 4
59
- };
60
-
61
15
  /**
62
16
  * @param {string} language in some format
63
17
  * @return {ISO6391?}
64
18
  */
65
19
  export function toISO6391(language) {
66
20
  if (!language) return null;
67
- language = language.toLowerCase();
21
+ language = language.toLocaleLowerCase();
22
+ if (specialLangs[language]) {
23
+ return language;
24
+ }
25
+ const codeObj = (
26
+ findLanguage(language, ['iso639_1']) ||
27
+ findLanguage(language, ['iso639_2T']) ||
28
+ findLanguage(language, ['iso639_2B', 'name', 'nativeName'])
29
+ );
30
+ if (codeObj) return codeObj.iso639_1;
31
+ return null;
32
+ }
68
33
 
69
- return searchForISO6391(language, ['ISO 639-1']) ||
70
- searchForISO6391(language, ['ISO 639-2/B']) ||
71
- searchForISO6391(language, ['ISO 639-2/T', 'Endonym', 'Name']);
34
+ /**
35
+ *
36
+ * @param {string} language
37
+ * @returns {string | null}
38
+ */
39
+ export function toNativeName(language) {
40
+ if (!language) return null;
41
+ language = language.toLocaleLowerCase();
42
+ if (specialLangs[language]) {
43
+ return specialLangs[language];
44
+ }
45
+ const codeObj = (
46
+ findLanguage(language, ['iso639_1']) ||
47
+ findLanguage(language, ['iso639_2T']) ||
48
+ findLanguage(language, ['iso639_2B', 'name', 'nativeName'])
49
+ );
50
+ if (codeObj?.nativeName) return codeObj.nativeName.split(", ")[0];
51
+ return null;
72
52
  }
73
53
 
54
+ /** @typedef {import('iso-language-codes').Code} Code */
55
+
74
56
  /**
75
- * Searches for the given long in the given columns.
76
57
  * @param {string} language
77
- * @param {Array<keyof COLUMN_TO_LANG_INDEX>} columnsToSearch
78
- * @return {ISO6391?}
58
+ * @param {Array<'iso639_1' | 'iso639_2T' | 'iso639_2B' | 'nativeName' | 'name'>} fields
59
+ * @returns {Code | null}
79
60
  */
80
- function searchForISO6391(language, columnsToSearch) {
81
- for (let i = 0; i < langs.length; i++) {
82
- for (let colI = 0; colI < columnsToSearch.length; colI++) {
83
- const column = columnsToSearch[colI];
84
- const columnValue = langs[i][COLUMN_TO_LANG_INDEX[column]];
85
- if (columnValue.split(', ').map(x => x.toLowerCase()).indexOf(language) != -1) {
86
- return langs[i][COLUMN_TO_LANG_INDEX['ISO 639-1']];
61
+ function findLanguage(language, fields) {
62
+ if (!language) return null;
63
+ language = language.toLowerCase();
64
+ for (const lang of langs) {
65
+ for (const codeType of fields) {
66
+ if (lang[codeType]?.toLowerCase().split(", ").includes(language)) {
67
+ return lang;
87
68
  }
88
69
  }
89
70
  }
90
71
  return null;
91
72
  }
73
+
74
+ /**
75
+ * Checks whether the current browser supports localStorage or
76
+ * if the current context has access to it.
77
+ * @return {boolean}
78
+ */
79
+ export function hasLocalStorage() {
80
+ try {
81
+ return !!window.localStorage;
82
+ } catch (e) {
83
+ // Will throw in sandboxed iframe
84
+ // DOMException: Window.localStorage getter: Forbidden in a sandboxed document without the 'allow-same-origin' flag.
85
+ return false;
86
+ }
87
+ }
88
+
89
+ export const DEBUG_READ_ALOUD = location.toString().indexOf('_debugReadAloud=true') != -1;
90
+
91
+ export async function checkIfFiresPause() {
92
+ // Pick some random text so that if it accidentally speaks, it's not too annoying
93
+ const u = new SpeechSynthesisUtterance("Loading");
94
+ let calledPause = false;
95
+ u.addEventListener('pause', () => calledPause = true);
96
+ speechSynthesis.speak(u);
97
+ await new Promise(res => setTimeout(res, 10));
98
+ speechSynthesis.pause();
99
+ return calledPause;
100
+ }
@@ -0,0 +1,213 @@
1
+ /**
2
+ * @typedef {Object} UrlSchemaEntry
3
+ * @property {string} name
4
+ * @property {'path' | 'query_param'} position
5
+ * @property {string} [default]
6
+ * @property {string} [deprecated_for]
7
+ * @property {boolean} [readOnly] - If true, the param is read from the URL but never written back
8
+ */
9
+
10
+ export class UrlPlugin {
11
+ constructor(options = {}) {
12
+ this.bookReaderOptions = options;
13
+
14
+ // the canonical order of elements is important in the path and query string
15
+ /** @type {UrlSchemaEntry[]} */
16
+ this.urlSchema = [
17
+ { name: 'page', position: 'path', default: 'n0' },
18
+ { name: 'mode', position: 'path', default: '2up' },
19
+ { name: 'search', position: 'path', deprecated_for: 'q' },
20
+ { name: 'q', position: 'query_param' },
21
+ { name: 'sort', position: 'query_param' },
22
+ { name: 'view', position: 'query_param' },
23
+ { name: 'admin', position: 'query_param' },
24
+ { name: 'focus', position: 'query_param', readOnly: true },
25
+ ];
26
+
27
+ this.urlState = {};
28
+ this.urlMode = this.bookReaderOptions.urlMode || 'hash';
29
+ this.urlHistoryBasePath = this.bookReaderOptions.urlHistoryBasePath || '/';
30
+ this.urlLocationPollId = null;
31
+ this.oldLocationHash = null;
32
+ this.oldUserHash = null;
33
+ }
34
+
35
+ /**
36
+ * Parse JSON object URL state to string format
37
+ * Arrange path names in an order that it is positioned on the urlSchema
38
+ * @param {Object} urlState
39
+ * @returns {string}
40
+ */
41
+ urlStateToUrlString(urlState) {
42
+ const searchParams = new URLSearchParams();
43
+ const pathParams = {};
44
+
45
+ Object.keys(urlState).forEach(key => {
46
+ let schema = this.urlSchema.find(schema => schema.name === key);
47
+ if (schema?.deprecated_for) {
48
+ schema = this.urlSchema.find(schemaKey => schemaKey.name === schema.deprecated_for);
49
+ }
50
+ if (schema?.readOnly) return;
51
+ if (schema?.position == 'path') {
52
+ pathParams[schema?.name] = urlState[key];
53
+ } else {
54
+ searchParams.append(schema?.name || key, urlState[key]);
55
+ }
56
+ });
57
+
58
+ const strPathParams = this.urlSchema
59
+ .filter(s => s.position == 'path')
60
+ .map(schema => pathParams[schema.name] ? `${schema.name}/${encodeURIComponent(pathParams[schema.name])}` : '')
61
+ .join('/');
62
+
63
+ // replace consecutive slashes with a single slash + remove trailing slashes
64
+ const strStrippedTrailingSlash = `${strPathParams.replace(/\/+/g, '/').replace(/\/+$/, '')}`;
65
+ const concatenatedPath = `${strStrippedTrailingSlash}?${searchParams.toString()}`;
66
+ return searchParams.toString() ? concatenatedPath : `${strStrippedTrailingSlash}`;
67
+ }
68
+
69
+ /**
70
+ * Parse string URL and add it in the current urlState
71
+ * Example:
72
+ * /page/n7/mode/2up => {page: 'n7', mode: '2up'}
73
+ * /page/n7/mode/2up/search/hello => {page: 'n7', mode: '2up', q: 'hello'}
74
+ * @param {string} urlString
75
+ * @returns {object}
76
+ */
77
+ urlStringToUrlState(urlString) {
78
+ const urlState = {};
79
+
80
+ // Fetch searchParams from given {str}
81
+ // Note: whole URL path is needed for URL parsing
82
+ const urlPath = new URL(urlString, 'http://example.com');
83
+ const urlSearchParamsObj = Object.fromEntries(urlPath.searchParams.entries());
84
+ const splitUrlMatches = urlPath.pathname.match(/[^\\/]+\/[^\\/]+/g);
85
+ const urlStrSplitSlashObj = splitUrlMatches ? Object.fromEntries(splitUrlMatches.map(x => x.split('/'))) : {};
86
+
87
+ const doesKeyExists = (_object, _key) => {
88
+ return Object.keys(_object).some(value => value == _key);
89
+ };
90
+
91
+ // Add path objects to urlState
92
+ this.urlSchema
93
+ .filter(schema => schema.position == 'path')
94
+ .forEach(schema => {
95
+ const hasPropertyKey = doesKeyExists(urlStrSplitSlashObj, schema.name);
96
+ const hasDeprecatedKey = doesKeyExists(schema, 'deprecated_for') && hasPropertyKey;
97
+
98
+ // Not in the URL
99
+ if (!hasPropertyKey && !hasDeprecatedKey) {
100
+ return;
101
+ }
102
+
103
+ const urlStateParam = hasDeprecatedKey ? schema.deprecated_for : schema.name;
104
+ urlState[urlStateParam] = decodeURIComponent(urlStrSplitSlashObj[schema.name]);
105
+ });
106
+
107
+ // Add searchParams to urlState
108
+ Object.entries(urlSearchParamsObj).forEach(([key, value]) => {
109
+ urlState[key] = value;
110
+ });
111
+
112
+ return urlState;
113
+ }
114
+
115
+ /**
116
+ * Add or update key-value to the urlState
117
+ * @param {string} key
118
+ * @param {string} val
119
+ */
120
+ setUrlParam(key, value) {
121
+ this.urlState[key] = value;
122
+
123
+ this.pushToAddressBar();
124
+ }
125
+
126
+ /**
127
+ * Delete key-value to the urlState
128
+ * @param {string} key
129
+ */
130
+ removeUrlParam(key) {
131
+ delete this.urlState[key];
132
+
133
+ this.pushToAddressBar();
134
+ }
135
+
136
+ /**
137
+ * Get key-value from the urlState
138
+ * @param {string} key
139
+ * @return {string}
140
+ */
141
+ getUrlParam(key) {
142
+ return this.urlState[key];
143
+ }
144
+
145
+ /**
146
+ * Push URL params to addressbar
147
+ */
148
+ pushToAddressBar() {
149
+ const urlStrPath = this.urlStateToUrlString(this.urlState);
150
+ const concatenatedPath = urlStrPath !== '/' ? urlStrPath : '';
151
+ if (this.urlMode == 'history') {
152
+ if (!window.history || !window.history.replaceState) {
153
+ this.options.urlMode = 'hash';
154
+ } else {
155
+ const newUrlPath = `${this.urlHistoryBasePath}${concatenatedPath}`.trim().replace(/(\/+)/g, '/');
156
+ try {
157
+ window.history.replaceState({}, null, newUrlPath);
158
+ } catch (e) {
159
+ // DOMException on Chrome when in sandboxed iframe
160
+ this.urlMode = 'hash';
161
+ }
162
+ }
163
+ }
164
+
165
+ if (this.urlMode == 'hash') {
166
+ // Built from location.href so a <base href> on the page can't change
167
+ // the pathname, and replace() so page flips don't add history entries.
168
+ const [baseHref] = window.location.href.split('#');
169
+ window.location.replace(`${baseHref}#${concatenatedPath}`);
170
+ }
171
+ this.oldLocationHash = urlStrPath;
172
+ }
173
+
174
+ /**
175
+ * Get the url and check if it has changed
176
+ * If it was changeed, update the urlState
177
+ */
178
+ listenForHashChanges() {
179
+ this.oldLocationHash = this.getHash();
180
+ if (this.urlLocationPollId) {
181
+ clearInterval(this.urlLocationPollId);
182
+ this.urlLocationPollId = null;
183
+ }
184
+
185
+ // check if the URL changes
186
+ const updateHash = () => {
187
+ const newFragment = this.getHash();
188
+ const hasFragmentChange = newFragment != this.oldLocationHash;
189
+
190
+ if (!hasFragmentChange) { return; }
191
+
192
+ this.urlState = this.urlStringToUrlState(newFragment);
193
+ };
194
+ this.urlLocationPollId = setInterval(updateHash, 500);
195
+ }
196
+
197
+ /**
198
+ * Will read either the hash or URL and return the bookreader fragment
199
+ */
200
+ pullFromAddressBar(location = window.location) {
201
+ const path = this.urlMode === 'history'
202
+ ? (location.pathname.substr(this.urlHistoryBasePath.length) + location.search)
203
+ : location.hash.substr(1);
204
+ this.urlState = this.urlStringToUrlState(path);
205
+ }
206
+
207
+ /**
208
+ * Get the hash out of the current URL
209
+ */
210
+ getHash() {
211
+ return window.location.hash.slice(1);
212
+ }
213
+ }
@@ -1,4 +1,7 @@
1
1
  /* global BookReader */
2
+
3
+ import { UrlPlugin } from "./UrlPlugin.js";
4
+
2
5
  /**
3
6
  * Plugin for URL management in BookReader
4
7
  * Note read more about the url "fragment" here:
@@ -22,7 +25,7 @@ jQuery.extend(BookReader.defaultOptions, {
22
25
  urlHistoryBasePath: '/',
23
26
 
24
27
  /** Only these params will be reflected onto the URL */
25
- urlTrackedParams: ['page', 'search', 'mode', 'region', 'highlight'],
28
+ urlTrackedParams: ['page', 'search', 'mode', 'region', 'highlight', 'view', 'text'],
26
29
 
27
30
  /** If true, don't update the URL when `page == n0 (eg "/page/n0")` */
28
31
  urlTrackIndex0: false,
@@ -50,7 +53,7 @@ BookReader.prototype.init = (function(super_) {
50
53
  this.bind(BookReader.eventNames.PostInit, () => {
51
54
  const { updateWindowTitle, urlMode } = this.options;
52
55
  if (updateWindowTitle) {
53
- document.title = this.shortTitle(50);
56
+ document.title = this.shortTitle(this.bookTitle, 50);
54
57
  }
55
58
  if (urlMode === 'hash') {
56
59
  this.urlStartLocationPolling();
@@ -58,7 +61,7 @@ BookReader.prototype.init = (function(super_) {
58
61
  });
59
62
 
60
63
  this.bind(BookReader.eventNames.fragmentChange,
61
- this.urlUpdateFragment.bind(this)
64
+ this.urlUpdateFragment.bind(this),
62
65
  );
63
66
  }
64
67
  super_.call(this);
@@ -86,7 +89,7 @@ BookReader.prototype.urlStartLocationPolling = function() {
86
89
  this.oldLocationHash = this.urlReadFragment();
87
90
 
88
91
  if (this.locationPollId) {
89
- clearInterval(this.locationPollID);
92
+ clearInterval(this.locationPollId);
90
93
  this.locationPollId = null;
91
94
  }
92
95
 
@@ -103,7 +106,7 @@ BookReader.prototype.urlStartLocationPolling = function() {
103
106
  this.trigger(BookReader.eventNames.stop);
104
107
  if (this.animating) {
105
108
  // Queue change if animating
106
- if (this.autoStop) this.autoStop();
109
+ this.plugins.autoplay?.stop();
107
110
  this.animationFinishedCallback = updateParams;
108
111
  } else {
109
112
  // update immediately
@@ -121,7 +124,7 @@ BookReader.prototype.urlStartLocationPolling = function() {
121
124
  */
122
125
  BookReader.prototype.urlUpdateFragment = function() {
123
126
  const allParams = this.paramsFromCurrent();
124
- const { urlMode, urlTrackIndex0, urlTrackedParams } = this.options;
127
+ const { urlTrackIndex0, urlTrackedParams } = this.options;
125
128
 
126
129
  if (!urlTrackIndex0
127
130
  && (typeof(allParams.index) !== 'undefined')
@@ -137,29 +140,44 @@ BookReader.prototype.urlUpdateFragment = function() {
137
140
  return validParams;
138
141
  }, {});
139
142
 
140
- const newFragment = this.fragmentFromParams(params, urlMode);
143
+ // eg 'page/3/mode/2up'; no query params (in hash mode, it might have /search/term)
144
+ const newFragment = this.fragmentFromParams(params, this.options.urlMode);
145
+ const newFragmentWithSlash = newFragment === '' ? '' : `/${newFragment}`;
146
+ // eg 'page/3/mode/2up'; no query params
141
147
  const currFragment = this.urlReadFragment();
148
+ // This should have both ?q=foo&text=bar (and any other params) as an encoded string
142
149
  const currQueryString = this.getLocationSearch();
143
- const newQueryString = this.queryStringFromParams(params, currQueryString, urlMode);
150
+ // Eg ?q=foo&text=bar; only query params, no fragment
151
+ const newQueryString = this.queryStringFromParams(params, currQueryString, this.options.urlMode);
152
+ // Avoid infinite loop if there are no changes
144
153
  if (currFragment === newFragment && currQueryString === newQueryString) {
145
154
  return;
146
155
  }
147
156
 
148
- if (urlMode === 'history') {
149
- if (window.history && window.history.replaceState) {
157
+ if (this.options.urlMode === 'history') {
158
+ if (!window.history || !window.history.replaceState) {
159
+ this.options.urlMode = 'hash';
160
+ } else {
150
161
  const baseWithoutSlash = this.options.urlHistoryBasePath.replace(/\/+$/, '');
151
- const newFragmentWithSlash = newFragment === '' ? '' : `/${newFragment}`;
152
-
153
162
  const newUrlPath = `${baseWithoutSlash}${newFragmentWithSlash}${newQueryString}`;
154
- window.history.replaceState({}, null, newUrlPath);
155
- this.oldLocationHash = newFragment + newQueryString;
156
163
 
164
+ try {
165
+ window.history.replaceState({}, null, newUrlPath);
166
+ this.oldLocationHash = newFragment + newQueryString;
167
+ } catch (e) {
168
+ // DOMException on Chrome when in sandboxed iframe
169
+ this.options.urlMode = 'hash';
170
+ }
157
171
  }
158
- } else {
172
+ }
173
+
174
+ if (this.options.urlMode === 'hash') {
159
175
  const newQueryStringSearch = this.urlParamsFiltersOnlySearch(this.readQueryString());
160
- window.location.replace('#' + newFragment + newQueryStringSearch);
176
+ // Built from location.href so a <base href> on the page can't change
177
+ // the pathname, and replace() so page flips don't add history entries.
178
+ const [baseHref] = window.location.href.split('#');
179
+ window.location.replace(`${baseHref}#${newFragment}${newQueryStringSearch}`);
161
180
  this.oldLocationHash = newFragment + newQueryStringSearch;
162
-
163
181
  }
164
182
  };
165
183
 
@@ -185,7 +203,7 @@ BookReader.prototype.urlReadFragment = function() {
185
203
  if (urlMode === 'history') {
186
204
  return window.location.pathname.substr(urlHistoryBasePath.length);
187
205
  } else {
188
- return window.location.hash.substr(1);
206
+ return this.urlPlugin.getHash();
189
207
  }
190
208
  };
191
209
 
@@ -196,3 +214,21 @@ BookReader.prototype.urlReadFragment = function() {
196
214
  BookReader.prototype.urlReadHashFragment = function() {
197
215
  return window.location.hash.substr(1);
198
216
  };
217
+ export class BookreaderUrlPlugin extends BookReader {
218
+ init() {
219
+ if (this.options.enableUrlPlugin) {
220
+ this.urlPlugin = new UrlPlugin(this.options);
221
+
222
+ this.on(BookReader.eventNames.PostInit, () => {
223
+ if (this.options.urlMode === 'hash') {
224
+ this.urlPlugin.listenForHashChanges();
225
+ }
226
+ });
227
+ }
228
+
229
+ super.init();
230
+ }
231
+ }
232
+
233
+ window.BookReader = BookreaderUrlPlugin;
234
+ export default BookreaderUrlPlugin;