@internetarchive/bookreader 5.0.0-11-multiple-files → 5.0.0-110
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 +2 -0
- package/BookReader/474.js.map +1 -0
- package/BookReader/BookReader.css +616 -1467
- package/BookReader/BookReader.js +2 -21564
- package/BookReader/BookReader.js.LICENSE.txt +20 -20
- package/BookReader/BookReader.js.map +1 -1
- package/BookReader/bergamot-translator-worker.js +2966 -0
- package/BookReader/bergamot-translator-worker.wasm +0 -0
- package/BookReader/hypothesis/LICENSE +50 -0
- package/BookReader/hypothesis/README.md +55 -0
- package/BookReader/hypothesis/build/boot.js +1 -0
- package/BookReader/hypothesis/build/manifest.json +20 -0
- package/BookReader/hypothesis/build/scripts/annotator.bundle.js +184 -0
- package/BookReader/hypothesis/build/scripts/annotator.bundle.js.map +1 -0
- package/BookReader/hypothesis/build/scripts/sidebar.bundle.js +798 -0
- package/BookReader/hypothesis/build/scripts/sidebar.bundle.js.map +1 -0
- package/BookReader/hypothesis/build/scripts/ui-playground.bundle.js +711 -0
- package/BookReader/hypothesis/build/scripts/ui-playground.bundle.js.map +1 -0
- package/BookReader/hypothesis/build/styles/annotator.css +2235 -0
- package/BookReader/hypothesis/build/styles/annotator.css.map +1 -0
- package/BookReader/hypothesis/build/styles/fonts/KaTeX_AMS-Regular.woff2 +0 -0
- package/BookReader/hypothesis/build/styles/fonts/KaTeX_Caligraphic-Bold.woff2 +0 -0
- package/BookReader/hypothesis/build/styles/fonts/KaTeX_Caligraphic-Regular.woff2 +0 -0
- package/BookReader/hypothesis/build/styles/fonts/KaTeX_Fraktur-Bold.woff2 +0 -0
- package/BookReader/hypothesis/build/styles/fonts/KaTeX_Fraktur-Regular.woff2 +0 -0
- package/BookReader/hypothesis/build/styles/fonts/KaTeX_Main-Bold.woff2 +0 -0
- package/BookReader/hypothesis/build/styles/fonts/KaTeX_Main-BoldItalic.woff2 +0 -0
- package/BookReader/hypothesis/build/styles/fonts/KaTeX_Main-Italic.woff2 +0 -0
- package/BookReader/hypothesis/build/styles/fonts/KaTeX_Main-Regular.woff2 +0 -0
- package/BookReader/hypothesis/build/styles/fonts/KaTeX_Math-BoldItalic.woff2 +0 -0
- package/BookReader/hypothesis/build/styles/fonts/KaTeX_Math-Italic.woff2 +0 -0
- package/BookReader/hypothesis/build/styles/fonts/KaTeX_SansSerif-Bold.woff2 +0 -0
- package/BookReader/hypothesis/build/styles/fonts/KaTeX_SansSerif-Italic.woff2 +0 -0
- package/BookReader/hypothesis/build/styles/fonts/KaTeX_SansSerif-Regular.woff2 +0 -0
- package/BookReader/hypothesis/build/styles/fonts/KaTeX_Script-Regular.woff2 +0 -0
- package/BookReader/hypothesis/build/styles/fonts/KaTeX_Size1-Regular.woff2 +0 -0
- package/BookReader/hypothesis/build/styles/fonts/KaTeX_Size2-Regular.woff2 +0 -0
- package/BookReader/hypothesis/build/styles/fonts/KaTeX_Size3-Regular.woff2 +0 -0
- package/BookReader/hypothesis/build/styles/fonts/KaTeX_Size4-Regular.woff2 +0 -0
- package/BookReader/hypothesis/build/styles/fonts/KaTeX_Typewriter-Regular.woff2 +0 -0
- package/BookReader/hypothesis/build/styles/highlights.css +2 -0
- package/BookReader/hypothesis/build/styles/highlights.css.map +1 -0
- package/BookReader/hypothesis/build/styles/katex.min.css +2 -0
- package/BookReader/hypothesis/build/styles/katex.min.css.map +1 -0
- package/BookReader/hypothesis/build/styles/pdfjs-overrides.css +2 -0
- package/BookReader/hypothesis/build/styles/pdfjs-overrides.css.map +1 -0
- package/BookReader/hypothesis/build/styles/sidebar.css +2731 -0
- package/BookReader/hypothesis/build/styles/sidebar.css.map +1 -0
- package/BookReader/hypothesis/build/styles/ui-playground.css +2659 -0
- package/BookReader/hypothesis/build/styles/ui-playground.css.map +1 -0
- package/BookReader/hypothesis/package.json +126 -0
- package/BookReader/ia-bookreader-bundle.js +1907 -0
- package/BookReader/ia-bookreader-bundle.js.LICENSE.txt +19 -0
- package/BookReader/ia-bookreader-bundle.js.map +1 -0
- package/BookReader/icons/1up.svg +1 -12
- package/BookReader/icons/2up.svg +1 -15
- package/BookReader/icons/advance.svg +3 -26
- package/BookReader/icons/chevron-right.svg +1 -1
- package/BookReader/icons/close-circle-dark.svg +1 -0
- package/BookReader/icons/close-circle.svg +1 -1
- package/BookReader/icons/fullscreen.svg +1 -17
- package/BookReader/icons/fullscreen_exit.svg +1 -17
- package/BookReader/icons/hamburger.svg +1 -15
- package/BookReader/icons/left-arrow.svg +1 -12
- package/BookReader/icons/magnify-minus.svg +1 -16
- package/BookReader/icons/magnify-plus.svg +1 -17
- package/BookReader/icons/magnify.svg +1 -15
- package/BookReader/icons/pause.svg +1 -23
- package/BookReader/icons/play.svg +1 -22
- package/BookReader/icons/playback-speed.svg +1 -34
- package/BookReader/icons/read-aloud.svg +1 -22
- package/BookReader/icons/review.svg +3 -22
- package/BookReader/icons/slider-toggle.svg +1 -0
- package/BookReader/icons/thumbnails.svg +1 -17
- package/BookReader/icons/voice.svg +1 -0
- package/BookReader/icons/volume-full.svg +1 -22
- package/BookReader/images/BRicons.svg +5 -94
- package/BookReader/images/books_graphic.svg +1 -177
- package/BookReader/images/hypothesis.ico +0 -0
- package/BookReader/images/icon_book.svg +1 -12
- package/BookReader/images/icon_bookmark.svg +1 -12
- package/BookReader/images/icon_experiment.svg +1 -0
- package/BookReader/images/icon_gear.svg +1 -14
- package/BookReader/images/icon_hamburger.svg +1 -20
- package/BookReader/images/icon_home.svg +1 -21
- package/BookReader/images/icon_info.svg +1 -11
- package/BookReader/images/icon_one_page.svg +1 -8
- package/BookReader/images/icon_pause.svg +1 -1
- package/BookReader/images/icon_play.svg +1 -1
- package/BookReader/images/icon_playback-rate.svg +1 -15
- package/BookReader/images/icon_search_button.svg +1 -8
- package/BookReader/images/icon_share.svg +1 -9
- package/BookReader/images/icon_skip-ahead.svg +1 -6
- package/BookReader/images/icon_skip-back.svg +2 -13
- package/BookReader/images/icon_speaker.svg +1 -18
- package/BookReader/images/icon_speaker_open.svg +1 -10
- package/BookReader/images/icon_thumbnails.svg +1 -12
- package/BookReader/images/icon_toc.svg +1 -5
- package/BookReader/images/icon_two_pages.svg +1 -9
- package/BookReader/images/marker_chap-off.svg +1 -11
- package/BookReader/images/marker_chap-on.svg +1 -11
- package/BookReader/images/marker_srch-on.svg +1 -11
- package/BookReader/images/translate.svg +1 -0
- package/BookReader/images/unviewable_page.png +0 -0
- package/BookReader/jquery-3.js +2 -0
- package/BookReader/jquery-3.js.LICENSE.txt +24 -0
- package/BookReader/plugins/plugin.archive_analytics.js +1 -172
- package/BookReader/plugins/plugin.archive_analytics.js.map +1 -1
- package/BookReader/plugins/plugin.autoplay.js +1 -165
- package/BookReader/plugins/plugin.autoplay.js.map +1 -1
- package/BookReader/plugins/plugin.chapters.js +19 -301
- package/BookReader/plugins/plugin.chapters.js.LICENSE.txt +1 -0
- package/BookReader/plugins/plugin.chapters.js.map +1 -1
- package/BookReader/plugins/plugin.experiments.js +3 -0
- package/BookReader/plugins/plugin.experiments.js.LICENSE.txt +1 -0
- package/BookReader/plugins/plugin.experiments.js.map +1 -0
- package/BookReader/plugins/plugin.iframe.js +1 -74
- package/BookReader/plugins/plugin.iframe.js.map +1 -1
- package/BookReader/plugins/plugin.iiif.js +2 -0
- package/BookReader/plugins/plugin.iiif.js.map +1 -0
- package/BookReader/plugins/plugin.resume.js +1 -368
- package/BookReader/plugins/plugin.resume.js.map +1 -1
- package/BookReader/plugins/plugin.search.js +2 -1420
- package/BookReader/plugins/plugin.search.js.LICENSE.txt +1 -0
- package/BookReader/plugins/plugin.search.js.map +1 -1
- package/BookReader/plugins/plugin.text_selection.js +2 -1080
- package/BookReader/plugins/plugin.text_selection.js.LICENSE.txt +1 -0
- package/BookReader/plugins/plugin.text_selection.js.map +1 -1
- package/BookReader/plugins/plugin.translate.js +137 -0
- package/BookReader/plugins/plugin.translate.js.LICENSE.txt +1 -0
- package/BookReader/plugins/plugin.translate.js.map +1 -0
- package/BookReader/plugins/plugin.tts.js +2 -9193
- package/BookReader/plugins/plugin.tts.js.LICENSE.txt +2 -0
- package/BookReader/plugins/plugin.tts.js.map +1 -1
- package/BookReader/plugins/plugin.url.js +1 -269
- package/BookReader/plugins/plugin.url.js.map +1 -1
- package/BookReader/plugins/plugin.vendor-fullscreen.js +1 -379
- package/BookReader/plugins/plugin.vendor-fullscreen.js.map +1 -1
- package/BookReader/plugins/translator-worker.js +2 -0
- package/BookReader/plugins/translator-worker.js.map +1 -0
- package/BookReader/silence.mp3 +0 -0
- package/BookReader/translator-worker.js +475 -0
- package/BookReader/webcomponents-bundle.js +3 -0
- package/BookReader/webcomponents-bundle.js.LICENSE.txt +9 -0
- package/BookReader/webcomponents-bundle.js.map +1 -0
- package/README.md +14 -3
- package/jsconfig.json +19 -0
- package/package.json +92 -70
- package/src/BookReader/BookModel.js +92 -46
- package/src/BookReader/DragScrollable.js +233 -0
- package/src/BookReader/ImageCache.js +49 -16
- package/src/BookReader/Mode1Up.js +66 -356
- package/src/BookReader/Mode1UpLit.js +392 -0
- package/src/BookReader/Mode2Up.js +87 -1315
- package/src/BookReader/Mode2UpLit.js +788 -0
- package/src/BookReader/ModeAbstract.js +43 -0
- package/src/BookReader/ModeCoordinateSpace.js +29 -0
- package/src/BookReader/ModeSmoothZoom.js +312 -0
- package/src/BookReader/ModeThumb.js +30 -16
- package/src/BookReader/Navbar/Navbar.js +201 -76
- package/src/BookReader/PageContainer.js +120 -23
- package/src/BookReader/ReduceSet.js +3 -3
- package/src/BookReader/Toolbar/Toolbar.js +19 -41
- package/src/BookReader/events.js +3 -3
- package/src/BookReader/options.js +94 -17
- package/src/BookReader/utils/HTMLDimensionsCacher.js +44 -0
- package/src/BookReader/utils/ScrollClassAdder.js +31 -0
- package/src/BookReader/utils/SelectionObserver.js +45 -0
- package/src/BookReader/utils/classes.js +1 -1
- package/src/BookReader/utils.js +141 -13
- package/src/BookReader.js +711 -1241
- package/src/BookReaderPlugin.js +52 -0
- package/src/assets/icons/close-circle-dark.svg +1 -0
- package/src/assets/icons/magnify-minus.svg +3 -7
- package/src/assets/icons/magnify-plus.svg +3 -7
- package/src/assets/icons/slider-toggle.svg +1 -0
- package/src/assets/icons/voice.svg +1 -0
- package/src/assets/images/hypothesis.ico +0 -0
- package/src/assets/images/icon_experiment.svg +1 -0
- package/src/assets/images/translate.svg +1 -0
- package/src/assets/images/unviewable_page.png +0 -0
- package/src/assets/silence.mp3 +0 -0
- package/src/css/BookReader.scss +1 -17
- package/src/css/_BRBookmarks.scss +1 -1
- package/src/css/_BRComponent.scss +1 -1
- package/src/css/_BRicon.scss +8 -2
- package/src/css/_BRmain.scss +33 -27
- package/src/css/_BRnav.scss +74 -70
- package/src/css/_BRpages.scss +171 -42
- package/src/css/_BRsearch.scss +69 -235
- package/src/css/_BRtoolbar.scss +5 -5
- package/src/css/_TextSelection.scss +129 -24
- package/src/css/_colorbox.scss +2 -2
- package/src/css/_controls.scss +24 -7
- package/src/css/_icons.scss +14 -1
- package/src/{BookNavigator/assets → css}/button-base.js +10 -3
- package/src/css/icon_checkmark.js +9 -0
- package/src/css/sharedStyles.js +15 -0
- package/src/ia-bookreader/downloads/downloads-provider.js +81 -0
- package/src/{BookNavigator → ia-bookreader}/downloads/downloads.js +29 -25
- package/src/ia-bookreader/ia-bookreader.js +666 -0
- package/src/ia-bookreader/sharing.js +27 -0
- package/src/ia-bookreader/viewable-files.js +98 -0
- package/src/{BookNavigator → ia-bookreader}/visual-adjustments/visual-adjustments-provider.js +17 -17
- package/src/{BookNavigator → ia-bookreader}/visual-adjustments/visual-adjustments.js +75 -67
- package/src/{BookNavigator → plugins}/bookmarks/bookmark-button.js +4 -3
- package/src/{BookNavigator/assets → plugins/bookmarks}/bookmark-colors.js +1 -1
- package/src/{BookNavigator → plugins}/bookmarks/bookmark-edit.js +44 -32
- package/src/{BookNavigator → plugins}/bookmarks/bookmarks-list.js +48 -49
- package/src/{BookNavigator → plugins}/bookmarks/bookmarks-loginCTA.js +5 -10
- package/src/plugins/bookmarks/bookmarks-provider.js +63 -0
- package/src/{BookNavigator → plugins/bookmarks}/delete-modal-actions.js +1 -1
- package/src/{BookNavigator → plugins}/bookmarks/ia-bookmarks.js +117 -68
- package/src/plugins/plugin.archive_analytics.js +84 -78
- package/src/plugins/plugin.autoplay.js +99 -104
- package/src/plugins/plugin.chapters.js +310 -201
- package/src/plugins/plugin.experiments.js +321 -0
- package/src/plugins/plugin.iframe.js +1 -1
- package/src/plugins/plugin.iiif.js +141 -0
- package/src/plugins/plugin.resume.js +53 -50
- package/src/plugins/plugin.text_selection.js +522 -219
- package/src/plugins/plugin.vendor-fullscreen.js +7 -7
- package/src/plugins/search/plugin.search.js +380 -360
- package/src/{BookNavigator → plugins}/search/search-provider.js +94 -32
- package/src/{BookNavigator → plugins}/search/search-results.js +108 -90
- package/src/plugins/search/utils.js +50 -0
- package/src/plugins/search/view.js +79 -210
- package/src/plugins/translate/TranslationManager.js +164 -0
- package/src/plugins/translate/plugin.translate.js +512 -0
- package/src/plugins/tts/AbstractTTSEngine.js +78 -49
- package/src/plugins/tts/FestivalTTSEngine.js +21 -31
- package/src/plugins/tts/PageChunk.js +33 -21
- package/src/plugins/tts/PageChunkIterator.js +11 -17
- package/src/plugins/tts/WebTTSEngine.js +131 -91
- package/src/plugins/tts/plugin.tts.js +345 -350
- package/src/plugins/tts/utils.js +77 -49
- package/src/plugins/url/UrlPlugin.js +191 -0
- package/src/plugins/{plugin.url.js → url/plugin.url.js} +47 -18
- package/src/util/TextSelectionManager.js +282 -0
- package/src/util/browserSniffing.js +33 -1
- package/src/util/cache.js +20 -0
- package/src/util/docCookies.js +21 -2
- package/src/util/lit.js +15 -0
- package/src/util/strings.js +1 -0
- package/.babelrc +0 -12
- package/.dependabot/config.yml +0 -6
- package/.eslintrc.js +0 -49
- package/.gitattributes +0 -2
- package/.github/ISSUE_TEMPLATE/bug.md +0 -32
- package/.github/ISSUE_TEMPLATE/feature-request.md +0 -30
- package/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md +0 -15
- package/.github/workflows/node.js.yml +0 -28
- package/.github/workflows/npm-publish.yml +0 -47
- package/.testcaferc.json +0 -5
- package/BookReader/bookreader-component-bundle.js +0 -14330
- package/BookReader/bookreader-component-bundle.js.LICENSE.txt +0 -38
- package/BookReader/bookreader-component-bundle.js.map +0 -1
- package/BookReader/icons/sort-ascending.svg +0 -1
- package/BookReader/icons/sort-descending.svg +0 -1
- package/BookReader/jquery-1.10.1.js +0 -108
- package/BookReader/jquery-1.10.1.js.LICENSE.txt +0 -24
- package/BookReader/plugins/plugin.menu_toggle.js +0 -369
- package/BookReader/plugins/plugin.menu_toggle.js.map +0 -1
- package/BookReader/plugins/plugin.mobile_nav.js +0 -335
- package/BookReader/plugins/plugin.mobile_nav.js.map +0 -1
- package/BookReaderDemo/BookReaderDemo.css +0 -41
- package/BookReaderDemo/BookReaderJSAdvanced.js +0 -115
- package/BookReaderDemo/BookReaderJSAutoplay.js +0 -56
- package/BookReaderDemo/BookReaderJSSimple.js +0 -55
- package/BookReaderDemo/IIIFBookReader.js +0 -207
- package/BookReaderDemo/assets/v5/Bookreader-logo-cool-grad.svg +0 -1
- package/BookReaderDemo/assets/v5/Bookreader-logo-flat.svg +0 -1
- package/BookReaderDemo/assets/v5/Bookreader-logo-hex-cool-grad.png +0 -0
- package/BookReaderDemo/assets/v5/Bookreader-logo-hex-flat.png +0 -0
- package/BookReaderDemo/assets/v5/Bookreader-logo-lines.png +0 -0
- package/BookReaderDemo/assets/v5/Bookreader-logo-lines.svg +0 -1
- package/BookReaderDemo/assets/v5/Bookreader-logo-warm.svg +0 -1
- package/BookReaderDemo/assets/v5/bookreader-logo-renders@1x.png +0 -0
- package/BookReaderDemo/assets/v5/bookreader-logo-renders@2x.png +0 -0
- package/BookReaderDemo/assets/v5/bookreader-v5-screenshot.png +0 -0
- package/BookReaderDemo/bookreader-template-bundle.js +0 -7178
- package/BookReaderDemo/demo-advanced.html +0 -33
- package/BookReaderDemo/demo-autoplay.html +0 -38
- package/BookReaderDemo/demo-embed-iframe-src.html +0 -84
- package/BookReaderDemo/demo-embed.html +0 -26
- package/BookReaderDemo/demo-fullscreen-mobile.html +0 -36
- package/BookReaderDemo/demo-fullscreen.html +0 -33
- package/BookReaderDemo/demo-iiif.html +0 -34
- package/BookReaderDemo/demo-iiif.js +0 -26
- package/BookReaderDemo/demo-internetarchive.html +0 -74
- package/BookReaderDemo/demo-multiple.html +0 -43
- package/BookReaderDemo/demo-plugin-menu-toggle.html +0 -34
- package/BookReaderDemo/demo-preview-pages.html +0 -1092
- package/BookReaderDemo/demo-simple.html +0 -34
- package/BookReaderDemo/demo-vendor-fullscreen.html +0 -36
- package/BookReaderDemo/immersion-1up.html +0 -64
- package/BookReaderDemo/immersion-mode.html +0 -35
- package/BookReaderDemo/toggle_controls.html +0 -53
- package/BookReaderDemo/view_mode.html +0 -39
- package/BookReaderDemo/viewmode-cycle.html +0 -41
- package/CHANGELOG.md +0 -476
- package/CONTRIBUTING.md +0 -7
- package/codecov.yml +0 -17
- package/index.html +0 -31
- package/karma.conf.js +0 -23
- package/screenshot.png +0 -0
- package/scripts/postversion.js +0 -10
- package/scripts/preversion.js +0 -14
- package/scripts/version.js +0 -26
- package/src/BookNavigator/BookModel.js +0 -14
- package/src/BookNavigator/BookNavigator.js +0 -451
- package/src/BookNavigator/assets/book-loader.js +0 -27
- package/src/BookNavigator/assets/icon_checkmark.js +0 -6
- package/src/BookNavigator/assets/icon_close.js +0 -3
- package/src/BookNavigator/assets/icon_sort_ascending.js +0 -5
- package/src/BookNavigator/assets/icon_sort_descending.js +0 -5
- package/src/BookNavigator/bookmarks/bookmarks-provider.js +0 -53
- package/src/BookNavigator/br-fullscreen-mgr.js +0 -83
- package/src/BookNavigator/downloads/downloads-provider.js +0 -66
- package/src/BookNavigator/search/a-search-result.js +0 -55
- package/src/BookNavigator/volumes/volumes-provider.js +0 -75
- package/src/BookNavigator/volumes/volumes.js +0 -161
- package/src/BookReader/DebugConsole.js +0 -54
- package/src/BookReaderComponent/BookReaderComponent.js +0 -112
- package/src/ItemNavigator/ItemNavigator.js +0 -372
- package/src/ItemNavigator/providers/sharing.js +0 -29
- package/src/assets/icons/sort-ascending.svg +0 -1
- package/src/assets/icons/sort-descending.svg +0 -1
- package/src/css/_MobileNav.scss +0 -194
- package/src/dragscrollable-br.js +0 -261
- package/src/plugins/menu_toggle/plugin.menu_toggle.js +0 -324
- package/src/plugins/plugin.mobile_nav.js +0 -287
- package/tests/BookReader/BookModel.test.js +0 -312
- package/tests/BookReader/BookReaderPublicFunctions.test.js +0 -171
- package/tests/BookReader/DebugConsole.test.js +0 -25
- package/tests/BookReader/ImageCache.test.js +0 -150
- package/tests/BookReader/Mode1Up.test.js +0 -164
- package/tests/BookReader/Mode2Up.test.js +0 -247
- package/tests/BookReader/Navbar/Navbar.test.js +0 -169
- package/tests/BookReader/PageContainer.test.js +0 -115
- package/tests/BookReader/ReduceSet.test.js +0 -38
- package/tests/BookReader/Toolbar/Toolbar.test.js +0 -26
- package/tests/BookReader/utils/classes.test.js +0 -88
- package/tests/BookReader/utils.test.js +0 -109
- package/tests/BookReader.options.test.js +0 -39
- package/tests/BookReader.test.js +0 -301
- package/tests/e2e/README.md +0 -75
- package/tests/e2e/autoplay.test.js +0 -13
- package/tests/e2e/base.test.js +0 -35
- package/tests/e2e/helpers/base.js +0 -258
- package/tests/e2e/helpers/debug.js +0 -13
- package/tests/e2e/helpers/desktopSearch.js +0 -72
- package/tests/e2e/helpers/mobileSearch.js +0 -85
- package/tests/e2e/helpers/mockSearch.js +0 -93
- package/tests/e2e/helpers/rightToLeft.js +0 -29
- package/tests/e2e/ia-production/ia-prod-base.js +0 -17
- package/tests/e2e/models/BookReader.js +0 -11
- package/tests/e2e/models/Navigation.js +0 -56
- package/tests/e2e/rightToLeft.test.js +0 -20
- package/tests/e2e/viewmode.test.js +0 -37
- package/tests/karma/BookNavigator/book-navigator.test.js +0 -132
- package/tests/karma/BookNavigator/bookmarks/bookmark-edit.test.js +0 -133
- package/tests/karma/BookNavigator/bookmarks/bookmarks-list.test.js +0 -222
- package/tests/karma/BookNavigator/search-results.test.js +0 -240
- package/tests/karma/BookNavigator/visual-adjustments.test.js +0 -201
- package/tests/karma/BookNavigator/volumes.test.js +0 -133
- package/tests/plugins/menu_toggle/plugin.menu_toggle.test.js +0 -68
- package/tests/plugins/plugin.archive_analytics.test.js +0 -23
- package/tests/plugins/plugin.autoplay.test.js +0 -52
- package/tests/plugins/plugin.chapters.test.js +0 -130
- package/tests/plugins/plugin.iframe.test.js +0 -42
- package/tests/plugins/plugin.mobile_nav.test.js +0 -66
- package/tests/plugins/plugin.resume.test.js +0 -98
- package/tests/plugins/plugin.text_selection.test.js +0 -203
- package/tests/plugins/plugin.url.test.js +0 -129
- package/tests/plugins/plugin.vendor-fullscreen.test.js +0 -65
- package/tests/plugins/search/plugin.search.test.js +0 -166
- package/tests/plugins/search/plugin.search.view.test.js +0 -106
- package/tests/plugins/tts/AbstractTTSEngine.test.js +0 -153
- package/tests/plugins/tts/FestivalTTSEngine.test.js +0 -59
- package/tests/plugins/tts/PageChunk.test.js +0 -57
- package/tests/plugins/tts/PageChunkIterator.test.js +0 -179
- package/tests/plugins/tts/WebTTSEngine.test.js +0 -126
- package/tests/plugins/tts/utils.test.js +0 -133
- package/tests/util/browserSniffing.test.js +0 -56
- package/tests/util/docCookies.test.js +0 -15
- package/tests/util/strings.test.js +0 -63
- package/tests/utils.js +0 -42
- package/webpack.config.js +0 -86
|
@@ -1,75 +1,33 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
/** @typedef {import('@/src/BookReader.js').default} BookReader */
|
|
3
|
+
|
|
1
4
|
class SearchView {
|
|
2
5
|
/**
|
|
3
6
|
* @param {object} params
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* @param {object} params.br The BookReader instance
|
|
7
|
+
* @param {BookReader} params.br The BookReader instance
|
|
8
|
+
* @param {function} params.searchCancelledCallback callback when a user wants to cancel search
|
|
7
9
|
*
|
|
8
10
|
* @event BookReader:SearchResultsCleared - when the search results nav gets cleared
|
|
9
11
|
* @event BookReader:ToggleSearchMenu - when search results menu should toggle
|
|
10
12
|
*/
|
|
11
|
-
constructor(
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
return;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
this.br = params.br;
|
|
18
|
-
|
|
19
|
-
// Search results are returned as a text blob with the hits wrapped in
|
|
20
|
-
// triple mustaches. Hits occasionally include text beyond the search
|
|
21
|
-
// term, so everything within the staches is captured and wrapped.
|
|
22
|
-
this.matcher = new RegExp('{{{(.+?)}}}', 'g');
|
|
13
|
+
constructor({ br, searchCancelledCallback = () => {} }) {
|
|
14
|
+
/** @type {BookReader} */
|
|
15
|
+
this.br = br;
|
|
23
16
|
this.matches = [];
|
|
24
|
-
this.cacheDOMElements(
|
|
17
|
+
this.cacheDOMElements();
|
|
18
|
+
this.cancelSearch = searchCancelledCallback;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
init() {
|
|
25
22
|
this.bindEvents();
|
|
26
23
|
}
|
|
27
24
|
|
|
28
|
-
|
|
29
|
-
* @param {string} selector A selector for the element that the search tray will be rendered in
|
|
30
|
-
*/
|
|
31
|
-
cacheDOMElements(selector) {
|
|
25
|
+
cacheDOMElements() {
|
|
32
26
|
this.dom = {};
|
|
33
|
-
|
|
34
|
-
// The parent search tray in mobile menu
|
|
35
|
-
this.dom.searchTray = this.renderSearchTray(selector);
|
|
36
|
-
// Container for rendered search results
|
|
37
|
-
this.dom.results = this.dom.searchTray.querySelector('[data-id="results"]');
|
|
38
|
-
// Element used to display number of results
|
|
39
|
-
this.dom.resultsCount = this.dom.searchTray.querySelector('[data-id="results_count"]');
|
|
40
|
-
// Search input within the mobile search tray
|
|
41
|
-
this.dom.searchField = this.dom.searchTray.querySelector('[name="query"]');
|
|
42
|
-
// Waiting indicator displayed while waiting for a search request
|
|
43
|
-
this.dom.searchPending = this.dom.searchTray.querySelector('[data-id="searchPending"]');
|
|
44
|
-
// The element added to the mobile menu that is animated into view when
|
|
45
|
-
// the "search" nav item is clicked
|
|
46
|
-
this.dom.mobileSearch = this.buildMobileDrawer();
|
|
47
27
|
// Search input within the top toolbar. Will be removed once the mobile menu is replaced.
|
|
48
28
|
this.dom.toolbarSearch = this.buildToolbarSearch();
|
|
49
29
|
}
|
|
50
30
|
|
|
51
|
-
/**
|
|
52
|
-
* @param {boolean} bool
|
|
53
|
-
*/
|
|
54
|
-
toggleSearchTray(bool = this.dom.searchTray.classList.contains('hidden')) {
|
|
55
|
-
this.dom.searchTray.classList.toggle('hidden', !bool);
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* @param {boolean} bool
|
|
60
|
-
*/
|
|
61
|
-
toggleResultsCount(bool) {
|
|
62
|
-
this.dom.resultsCount.classList.toggle('visible', bool);
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
* @param {SearchInsideResults} results
|
|
67
|
-
*/
|
|
68
|
-
updateResultsCount(results) {
|
|
69
|
-
this.dom.resultsCount.innerText = `(${results} result${results != 1 ? 's' : ''})`;
|
|
70
|
-
this.toggleResultsCount(true);
|
|
71
|
-
}
|
|
72
|
-
|
|
73
31
|
/**
|
|
74
32
|
* @param {string} query
|
|
75
33
|
*/
|
|
@@ -78,7 +36,6 @@ class SearchView {
|
|
|
78
36
|
}
|
|
79
37
|
|
|
80
38
|
emptyMatches() {
|
|
81
|
-
this.dom.results.innerHTML = '';
|
|
82
39
|
this.matches = [];
|
|
83
40
|
}
|
|
84
41
|
|
|
@@ -86,52 +43,24 @@ class SearchView {
|
|
|
86
43
|
this.br.$('.BRnavpos .BRsearch').remove();
|
|
87
44
|
}
|
|
88
45
|
|
|
89
|
-
clearSearchFieldAndResults() {
|
|
90
|
-
this.br.removeSearchResults();
|
|
91
|
-
this.toggleResultsCount(false);
|
|
46
|
+
clearSearchFieldAndResults(dispatchEventWhenComplete = true) {
|
|
47
|
+
this.br.plugins.search.removeSearchResults();
|
|
92
48
|
this.removeResultPins();
|
|
93
49
|
this.emptyMatches();
|
|
94
50
|
this.setQuery('');
|
|
95
51
|
this.teardownSearchNavigation();
|
|
96
|
-
|
|
52
|
+
if (dispatchEventWhenComplete) {
|
|
53
|
+
this.br.trigger('SearchResultsCleared');
|
|
54
|
+
}
|
|
97
55
|
}
|
|
98
56
|
|
|
99
57
|
toggleSidebar() {
|
|
100
58
|
this.br.trigger('ToggleSearchMenu');
|
|
101
59
|
}
|
|
102
|
-
/**
|
|
103
|
-
* @param {string} selector The ID attribute to be used for the search tray
|
|
104
|
-
*/
|
|
105
|
-
renderSearchTray(selector) {
|
|
106
|
-
const searchTray = document.createElement('div');
|
|
107
|
-
searchTray.setAttribute('id', selector.replace(/^#/, ''));
|
|
108
|
-
searchTray.innerHTML = `
|
|
109
|
-
<header>
|
|
110
|
-
<div>
|
|
111
|
-
<h3>Search inside</h3>
|
|
112
|
-
<p data-id="results_count"></p>
|
|
113
|
-
</div>
|
|
114
|
-
<a href="#" class="close"></a>
|
|
115
|
-
</header>
|
|
116
|
-
<form action="" method="get">
|
|
117
|
-
<fieldset>
|
|
118
|
-
<input name="all_files" id="all_files" type="checkbox" />
|
|
119
|
-
<label class="checkbox" for="all_files">Search all files</label>
|
|
120
|
-
<input type="search" name="query" placeholder="Enter a search term" />
|
|
121
|
-
</fieldset>
|
|
122
|
-
</form>
|
|
123
|
-
<div data-id="searchPending" id="search_pending">
|
|
124
|
-
<p>Your search results will appear below</p>
|
|
125
|
-
<div class="loader tc mt20"></div>
|
|
126
|
-
</div>
|
|
127
|
-
<ul data-id="results"></ul>
|
|
128
|
-
`;
|
|
129
|
-
return searchTray;
|
|
130
|
-
}
|
|
131
60
|
|
|
132
61
|
renderSearchNavigation() {
|
|
133
62
|
const selector = 'BRsearch-navigation';
|
|
134
|
-
$('.BRnav').before(`
|
|
63
|
+
$('.BRnav.BRnavMain').before(`
|
|
135
64
|
<div class="${selector}">
|
|
136
65
|
<button class="toggle-sidebar">
|
|
137
66
|
<h4>
|
|
@@ -215,17 +144,19 @@ class SearchView {
|
|
|
215
144
|
const start = pool.slice(0, pool.length / 2);
|
|
216
145
|
const end = pool.slice(pool.length / 2);
|
|
217
146
|
return closestTo((comparisonFn(start, end, comparator) ? start : end), comparator);
|
|
218
|
-
}
|
|
147
|
+
};
|
|
219
148
|
|
|
220
149
|
const closestPage = closestTo(matchPages, currentPage);
|
|
221
150
|
return this.matches.indexOf(this.matches.find((m) => m.par[0].page === closestPage));
|
|
222
151
|
}
|
|
223
152
|
|
|
224
153
|
updateResultsPosition() {
|
|
154
|
+
if (!this.dom.searchNavigation) return;
|
|
225
155
|
this.dom.searchNavigation.find('[data-id=resultsCount]').text(this.resultsPosition());
|
|
226
156
|
}
|
|
227
157
|
|
|
228
158
|
updateSearchNavigationButtons() {
|
|
159
|
+
if (!this.dom.searchNavigation) return;
|
|
229
160
|
this.dom.searchNavigation.find('.prev').attr('disabled', !this.currentMatchIndex);
|
|
230
161
|
this.dom.searchNavigation.find('.next').attr('disabled', this.currentMatchIndex + 1 === this.matches.length);
|
|
231
162
|
}
|
|
@@ -272,19 +203,6 @@ class SearchView {
|
|
|
272
203
|
this.updateSearchNavigationButtons();
|
|
273
204
|
}
|
|
274
205
|
|
|
275
|
-
/**
|
|
276
|
-
* @param {array} matches
|
|
277
|
-
*/
|
|
278
|
-
renderMatches(matches) {
|
|
279
|
-
const items = matches.map((match) => `
|
|
280
|
-
<li data-page="${match.par[0].page}" data-page-index="${this.br.leafNumToIndex(match.par[0].page)}">
|
|
281
|
-
<h4>Page ${match.par[0].page}</h4>
|
|
282
|
-
<p>${match.text.replace(this.matcher, '<mark>$1</mark>')}</p>
|
|
283
|
-
</li>
|
|
284
|
-
`);
|
|
285
|
-
this.dom.results.innerHTML = items.join('');
|
|
286
|
-
}
|
|
287
|
-
|
|
288
206
|
/**
|
|
289
207
|
* @param {boolean} bool
|
|
290
208
|
*/
|
|
@@ -293,23 +211,6 @@ class SearchView {
|
|
|
293
211
|
this.br.refs.$BRfooter.find('.BRsearch').css({ visibility: pinsVisibleState });
|
|
294
212
|
}
|
|
295
213
|
|
|
296
|
-
buildMobileDrawer() {
|
|
297
|
-
const mobileSearch = document.createElement('li');
|
|
298
|
-
mobileSearch.innerHTML = `
|
|
299
|
-
<span>
|
|
300
|
-
<span class="DrawerIconWrapper">
|
|
301
|
-
<img class="DrawerIcon" src="${this.br.imagesBaseURL}icon_search_button.svg" />
|
|
302
|
-
</span>
|
|
303
|
-
Search
|
|
304
|
-
</span>
|
|
305
|
-
<div data-id="search_slot">
|
|
306
|
-
</div>
|
|
307
|
-
`;
|
|
308
|
-
mobileSearch.querySelector('[data-id="search_slot"]').appendChild(this.dom.searchTray);
|
|
309
|
-
mobileSearch.classList.add('BRmobileMenu__search');
|
|
310
|
-
return mobileSearch;
|
|
311
|
-
}
|
|
312
|
-
|
|
313
214
|
buildToolbarSearch() {
|
|
314
215
|
const toolbarSearch = document.createElement('span');
|
|
315
216
|
toolbarSearch.classList.add('BRtoolbarSection', 'BRtoolbarSectionSearch');
|
|
@@ -317,7 +218,7 @@ class SearchView {
|
|
|
317
218
|
<form class="BRbooksearch desktop">
|
|
318
219
|
<input type="search" name="query" class="BRsearchInput" value="" placeholder="Search inside"/>
|
|
319
220
|
<button type="submit" class="BRsearchSubmit">
|
|
320
|
-
<img src="${this.br.imagesBaseURL}icon_search_button.svg" />
|
|
221
|
+
<img src="${this.br.options.imagesBaseURL}icon_search_button.svg" />
|
|
321
222
|
</button>
|
|
322
223
|
</form>
|
|
323
224
|
`;
|
|
@@ -329,25 +230,20 @@ class SearchView {
|
|
|
329
230
|
*/
|
|
330
231
|
renderPins(matches) {
|
|
331
232
|
matches.forEach((match) => {
|
|
332
|
-
const
|
|
333
|
-
const pageIndex = this.br.leafNumToIndex(match.par[0].page);
|
|
334
|
-
const pageNumber = this.br.getPageNum(pageIndex);
|
|
233
|
+
const pageIndex = this.br.book.leafNumToIndex(match.par[0].page);
|
|
335
234
|
const uiStringSearch = "Search result"; // i18n
|
|
336
|
-
const
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
.replace(this.matcher, '<b>$1</b>')
|
|
348
|
-
+ '...';
|
|
235
|
+
const percentThrough = this.br.constructor.util.cssPercentage(pageIndex, this.br.book.getNumLeafs() - 1);
|
|
236
|
+
|
|
237
|
+
let html = match.html;
|
|
238
|
+
if (html.length > 200) {
|
|
239
|
+
const start = Math.max(0, html.indexOf('<mark>') - 100);
|
|
240
|
+
if (start != 0) {
|
|
241
|
+
html = '…' + match.html
|
|
242
|
+
.substring(start)
|
|
243
|
+
// Make sure at word boundary though
|
|
244
|
+
.replace(/^\S+/, '');
|
|
245
|
+
}
|
|
349
246
|
}
|
|
350
|
-
|
|
351
247
|
// draw marker
|
|
352
248
|
$('<div>')
|
|
353
249
|
.addClass('BRsearch')
|
|
@@ -357,56 +253,56 @@ class SearchView {
|
|
|
357
253
|
.attr('title', uiStringSearch)
|
|
358
254
|
.append(`
|
|
359
255
|
<div class="BRquery">
|
|
360
|
-
<
|
|
361
|
-
<
|
|
256
|
+
<main>${html}</main>
|
|
257
|
+
<footer>Page ${match.displayPageNumber}</footer>
|
|
362
258
|
</div>
|
|
363
259
|
`)
|
|
364
|
-
.data({ pageIndex })
|
|
365
260
|
.appendTo(this.br.$('.BRnavline'))
|
|
366
|
-
.
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
.click(function (event) {
|
|
383
|
-
// closures are nested and deep, using an arrow function breaks references.
|
|
384
|
-
// Todo: update to arrow function & clean up closures
|
|
385
|
-
// to remove `bind` dependency
|
|
386
|
-
this.br._searchPluginGoToResult(+$(event.target).data('pageIndex'));
|
|
387
|
-
this.br.updateSearchHilites();
|
|
388
|
-
}.bind(this));
|
|
261
|
+
.on("mouseenter", (event) => {
|
|
262
|
+
// remove from other markers then turn on just for this
|
|
263
|
+
// XXX should be done when nav slider moves
|
|
264
|
+
const marker = event.currentTarget;
|
|
265
|
+
const tooltip = marker.querySelector('.BRquery');
|
|
266
|
+
const tooltipOffset = tooltip.getBoundingClientRect();
|
|
267
|
+
const targetOffset = marker.getBoundingClientRect();
|
|
268
|
+
const boxSizeAdjust = parseInt(getComputedStyle(tooltip).paddingLeft) * 2;
|
|
269
|
+
if (tooltipOffset.x - boxSizeAdjust < 0) {
|
|
270
|
+
tooltip.style.setProperty('transform', `translateX(-${targetOffset.left - boxSizeAdjust}px)`);
|
|
271
|
+
}
|
|
272
|
+
$('.BRsearch,.BRchapter').removeClass('front');
|
|
273
|
+
$(event.target).addClass('front');
|
|
274
|
+
})
|
|
275
|
+
.on("mouseleave", (event) => $(event.target).removeClass('front'))
|
|
276
|
+
.on("click", () => { this.br.plugins.search.jumpToMatch(match.matchIndex); });
|
|
389
277
|
});
|
|
390
278
|
}
|
|
391
279
|
|
|
392
280
|
/**
|
|
393
|
-
* @param {boolean}
|
|
281
|
+
* @param {boolean} show
|
|
394
282
|
*/
|
|
395
|
-
toggleSearchPending(
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
this.br.showProgressPopup("Search results will appear below...");
|
|
283
|
+
toggleSearchPending(show = false) {
|
|
284
|
+
if (show) {
|
|
285
|
+
this.br.showProgressPopup("Search results will appear below...", () => this.progressPopupClosed());
|
|
399
286
|
}
|
|
400
287
|
else {
|
|
401
288
|
this.br.removeProgressPopup();
|
|
402
289
|
}
|
|
403
290
|
}
|
|
404
291
|
|
|
405
|
-
|
|
292
|
+
/**
|
|
293
|
+
* Primary callback when user cancels search popup
|
|
294
|
+
*/
|
|
295
|
+
progressPopupClosed() {
|
|
296
|
+
this.toggleSearchPending();
|
|
297
|
+
this.cancelSearch();
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
renderErrorModal(textIsProcessing = false) {
|
|
301
|
+
const errorDetails = `${!textIsProcessing ? 'The text may still be processing. ' : ''}Please try again.`;
|
|
406
302
|
this.renderModalMessage(`
|
|
407
303
|
Sorry, there was an error with your search.
|
|
408
304
|
<br />
|
|
409
|
-
|
|
305
|
+
${errorDetails}
|
|
410
306
|
`);
|
|
411
307
|
this.delayModalRemovalFor(4000);
|
|
412
308
|
}
|
|
@@ -445,14 +341,6 @@ class SearchView {
|
|
|
445
341
|
setTimeout(this.br.removeProgressPopup.bind(this.br), timeoutMS);
|
|
446
342
|
}
|
|
447
343
|
|
|
448
|
-
openMobileMenu() {
|
|
449
|
-
this.br.refs.$mmenu.data('mmenu').open();
|
|
450
|
-
}
|
|
451
|
-
|
|
452
|
-
closeMobileMenu() {
|
|
453
|
-
this.br.refs.$mmenu.data('mmenu').close();
|
|
454
|
-
}
|
|
455
|
-
|
|
456
344
|
/**
|
|
457
345
|
* @param {Event} e
|
|
458
346
|
*/
|
|
@@ -461,7 +349,6 @@ class SearchView {
|
|
|
461
349
|
const query = e.target.querySelector('[name="query"]').value;
|
|
462
350
|
if (!query.length) { return false; }
|
|
463
351
|
this.br.search(query);
|
|
464
|
-
this.dom.searchField.blur();
|
|
465
352
|
this.emptyMatches();
|
|
466
353
|
this.toggleSearchPending(true);
|
|
467
354
|
return false;
|
|
@@ -479,9 +366,7 @@ class SearchView {
|
|
|
479
366
|
this.teardownSearchNavigation();
|
|
480
367
|
this.renderSearchNavigation();
|
|
481
368
|
this.bindSearchNavigationEvents();
|
|
482
|
-
this.renderMatches(results.matches);
|
|
483
369
|
this.renderPins(results.matches);
|
|
484
|
-
this.updateResultsCount(results.matches.length);
|
|
485
370
|
this.toggleSearchPending(false);
|
|
486
371
|
if (options.goToFirstResult) {
|
|
487
372
|
$(document).one('BookReader:pageChanged', () => {
|
|
@@ -492,27 +377,23 @@ class SearchView {
|
|
|
492
377
|
}
|
|
493
378
|
}
|
|
494
379
|
|
|
495
|
-
/**
|
|
496
|
-
* @param {Event} e
|
|
497
|
-
*/
|
|
498
|
-
handleNavToggledCallback(e) {
|
|
499
|
-
const is_visible = this.br.navigationIsVisible();
|
|
500
|
-
this.togglePinsFor(is_visible);
|
|
501
|
-
this.toggleSearchTray(is_visible ? !!this.dom.results.querySelector('li') : false);
|
|
502
|
-
}
|
|
503
|
-
|
|
504
380
|
handleSearchStarted() {
|
|
505
381
|
this.emptyMatches();
|
|
506
|
-
this.br.removeSearchHilites();
|
|
382
|
+
this.br.plugins.search.removeSearchHilites();
|
|
507
383
|
this.removeResultPins();
|
|
508
384
|
this.toggleSearchPending(true);
|
|
509
385
|
this.teardownSearchNavigation();
|
|
510
|
-
this.setQuery(this.br.searchTerm);
|
|
386
|
+
this.setQuery(this.br.plugins.search.searchTerm);
|
|
511
387
|
}
|
|
512
388
|
|
|
513
|
-
|
|
389
|
+
/**
|
|
390
|
+
* Event listener for: `BookReader:SearchCallbackError`
|
|
391
|
+
* @param {CustomEvent} event
|
|
392
|
+
*/
|
|
393
|
+
handleSearchCallbackError(event = {}) {
|
|
514
394
|
this.toggleSearchPending(false);
|
|
515
|
-
|
|
395
|
+
const isIndexed = event?.detail?.props?.results?.indexed;
|
|
396
|
+
this.renderErrorModal(isIndexed);
|
|
516
397
|
}
|
|
517
398
|
|
|
518
399
|
handleSearchCallbackBookNotIndexed() {
|
|
@@ -528,26 +409,14 @@ class SearchView {
|
|
|
528
409
|
bindEvents() {
|
|
529
410
|
const namespace = 'BookReader:';
|
|
530
411
|
|
|
412
|
+
window.addEventListener(`${namespace}SearchCallbackError`, this.handleSearchCallbackError.bind(this));
|
|
531
413
|
$(document).on(`${namespace}SearchCallback`, this.handleSearchCallback.bind(this))
|
|
532
|
-
.on(`${namespace}navToggled`, this.handleNavToggledCallback.bind(this))
|
|
533
414
|
.on(`${namespace}SearchStarted`, this.handleSearchStarted.bind(this))
|
|
534
|
-
.on(`${namespace}SearchCallbackError`, this.handleSearchCallbackError.bind(this))
|
|
535
415
|
.on(`${namespace}SearchCallbackBookNotIndexed`, this.handleSearchCallbackBookNotIndexed.bind(this))
|
|
536
416
|
.on(`${namespace}SearchCallbackEmpty`, this.handleSearchCallbackEmpty.bind(this))
|
|
537
417
|
.on(`${namespace}pageChanged`, this.updateSearchNavigation.bind(this));
|
|
538
418
|
|
|
539
|
-
this.dom.searchTray.addEventListener('submit', this.submitHandler.bind(this));
|
|
540
419
|
this.dom.toolbarSearch.querySelector('form').addEventListener('submit', this.submitHandler.bind(this));
|
|
541
|
-
this.dom.searchField.addEventListener('search', () => {
|
|
542
|
-
if (this.dom.searchField.value) { return; }
|
|
543
|
-
this.clearSearchFieldAndResults();
|
|
544
|
-
});
|
|
545
|
-
|
|
546
|
-
$(this.dom.results).on('click', 'li', (e) => {
|
|
547
|
-
this.br._searchPluginGoToResult(+e.currentTarget.dataset.pageIndex);
|
|
548
|
-
this.br.updateSearchHilites();
|
|
549
|
-
this.closeMobileMenu();
|
|
550
|
-
});
|
|
551
420
|
}
|
|
552
421
|
}
|
|
553
422
|
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
import { Cache } from '../../util/cache.js';
|
|
3
|
+
import { BatchTranslator } from '@internetarchive/bergamot-translator/translator.js';
|
|
4
|
+
import { toISO6391, toNativeName } from '../tts/utils.js';
|
|
5
|
+
|
|
6
|
+
export class TranslationManager {
|
|
7
|
+
/** @type {Cache<{index: string, response: string}>} */
|
|
8
|
+
alreadyTranslated = new Cache(100);
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* @typedef {Object} genericModelInfo
|
|
12
|
+
* @property {string} name
|
|
13
|
+
* @property {number} size
|
|
14
|
+
* @property {number} estimatedCompressedSize
|
|
15
|
+
* @property {any} [qualityModel]
|
|
16
|
+
* @property {string} [expectedSha256Hash]
|
|
17
|
+
* @property {string} [modelType]
|
|
18
|
+
*/
|
|
19
|
+
/**
|
|
20
|
+
* @type { {[langPair: string] : {model: genericModelInfo, lex: genericModelInfo, vocab: genericModelInfo, quality?: genericModelInfo}} }
|
|
21
|
+
*/
|
|
22
|
+
modelRegistry = {};
|
|
23
|
+
|
|
24
|
+
/** @type {Record<key, {promise: Promise<string>, resolve: function, reject: function}>} */
|
|
25
|
+
currentlyTranslating = {}
|
|
26
|
+
|
|
27
|
+
/** @type {Record<string, string>[]} */
|
|
28
|
+
fromLanguages = [];
|
|
29
|
+
/** @type {Record<string, string>[]} */
|
|
30
|
+
toLanguages = [];
|
|
31
|
+
|
|
32
|
+
/** @type {boolean} */
|
|
33
|
+
active = false;
|
|
34
|
+
|
|
35
|
+
publicPath = '';
|
|
36
|
+
|
|
37
|
+
constructor() {
|
|
38
|
+
//TODO Should default to the book language as the first element
|
|
39
|
+
const enModel = {code: "en", name: "English (en)", type: "prod"};
|
|
40
|
+
this.fromLanguages.push(enModel);
|
|
41
|
+
this.toLanguages.push(enModel);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
async initWorker() {
|
|
46
|
+
if (this.initPromise) return this.initPromise;
|
|
47
|
+
this.initPromise = new Promise((resolve, reject) => {
|
|
48
|
+
this._initResolve = resolve;
|
|
49
|
+
this._initReject = reject;
|
|
50
|
+
});
|
|
51
|
+
const registryUrl = "https://cors.archive.org/cors/mozilla-translate-models/firefox_models/";
|
|
52
|
+
const registryJson = await fetch(registryUrl + "registry.json").then(r => r.json());
|
|
53
|
+
for (const language of Object.values(registryJson)) {
|
|
54
|
+
for (const file of Object.values(language)) {
|
|
55
|
+
file.name = registryUrl + file.name;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/** @type {BatchTranslator} */
|
|
60
|
+
// Arbitrary setting for number of workers, 1 is already quite fast
|
|
61
|
+
// batchSize from 8 -> 4 for improved performance
|
|
62
|
+
this.translator = new BatchTranslator({
|
|
63
|
+
registryUrl: `data:application/json,${encodeURIComponent(JSON.stringify(registryJson))}`,
|
|
64
|
+
workers: 2,
|
|
65
|
+
batchSize: 4,
|
|
66
|
+
workerUrl: this.publicPath + '/translator-worker.js',
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
const modelType = await this.translator.backing.registry;
|
|
70
|
+
const arr = {}; // unsure if we need to keep track of the files
|
|
71
|
+
for (const obj of Object.values(modelType)) {
|
|
72
|
+
const firstLang = obj['from'];
|
|
73
|
+
const secondLang = obj['to'];
|
|
74
|
+
const fromModelType = obj['files'];
|
|
75
|
+
arr[`${firstLang}${secondLang}`] = fromModelType;
|
|
76
|
+
// Assuming that all of the languages loaded from the registryUrl inside @internetarchive/bergamot-translator/translator.js are prod
|
|
77
|
+
// List of dev models found here https://github.com/mozilla/firefox-translations-models/tree/main/models/base
|
|
78
|
+
// There are also differences between the model types in the repo above here: https://github.com/mozilla/firefox-translations-models?tab=readme-ov-file#firefox-translations-models
|
|
79
|
+
if (firstLang !== "en") {
|
|
80
|
+
const name = `${toNativeName(firstLang)} (${toISO6391(firstLang)})`;
|
|
81
|
+
this.fromLanguages.push({code: firstLang, name: name, type: "prod"});
|
|
82
|
+
}
|
|
83
|
+
if (secondLang !== "en") {
|
|
84
|
+
const name = `${toNativeName(secondLang)} (${toISO6391(secondLang)})`;
|
|
85
|
+
this.toLanguages.push({code: secondLang, name: name, type: "prod"});
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
this._initResolve([this.modelRegistry]);
|
|
89
|
+
return this.initPromise;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Targets the page and paragraph of a text layer to create a translation from the "fromLang" to the "toLang". Tries to force order in translation by using the pageIndex (+1000 if the current page is not visible) and paragraphIndex
|
|
94
|
+
* @param {string} fromLang
|
|
95
|
+
* @param {string} toLang
|
|
96
|
+
* @param {string} pageIndex
|
|
97
|
+
* @param {number} paragraphIndex
|
|
98
|
+
* @param {string} text
|
|
99
|
+
* @param {number} priority
|
|
100
|
+
* @return {Promise<string>} translated text
|
|
101
|
+
*/
|
|
102
|
+
|
|
103
|
+
getTranslation = async (fromLang, toLang, pageIndex, paragraphIndex, text, priority) => {
|
|
104
|
+
this.active = true;
|
|
105
|
+
if (fromLang == toLang || !fromLang || !toLang) {
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
const key = `${fromLang}${toLang}-${pageIndex}:${paragraphIndex}`;
|
|
109
|
+
const cachedEntry = this.alreadyTranslated.entries.find(x => x.index == key);
|
|
110
|
+
|
|
111
|
+
if (cachedEntry) {
|
|
112
|
+
return cachedEntry.response;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
if (key in this.currentlyTranslating) {
|
|
116
|
+
return this.currentlyTranslating[key].promise;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
let _resolve = null;
|
|
120
|
+
let _reject = null;
|
|
121
|
+
const promise = new Promise((res, rej) => {
|
|
122
|
+
_resolve = res;
|
|
123
|
+
_reject = rej;
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
this.currentlyTranslating[key] = {
|
|
127
|
+
promise,
|
|
128
|
+
resolve: _resolve,
|
|
129
|
+
reject: _reject,
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
if (!text) {
|
|
133
|
+
this.currentlyTranslating[key].reject("No text was provided");
|
|
134
|
+
return promise;
|
|
135
|
+
}
|
|
136
|
+
this.translator.translate({
|
|
137
|
+
to: toLang,
|
|
138
|
+
from: fromLang,
|
|
139
|
+
text: text,
|
|
140
|
+
html: false,
|
|
141
|
+
priority: priority,
|
|
142
|
+
}).then((resp) => {
|
|
143
|
+
const response = resp;
|
|
144
|
+
this.currentlyTranslating[key].resolve(response.target.text);
|
|
145
|
+
this.alreadyTranslated.add({index: key, response: response.target.text});
|
|
146
|
+
delete this.currentlyTranslating[key];
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
return promise;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Checks and updates the status of a model that is currently being retreived from IA
|
|
154
|
+
* @param {string} fromLanguage
|
|
155
|
+
* @param {string} toLanguage
|
|
156
|
+
* @returns {Promise<boolean>}
|
|
157
|
+
*/
|
|
158
|
+
getTranslationModel = async(fromLanguage, toLanguage) => {
|
|
159
|
+
return this.translator.backing.getTranslationModel({from: fromLanguage, to: toLanguage})
|
|
160
|
+
.catch((err) => {
|
|
161
|
+
console.error(`An error occurred while trying to retreive the ${fromLanguage}-${toLanguage} model`);
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
}
|