@internetarchive/bookreader 5.0.0-10-alpha-3 → 5.0.0-101
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 +431 -1134
- package/BookReader/BookReader.js +1 -1
- 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 +1782 -0
- package/BookReader/ia-bookreader-bundle.js.LICENSE.txt +7 -0
- package/BookReader/ia-bookreader-bundle.js.map +1 -0
- package/BookReader/icons/1up.svg +1 -1
- package/BookReader/icons/2up.svg +1 -1
- package/BookReader/icons/advance.svg +1 -1
- package/BookReader/icons/chevron-right.svg +1 -1
- package/BookReader/icons/close-circle-dark.svg +1 -1
- package/BookReader/icons/close-circle.svg +1 -1
- package/BookReader/icons/fullscreen.svg +1 -1
- package/BookReader/icons/fullscreen_exit.svg +1 -1
- package/BookReader/icons/hamburger.svg +1 -1
- package/BookReader/icons/left-arrow.svg +1 -1
- package/BookReader/icons/magnify-minus.svg +1 -1
- package/BookReader/icons/magnify-plus.svg +1 -1
- package/BookReader/icons/magnify.svg +1 -1
- package/BookReader/icons/pause.svg +1 -1
- package/BookReader/icons/play.svg +1 -1
- package/BookReader/icons/playback-speed.svg +1 -1
- package/BookReader/icons/read-aloud.svg +1 -1
- package/BookReader/icons/review.svg +1 -1
- package/BookReader/icons/thumbnails.svg +1 -1
- package/BookReader/icons/voice.svg +1 -0
- package/BookReader/icons/volume-full.svg +1 -1
- package/BookReader/images/BRicons.svg +3 -3
- package/BookReader/images/books_graphic.svg +1 -1
- package/BookReader/images/hypothesis.ico +0 -0
- package/BookReader/images/icon_book.svg +1 -1
- package/BookReader/images/icon_bookmark.svg +1 -1
- package/BookReader/images/icon_experiment.svg +1 -0
- package/BookReader/images/icon_gear.svg +1 -1
- package/BookReader/images/icon_hamburger.svg +1 -1
- package/BookReader/images/icon_home.svg +1 -1
- package/BookReader/images/icon_info.svg +1 -1
- package/BookReader/images/icon_one_page.svg +1 -1
- package/BookReader/images/icon_pause.svg +1 -1
- package/BookReader/images/icon_play.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_skip-ahead.svg +1 -1
- package/BookReader/images/icon_skip-back.svg +1 -1
- package/BookReader/images/icon_speaker.svg +1 -1
- package/BookReader/images/icon_speaker_open.svg +1 -1
- package/BookReader/images/icon_thumbnails.svg +1 -1
- package/BookReader/images/icon_toc.svg +1 -1
- package/BookReader/images/icon_two_pages.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/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 -1
- package/BookReader/plugins/plugin.archive_analytics.js.map +1 -1
- package/BookReader/plugins/plugin.autoplay.js +1 -1
- package/BookReader/plugins/plugin.autoplay.js.map +1 -1
- package/BookReader/plugins/plugin.chapters.js +25 -1
- 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 -1
- 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 -1
- package/BookReader/plugins/plugin.resume.js.map +1 -1
- package/BookReader/plugins/plugin.search.js +2 -1
- 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 -1
- 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 +1 -1
- 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 -1
- package/BookReader/plugins/plugin.url.js.map +1 -1
- package/BookReader/plugins/plugin.vendor-fullscreen.js +1 -1
- package/BookReader/plugins/plugin.vendor-fullscreen.js.map +1 -1
- package/BookReader/plugins/translator-worker.js +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 +84 -64
- package/src/BookNavigator/assets/bookmark-colors.js +1 -1
- package/src/BookNavigator/assets/button-base.js +2 -1
- package/src/BookNavigator/assets/ia-logo.js +17 -0
- package/src/BookNavigator/assets/icon_checkmark.js +1 -1
- package/src/BookNavigator/assets/icon_close.js +1 -1
- package/src/BookNavigator/book-navigator.js +620 -0
- package/src/BookNavigator/bookmarks/bookmark-button.js +3 -2
- package/src/BookNavigator/bookmarks/bookmark-edit.js +2 -3
- package/src/BookNavigator/bookmarks/bookmarks-list.js +2 -3
- package/src/BookNavigator/bookmarks/bookmarks-loginCTA.js +2 -2
- package/src/BookNavigator/bookmarks/bookmarks-provider.js +27 -17
- package/src/BookNavigator/bookmarks/ia-bookmarks.js +116 -67
- package/src/BookNavigator/delete-modal-actions.js +1 -1
- package/src/BookNavigator/downloads/downloads-provider.js +36 -21
- package/src/BookNavigator/downloads/downloads.js +24 -4
- package/src/BookNavigator/search/search-provider.js +55 -27
- package/src/BookNavigator/search/search-results.js +25 -11
- package/src/BookNavigator/sharing.js +27 -0
- package/src/BookNavigator/viewable-files.js +95 -0
- package/src/BookNavigator/visual-adjustments/visual-adjustments-provider.js +13 -12
- package/src/BookNavigator/visual-adjustments/visual-adjustments.js +9 -9
- 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 +58 -360
- package/src/BookReader/Mode1UpLit.js +393 -0
- package/src/BookReader/Mode2Up.js +75 -1318
- package/src/BookReader/Mode2UpLit.js +787 -0
- package/src/BookReader/ModeCoordinateSpace.js +29 -0
- package/src/BookReader/ModeSmoothZoom.js +312 -0
- package/src/BookReader/ModeThumb.js +20 -12
- package/src/BookReader/Navbar/Navbar.js +130 -53
- package/src/BookReader/PageContainer.js +120 -23
- package/src/BookReader/ReduceSet.js +2 -2
- package/src/BookReader/Toolbar/Toolbar.js +18 -40
- package/src/BookReader/events.js +2 -3
- package/src/BookReader/options.js +87 -16
- 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 +136 -12
- package/src/BookReader.js +641 -1192
- package/src/BookReaderPlugin.js +52 -0
- package/src/assets/icons/magnify-minus.svg +3 -7
- package/src/assets/icons/magnify-plus.svg +3 -7
- 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 -5
- 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 +16 -3
- package/src/css/_BRnav.scss +12 -66
- package/src/css/_BRpages.scss +171 -42
- package/src/css/_BRsearch.scss +69 -30
- 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 +1 -1
- package/src/ia-bookreader/ia-bookreader.js +224 -0
- package/src/plugins/plugin.archive_analytics.js +84 -78
- package/src/plugins/plugin.autoplay.js +99 -104
- package/src/plugins/plugin.chapters.js +314 -205
- 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 +54 -51
- package/src/plugins/plugin.text_selection.js +510 -219
- package/src/plugins/plugin.vendor-fullscreen.js +5 -5
- package/src/plugins/search/plugin.search.js +370 -392
- package/src/plugins/search/utils.js +43 -0
- package/src/plugins/search/view.js +49 -67
- package/src/plugins/translate/TranslationManager.js +162 -0
- package/src/plugins/translate/plugin.translate.js +523 -0
- package/src/plugins/tts/AbstractTTSEngine.js +78 -49
- package/src/plugins/tts/FestivalTTSEngine.js +20 -30
- 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 +344 -350
- package/src/plugins/tts/utils.js +49 -47
- package/src/plugins/url/UrlPlugin.js +191 -0
- package/src/plugins/{plugin.url.js → url/plugin.url.js} +44 -15
- 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/strings.js +1 -0
- package/.babelrc +0 -12
- package/.dependabot/config.yml +0 -6
- package/.eslintrc.js +0 -50
- 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 -37
- package/.github/workflows/npm-publish.yml +0 -47
- package/.testcaferc.json +0 -5
- package/BookReader/bookreader-component-bundle.js +0 -1450
- package/BookReader/bookreader-component-bundle.js.LICENSE.txt +0 -38
- package/BookReader/bookreader-component-bundle.js.map +0 -1
- package/BookReader/jquery-1.10.1.js +0 -2
- package/BookReader/jquery-1.10.1.js.LICENSE.txt +0 -24
- package/BookReader/plugins/plugin.menu_toggle.js +0 -2
- package/BookReader/plugins/plugin.menu_toggle.js.map +0 -1
- package/BookReader/plugins/plugin.mobile_nav.js +0 -2
- 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 -493
- 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 -446
- package/src/BookNavigator/assets/book-loader.js +0 -27
- package/src/BookNavigator/br-fullscreen-mgr.js +0 -83
- package/src/BookNavigator/search/a-search-result.js +0 -55
- package/src/BookReader/DebugConsole.js +0 -54
- package/src/BookReaderComponent/BookReaderComponent.js +0 -112
- package/src/ItemNavigator/ItemNavigator.js +0 -376
- package/src/ItemNavigator/providers/sharing.js +0 -29
- 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 -263
- 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/search-provider.test.js +0 -23
- package/tests/karma/BookNavigator/search/search-results.test.js +0 -240
- package/tests/karma/BookNavigator/visual-adjustments.test.js +0 -201
- 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 -173
- 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,12 +1,12 @@
|
|
|
1
1
|
import PageChunkIterator from './PageChunkIterator.js';
|
|
2
|
+
import { hasLocalStorage } from './utils.js';
|
|
2
3
|
/** @typedef {import('./utils.js').ISO6391} ISO6391 */
|
|
3
4
|
/** @typedef {import('./PageChunk.js')} PageChunk */
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* @export
|
|
7
8
|
* @typedef {Object} TTSEngineOptions
|
|
8
|
-
* @property {
|
|
9
|
-
* @property {String} bookPath
|
|
9
|
+
* @property {import('@/src/util/strings.js').StringWithVars} pageChunkUrl
|
|
10
10
|
* @property {ISO6391} bookLanguage
|
|
11
11
|
* @property {Function} onLoadingStart
|
|
12
12
|
* @property {Function} onLoadingComplete
|
|
@@ -28,6 +28,7 @@ import PageChunkIterator from './PageChunkIterator.js';
|
|
|
28
28
|
* @property {() => void} resume
|
|
29
29
|
* @property {() => void} finish force the sound to 'finish'
|
|
30
30
|
* @property {number => void} setPlaybackRate
|
|
31
|
+
* @property {SpeechSynthesisVoice => void} setVoice
|
|
31
32
|
**/
|
|
32
33
|
|
|
33
34
|
/** Handling bookreader's text-to-speech */
|
|
@@ -39,6 +40,7 @@ export default class AbstractTTSEngine {
|
|
|
39
40
|
constructor(options) {
|
|
40
41
|
this.playing = false;
|
|
41
42
|
this.paused = false;
|
|
43
|
+
/** @type {TTSEngineOptions} */
|
|
42
44
|
this.opts = options;
|
|
43
45
|
/** @type {PageChunkIterator} */
|
|
44
46
|
this._chunkIterator = null;
|
|
@@ -50,9 +52,7 @@ export default class AbstractTTSEngine {
|
|
|
50
52
|
/** @type {SpeechSynthesisVoice} */
|
|
51
53
|
this.voice = null;
|
|
52
54
|
// Listen for voice changes (fired by subclasses)
|
|
53
|
-
this.events.on('voiceschanged',
|
|
54
|
-
this.voice = AbstractTTSEngine.getBestBookVoice(this.getVoices(), this.opts.bookLanguage);
|
|
55
|
-
});
|
|
55
|
+
this.events.on('voiceschanged', this.updateBestVoice);
|
|
56
56
|
this.events.trigger('voiceschanged');
|
|
57
57
|
}
|
|
58
58
|
|
|
@@ -71,20 +71,23 @@ export default class AbstractTTSEngine {
|
|
|
71
71
|
/** @abstract */
|
|
72
72
|
init() { return null; }
|
|
73
73
|
|
|
74
|
+
updateBestVoice = () => {
|
|
75
|
+
this.voice = AbstractTTSEngine.getBestBookVoice(this.getVoices(), this.opts.bookLanguage);
|
|
76
|
+
}
|
|
77
|
+
|
|
74
78
|
/**
|
|
75
79
|
* @param {number} leafIndex
|
|
76
80
|
* @param {number} numLeafs total number of leafs in the current book
|
|
77
81
|
*/
|
|
78
82
|
start(leafIndex, numLeafs) {
|
|
79
83
|
this.playing = true;
|
|
84
|
+
this.paused = false;
|
|
80
85
|
this.opts.onLoadingStart();
|
|
81
86
|
|
|
82
87
|
this._chunkIterator = new PageChunkIterator(numLeafs, leafIndex, {
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
pageBufferSize: 5,
|
|
88
|
+
pageChunkUrl: this.opts.pageChunkUrl,
|
|
89
|
+
pageBufferSize: 3,
|
|
86
90
|
});
|
|
87
|
-
|
|
88
91
|
this.step();
|
|
89
92
|
this.events.trigger('start');
|
|
90
93
|
}
|
|
@@ -92,6 +95,7 @@ export default class AbstractTTSEngine {
|
|
|
92
95
|
stop() {
|
|
93
96
|
if (this.activeSound) this.activeSound.stop();
|
|
94
97
|
this.playing = false;
|
|
98
|
+
this.paused = true;
|
|
95
99
|
this._chunkIterator = null;
|
|
96
100
|
this.activeSound = null;
|
|
97
101
|
this.events.trigger('stop');
|
|
@@ -124,13 +128,26 @@ export default class AbstractTTSEngine {
|
|
|
124
128
|
}
|
|
125
129
|
|
|
126
130
|
/** @public */
|
|
127
|
-
jumpBackward() {
|
|
128
|
-
Promise.all([
|
|
131
|
+
async jumpBackward() {
|
|
132
|
+
await Promise.all([
|
|
129
133
|
this.activeSound.stop(),
|
|
130
134
|
this._chunkIterator.decrement()
|
|
131
|
-
.then(() => this._chunkIterator.decrement())
|
|
132
|
-
])
|
|
133
|
-
|
|
135
|
+
.then(() => this._chunkIterator.decrement()),
|
|
136
|
+
]);
|
|
137
|
+
this.step();
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/** @param {string} voiceURI */
|
|
141
|
+
setVoice(voiceURI) {
|
|
142
|
+
// if the user actively selects a voice, don't re-choose best voice anymore
|
|
143
|
+
// MS Edge fires voices changed randomly very often
|
|
144
|
+
this.events.off('voiceschanged', this.updateBestVoice);
|
|
145
|
+
this.voice = this.getVoices().find(voice => voice.voiceURI === voiceURI);
|
|
146
|
+
// if the current book has a language set, store the selected voice with the book language as a suffix
|
|
147
|
+
if (this.opts.bookLanguage && hasLocalStorage()) {
|
|
148
|
+
localStorage.setItem(`BRtts-voice-${this.opts.bookLanguage}`, this.voice.voiceURI);
|
|
149
|
+
}
|
|
150
|
+
if (this.activeSound) this.activeSound.setVoice(this.voice);
|
|
134
151
|
}
|
|
135
152
|
|
|
136
153
|
/** @param {number} newRate */
|
|
@@ -140,36 +157,33 @@ export default class AbstractTTSEngine {
|
|
|
140
157
|
}
|
|
141
158
|
|
|
142
159
|
/** @private */
|
|
143
|
-
step() {
|
|
144
|
-
this._chunkIterator.next()
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
.then(() => {
|
|
171
|
-
if (this.playing) return this.step();
|
|
172
|
-
});
|
|
160
|
+
async step() {
|
|
161
|
+
const chunk = await this._chunkIterator.next();
|
|
162
|
+
if (chunk == PageChunkIterator.AT_END) {
|
|
163
|
+
this.stop();
|
|
164
|
+
this.opts.onDone();
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
this.opts.onLoadingStart();
|
|
168
|
+
const sound = this.createSound(chunk);
|
|
169
|
+
sound.chunk = chunk;
|
|
170
|
+
sound.rate = this.playbackRate;
|
|
171
|
+
sound.voice = this.voice;
|
|
172
|
+
sound.load(() => this.opts.onLoadingComplete());
|
|
173
|
+
|
|
174
|
+
this.opts.onLoadingComplete();
|
|
175
|
+
|
|
176
|
+
await this.opts.beforeChunkPlay(chunk);
|
|
177
|
+
|
|
178
|
+
if (!this.playing) return;
|
|
179
|
+
|
|
180
|
+
const playPromise = await this.playSound(sound)
|
|
181
|
+
.then(()=> this.opts.afterChunkPlay(sound.chunk));
|
|
182
|
+
|
|
183
|
+
if (this.paused) this.pause();
|
|
184
|
+
await playPromise;
|
|
185
|
+
|
|
186
|
+
if (this.playing) return this.step();
|
|
173
187
|
}
|
|
174
188
|
|
|
175
189
|
/**
|
|
@@ -190,8 +204,8 @@ export default class AbstractTTSEngine {
|
|
|
190
204
|
}
|
|
191
205
|
|
|
192
206
|
/** Convenience wrapper for {@see AbstractTTSEngine.getBestVoice} */
|
|
193
|
-
getBestVoice() {
|
|
194
|
-
return AbstractTTSEngine.getBestBookVoice(this.getVoices(), this.opts.bookLanguage);
|
|
207
|
+
getBestVoice(languageOverride) {
|
|
208
|
+
return AbstractTTSEngine.getBestBookVoice(this.getVoices(), languageOverride || this.opts.bookLanguage);
|
|
195
209
|
}
|
|
196
210
|
|
|
197
211
|
/**
|
|
@@ -212,10 +226,12 @@ export default class AbstractTTSEngine {
|
|
|
212
226
|
// user languages that match the book language
|
|
213
227
|
const matchingUserLangs = userLanguages.filter(lang => lang.startsWith(bookLanguage));
|
|
214
228
|
|
|
215
|
-
//
|
|
216
|
-
return AbstractTTSEngine.
|
|
229
|
+
// First try to find the last chosen voice from localStorage for the current book language
|
|
230
|
+
return AbstractTTSEngine.getMatchingStoredVoice(bookLangVoices, bookLanguage)
|
|
231
|
+
// Try to find voices that intersect these two sets
|
|
232
|
+
|| AbstractTTSEngine.getMatchingVoice(matchingUserLangs, bookLangVoices)
|
|
217
233
|
// no user languages match the books; let's return the best voice for the book language
|
|
218
|
-
(bookLangVoices.find(v => v.default) || bookLangVoices[0])
|
|
234
|
+
|| (bookLangVoices.find(v => v.default) || bookLangVoices[0])
|
|
219
235
|
// No voices match the book language? let's find a voice in the user's language
|
|
220
236
|
// and ignore book lang
|
|
221
237
|
|| AbstractTTSEngine.getMatchingVoice(userLanguages, voices)
|
|
@@ -223,6 +239,19 @@ export default class AbstractTTSEngine {
|
|
|
223
239
|
|| (voices.find(v => v.default) || voices[0]);
|
|
224
240
|
}
|
|
225
241
|
|
|
242
|
+
/**
|
|
243
|
+
* @private
|
|
244
|
+
* Get the voice last selected by the user for the book language from localStorage.
|
|
245
|
+
* Returns undefined if no voice is stored or found.
|
|
246
|
+
* @param {SpeechSynthesisVoice[]} voices browser voices to choose from
|
|
247
|
+
* @param {ISO6391} bookLanguage book language to look for
|
|
248
|
+
* @return {SpeechSynthesisVoice | undefined}
|
|
249
|
+
*/
|
|
250
|
+
static getMatchingStoredVoice(voices, bookLanguage) {
|
|
251
|
+
const storedVoice = hasLocalStorage() && localStorage.getItem(`BRtts-voice-${bookLanguage}`);
|
|
252
|
+
return (storedVoice ? voices.find(v => v.voiceURI === storedVoice) : undefined);
|
|
253
|
+
}
|
|
254
|
+
|
|
226
255
|
/**
|
|
227
256
|
* @private
|
|
228
257
|
* Get the best voice that matches one of the BCP47 languages (order by preference)
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import AbstractTTSEngine from './AbstractTTSEngine.js';
|
|
2
|
-
import { sleep } from '
|
|
2
|
+
import { sleep } from '../../BookReader/utils.js';
|
|
3
|
+
import { applyVariables } from '../../util/strings.js';
|
|
3
4
|
/* global soundManager */
|
|
4
5
|
import 'soundmanager2';
|
|
5
6
|
import 'jquery.browser';
|
|
@@ -17,19 +18,21 @@ export default class FestivalTTSEngine extends AbstractTTSEngine {
|
|
|
17
18
|
return typeof(soundManager) !== 'undefined' && soundManager.supported();
|
|
18
19
|
}
|
|
19
20
|
|
|
20
|
-
/** @param {TTSEngineOptions} options */
|
|
21
|
+
/** @param {TTSEngineOptions | { festivalUrl: import('@/src/util/strings.js').StringWithVars }} options */
|
|
21
22
|
constructor(options) {
|
|
22
23
|
super(options);
|
|
23
24
|
// $.browsers is sometimes undefined on some Android browsers :/
|
|
24
25
|
// Likely related to when $.browser was moved to npm
|
|
25
26
|
/** @type {'mp3' | 'ogg'} format of audio to get */
|
|
26
|
-
this.audioFormat = $.browser?.mozilla ? 'ogg' : 'mp3';
|
|
27
|
+
this.audioFormat = $.browser?.mozilla ? 'ogg' : 'mp3'; //eslint-disable-line no-jquery/no-browser
|
|
28
|
+
/** @type {import('@/src/util/strings.js').StringWithVars} */
|
|
29
|
+
this.festivalUrl = options.festivalUrl;
|
|
27
30
|
}
|
|
28
31
|
|
|
29
32
|
/** @override */
|
|
30
33
|
getVoices() {
|
|
31
34
|
return [
|
|
32
|
-
{ default: true, lang: "en-US", localService: false, name: "Festival - English (US)", voiceURI: null }
|
|
35
|
+
{ default: true, lang: "en-US", localService: false, name: "Festival - English (US)", voiceURI: null },
|
|
33
36
|
];
|
|
34
37
|
}
|
|
35
38
|
|
|
@@ -45,7 +48,7 @@ export default class FestivalTTSEngine extends AbstractTTSEngine {
|
|
|
45
48
|
url: '/bookreader/BookReader/soundmanager/swf',
|
|
46
49
|
useHTML5Audio: true,
|
|
47
50
|
//flash 8 version of swf is buggy when calling play() on a sound that is still loading
|
|
48
|
-
flashVersion: 9
|
|
51
|
+
flashVersion: 9,
|
|
49
52
|
});
|
|
50
53
|
}
|
|
51
54
|
|
|
@@ -68,19 +71,7 @@ export default class FestivalTTSEngine extends AbstractTTSEngine {
|
|
|
68
71
|
|
|
69
72
|
/** @override */
|
|
70
73
|
createSound(chunk) {
|
|
71
|
-
return new FestivalTTSSound(this.
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
/**
|
|
75
|
-
* @private
|
|
76
|
-
* Get URL for audio that says this text
|
|
77
|
-
* @param {String} dataString the thing to say
|
|
78
|
-
* @return {String} url
|
|
79
|
-
*/
|
|
80
|
-
getSoundUrl(dataString) {
|
|
81
|
-
return 'https://' + this.opts.server + '/BookReader/BookReaderGetTTS.php?string='
|
|
82
|
-
+ encodeURIComponent(dataString)
|
|
83
|
-
+ '&format=.' + this.audioFormat;
|
|
74
|
+
return new FestivalTTSSound(applyVariables(this.festivalUrl, { text: chunk.text, format: this.audioFormat }));
|
|
84
75
|
}
|
|
85
76
|
|
|
86
77
|
/**
|
|
@@ -91,10 +82,10 @@ export default class FestivalTTSEngine extends AbstractTTSEngine {
|
|
|
91
82
|
* See https://stackoverflow.com/questions/12206631/html5-audio-cant-play-through-javascript-unless-triggered-manually-once
|
|
92
83
|
* @return {PromiseLike}
|
|
93
84
|
*/
|
|
94
|
-
iOSCaptureUserIntentHack() {
|
|
85
|
+
async iOSCaptureUserIntentHack() {
|
|
95
86
|
const sound = soundManager.createSound({ url: SILENCE_1MS[this.audioFormat] });
|
|
96
|
-
|
|
97
|
-
|
|
87
|
+
await new Promise(res => sound.play({onfinish: res}));
|
|
88
|
+
sound.destruct();
|
|
98
89
|
}
|
|
99
90
|
}
|
|
100
91
|
|
|
@@ -122,21 +113,20 @@ class FestivalTTSSound {
|
|
|
122
113
|
if (this.rate != 1) this.sound.setPlaybackRate(this.rate);
|
|
123
114
|
onload();
|
|
124
115
|
},
|
|
125
|
-
onresume: () => {
|
|
126
|
-
sleep(25)
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
}
|
|
116
|
+
onresume: async () => {
|
|
117
|
+
await sleep(25);
|
|
118
|
+
if (this.rate != 1) this.sound.setPlaybackRate(this.rate);
|
|
119
|
+
},
|
|
130
120
|
});
|
|
131
121
|
return this.sound.load();
|
|
132
122
|
}
|
|
133
123
|
|
|
134
|
-
play() {
|
|
135
|
-
|
|
124
|
+
async play() {
|
|
125
|
+
await new Promise(res => {
|
|
136
126
|
this._finishResolver = res;
|
|
137
127
|
this.sound.play({ onfinish: res });
|
|
138
|
-
})
|
|
139
|
-
|
|
128
|
+
});
|
|
129
|
+
this.sound.destruct();
|
|
140
130
|
}
|
|
141
131
|
|
|
142
132
|
/** @override */
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { applyVariables } from "../../util/strings.js";
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
* Class to manage a 'chunk' (approximately a paragraph) of text on a page.
|
|
3
5
|
*/
|
|
@@ -16,32 +18,39 @@ export default class PageChunk {
|
|
|
16
18
|
}
|
|
17
19
|
|
|
18
20
|
/**
|
|
19
|
-
* @param {
|
|
20
|
-
* @param {string} bookPath
|
|
21
|
+
* @param {import('@/src/util/strings.js').StringWithVars} pageChunkUrl
|
|
21
22
|
* @param {number} leafIndex
|
|
22
23
|
* @return {Promise<PageChunk[]>}
|
|
23
24
|
*/
|
|
24
|
-
static fetch(
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
25
|
+
static async fetch(pageChunkUrl, leafIndex) {
|
|
26
|
+
if (window.br.plugins.translate?.translationManager.active) {
|
|
27
|
+
const translateLayers = await window.br.plugins.translate.getTranslateLayers(leafIndex);
|
|
28
|
+
const paragraphs = Array.from(translateLayers[0].childNodes);
|
|
29
|
+
|
|
30
|
+
const pageChunks = [];
|
|
31
|
+
for (const [idx, item] of paragraphs.entries()) {
|
|
32
|
+
// Should not read paragraphs w/ header or footer roles
|
|
33
|
+
if (!item.classList.contains('ocr-role-header-footer')) {
|
|
34
|
+
const translatedChunk = new PageChunk(leafIndex, idx, item.textContent, []);
|
|
35
|
+
pageChunks.push(translatedChunk);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
if (pageChunks.length === 0) {
|
|
39
|
+
const placeholder = new PageChunk(leafIndex, 0, "", []);
|
|
40
|
+
pageChunks.push(placeholder);
|
|
41
|
+
}
|
|
42
|
+
return pageChunks;
|
|
43
|
+
} else {
|
|
44
|
+
const chunks = await $.ajax({
|
|
31
45
|
type: 'GET',
|
|
32
|
-
url:
|
|
33
|
-
dataType:'jsonp',
|
|
46
|
+
url: applyVariables(pageChunkUrl, { pageIndex: leafIndex }),
|
|
34
47
|
cache: true,
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
page: leafIndex
|
|
48
|
+
xhrFields: {
|
|
49
|
+
withCredentials: window.br.protected,
|
|
38
50
|
},
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
res(PageChunk._fromTextWrapperResponse(leafIndex, chunks));
|
|
43
|
-
});
|
|
44
|
-
});
|
|
51
|
+
});
|
|
52
|
+
return PageChunk._fromTextWrapperResponse(leafIndex, chunks);
|
|
53
|
+
}
|
|
45
54
|
}
|
|
46
55
|
|
|
47
56
|
/**
|
|
@@ -97,7 +106,10 @@ export default class PageChunk {
|
|
|
97
106
|
* @return {string}
|
|
98
107
|
*/
|
|
99
108
|
static _removeDanglingHyphens(text) {
|
|
100
|
-
|
|
109
|
+
// Some books mis-OCR a dangling hyphen as a ¬ (mathematical not sign) . Since in math
|
|
110
|
+
// the not sign should not appear followed by a space, we think we can safely assume
|
|
111
|
+
// this should be replaced.
|
|
112
|
+
return text.replace(/[-¬]\s+/g, '');
|
|
101
113
|
}
|
|
102
114
|
}
|
|
103
115
|
|
|
@@ -53,22 +53,18 @@ export default class PageChunkIterator {
|
|
|
53
53
|
* in the correct order.
|
|
54
54
|
* @return {PromiseLike<"__PageChunkIterator.AT_END__" | PageChunk>}
|
|
55
55
|
*/
|
|
56
|
-
_nextUncontrolled() {
|
|
56
|
+
async _nextUncontrolled() {
|
|
57
57
|
if (this._cursor.page == this.pageCount) {
|
|
58
58
|
return Promise.resolve(PageChunkIterator.AT_END);
|
|
59
59
|
}
|
|
60
|
-
|
|
61
60
|
this._recenterBuffer(this._cursor.page);
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
.
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
}
|
|
70
|
-
return chunks[this._cursor.chunk++];
|
|
71
|
-
});
|
|
61
|
+
const chunks = await this._fetchPageChunks(this._cursor.page);
|
|
62
|
+
if (this._cursor.chunk == chunks.length) {
|
|
63
|
+
this._cursor.page++;
|
|
64
|
+
this._cursor.chunk = 0;
|
|
65
|
+
return this._nextUncontrolled();
|
|
66
|
+
}
|
|
67
|
+
return chunks[this._cursor.chunk++];
|
|
72
68
|
}
|
|
73
69
|
|
|
74
70
|
/**
|
|
@@ -142,7 +138,7 @@ export default class PageChunkIterator {
|
|
|
142
138
|
* @param {number} index
|
|
143
139
|
*/
|
|
144
140
|
_fetchPageChunksDirect(index) {
|
|
145
|
-
return PageChunk.fetch(this.opts.
|
|
141
|
+
return PageChunk.fetch(this.opts.pageChunkUrl, index);
|
|
146
142
|
}
|
|
147
143
|
}
|
|
148
144
|
|
|
@@ -150,14 +146,12 @@ PageChunkIterator.AT_END = "__PageChunkIterator.AT_END__";
|
|
|
150
146
|
|
|
151
147
|
/** @type {PageChunkIteratorOptions} */
|
|
152
148
|
const DEFAULT_OPTS = {
|
|
153
|
-
|
|
154
|
-
bookPath: null,
|
|
149
|
+
pageChunkUrl: null,
|
|
155
150
|
pageBufferSize: 2,
|
|
156
151
|
};
|
|
157
152
|
|
|
158
153
|
/**
|
|
159
154
|
* @typedef {Object} PageChunkIteratorOptions
|
|
160
|
-
* @property {
|
|
161
|
-
* @property {string} bookPath
|
|
155
|
+
* @property {import('@/src/util/strings.js').StringWithVars} pageChunkUrl
|
|
162
156
|
* @property {number} [pageBufferSize] number of pages to buffer before/after the current page
|
|
163
157
|
*/
|