@internetarchive/bookreader 5.0.0-9 → 5.0.0-90
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/.eslintrc.js +21 -19
- package/.github/workflows/node.js.yml +76 -11
- package/.github/workflows/npm-publish.yml +6 -20
- package/.testcaferc.js +10 -0
- package/BookReader/BookReader.css +404 -1125
- package/BookReader/BookReader.js +1 -1
- package/BookReader/BookReader.js.LICENSE.txt +20 -20
- package/BookReader/BookReader.js.map +1 -1
- 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/icon_book.svg +1 -1
- package/BookReader/images/icon_bookmark.svg +1 -1
- 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/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.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.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/webcomponents-bundle.js +3 -0
- package/BookReader/webcomponents-bundle.js.LICENSE.txt +9 -0
- package/BookReader/webcomponents-bundle.js.map +1 -0
- package/BookReaderDemo/BookReaderDemo.css +18 -19
- package/BookReaderDemo/BookReaderJSAdvanced.js +0 -3
- package/BookReaderDemo/BookReaderJSSimple.js +1 -0
- package/BookReaderDemo/IADemoBr.js +144 -0
- package/BookReaderDemo/demo-advanced.html +2 -2
- package/BookReaderDemo/demo-embed-iframe-src.html +2 -1
- package/BookReaderDemo/demo-fullscreen-mobile.html +3 -5
- package/BookReaderDemo/demo-fullscreen.html +2 -4
- package/BookReaderDemo/demo-iiif.html +99 -12
- package/BookReaderDemo/demo-internetarchive.html +214 -18
- package/BookReaderDemo/demo-multiple.html +2 -1
- package/BookReaderDemo/demo-preview-pages.html +526 -525
- package/BookReaderDemo/demo-simple.html +2 -1
- package/BookReaderDemo/demo-vendor-fullscreen.html +2 -4
- package/BookReaderDemo/ia-multiple-volumes-manifest.js +170 -0
- package/BookReaderDemo/immersion-1up.html +2 -2
- package/BookReaderDemo/immersion-mode.html +2 -4
- package/BookReaderDemo/toggle_controls.html +3 -2
- package/BookReaderDemo/view_mode.html +2 -1
- package/BookReaderDemo/viewmode-cycle.html +2 -3
- package/CHANGELOG.md +584 -33
- package/README.md +14 -1
- package/babel.config.js +20 -0
- package/codecov.yml +6 -0
- package/index.html +5 -2
- package/jsconfig.json +19 -0
- package/netlify.toml +9 -0
- package/package.json +70 -62
- package/renovate.json +52 -0
- package/scripts/preversion.js +0 -1
- package/src/BookNavigator/assets/bookmark-colors.js +1 -1
- package/src/BookNavigator/assets/button-base.js +5 -2
- 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 +590 -0
- package/src/BookNavigator/bookmarks/bookmark-button.js +3 -2
- package/src/BookNavigator/bookmarks/bookmark-edit.js +3 -4
- package/src/BookNavigator/bookmarks/bookmarks-list.js +2 -3
- package/src/BookNavigator/bookmarks/bookmarks-loginCTA.js +4 -9
- 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 +29 -25
- package/src/BookNavigator/search/search-provider.js +50 -28
- package/src/BookNavigator/search/search-results.js +24 -10
- 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 +7 -7
- package/src/BookReader/BookModel.js +76 -41
- package/src/BookReader/DragScrollable.js +233 -0
- package/src/BookReader/ImageCache.js +48 -15
- package/src/BookReader/Mode1Up.js +56 -351
- package/src/BookReader/Mode1UpLit.js +388 -0
- package/src/BookReader/Mode2Up.js +73 -1318
- package/src/BookReader/Mode2UpLit.js +777 -0
- package/src/BookReader/ModeCoordinateSpace.js +29 -0
- package/src/BookReader/ModeSmoothZoom.js +312 -0
- package/src/BookReader/ModeThumb.js +19 -13
- package/src/BookReader/Navbar/Navbar.js +70 -54
- package/src/BookReader/PageContainer.js +116 -22
- package/src/BookReader/ReduceSet.js +3 -3
- package/src/BookReader/Toolbar/Toolbar.js +14 -41
- package/src/BookReader/events.js +2 -3
- package/src/BookReader/options.js +73 -15
- 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 +128 -13
- package/src/BookReader.js +544 -1078
- package/src/BookReaderPlugin.js +44 -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/unviewable_page.png +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 -42
- package/src/css/_BRpages.scss +170 -42
- package/src/css/_BRsearch.scss +68 -25
- package/src/css/_BRtoolbar.scss +5 -5
- package/src/css/_TextSelection.scss +87 -27
- 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 +237 -191
- 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 +503 -175
- package/src/plugins/plugin.vendor-fullscreen.js +7 -7
- package/src/plugins/search/plugin.search.js +151 -127
- package/src/plugins/search/utils.js +43 -0
- package/src/plugins/search/view.js +37 -59
- package/src/plugins/tts/AbstractTTSEngine.js +75 -45
- package/src/plugins/tts/FestivalTTSEngine.js +21 -31
- package/src/plugins/tts/PageChunk.js +16 -23
- package/src/plugins/tts/PageChunkIterator.js +11 -17
- package/src/plugins/tts/WebTTSEngine.js +88 -72
- package/src/plugins/tts/plugin.tts.js +310 -350
- package/src/plugins/tts/utils.js +16 -26
- package/src/plugins/url/UrlPlugin.js +191 -0
- package/src/plugins/{plugin.url.js → url/plugin.url.js} +47 -18
- package/src/util/browserSniffing.js +22 -0
- package/src/util/docCookies.js +21 -2
- package/src/util/strings.js +1 -0
- package/tests/e2e/README.md +37 -0
- package/tests/e2e/autoplay.test.js +9 -6
- package/tests/e2e/base.test.js +8 -16
- package/tests/e2e/helpers/base.js +55 -50
- package/tests/e2e/helpers/debug.js +1 -1
- package/tests/e2e/helpers/mockSearch.js +19 -22
- package/tests/e2e/helpers/params.js +17 -0
- package/tests/e2e/helpers/rightToLeft.js +8 -14
- package/tests/e2e/helpers/search.js +73 -0
- package/tests/e2e/models/Navigation.js +20 -37
- package/tests/e2e/rightToLeft.test.js +4 -5
- package/tests/e2e/viewmode.test.js +40 -33
- package/tests/jest/BookNavigator/book-navigator.test.js +661 -0
- package/tests/jest/BookNavigator/bookmarks/bookmark-button.test.js +43 -0
- package/tests/{karma → jest}/BookNavigator/bookmarks/bookmark-edit.test.js +25 -26
- package/tests/{karma → jest}/BookNavigator/bookmarks/bookmarks-list.test.js +41 -42
- package/tests/jest/BookNavigator/bookmarks/ia-bookmarks.test.js +45 -0
- package/tests/jest/BookNavigator/downloads/downloads-provider.test.js +67 -0
- package/tests/jest/BookNavigator/downloads/downloads.test.js +53 -0
- package/tests/jest/BookNavigator/search/search-provider.test.js +167 -0
- package/tests/{karma → jest}/BookNavigator/search/search-results.test.js +109 -60
- package/tests/jest/BookNavigator/sharing/sharing-provider.test.js +49 -0
- package/tests/jest/BookNavigator/viewable-files/viewable-files-provider.test.js +80 -0
- package/tests/jest/BookNavigator/visual-adjustments.test.js +200 -0
- package/tests/{BookReader → jest/BookReader}/BookModel.test.js +74 -14
- package/tests/jest/BookReader/BookReaderPublicFunctions.test.js +193 -0
- package/tests/{BookReader → jest/BookReader}/ImageCache.test.js +4 -4
- package/tests/jest/BookReader/Mode1UpLit.test.js +73 -0
- package/tests/jest/BookReader/Mode2Up.test.js +98 -0
- package/tests/jest/BookReader/Mode2UpLit.test.js +190 -0
- package/tests/jest/BookReader/ModeCoordinateSpace.test.js +16 -0
- package/tests/jest/BookReader/ModeSmoothZoom.test.js +218 -0
- package/tests/jest/BookReader/ModeThumb.test.js +71 -0
- package/tests/{BookReader → jest/BookReader}/Navbar/Navbar.test.js +42 -29
- package/tests/jest/BookReader/PageContainer.test.js +238 -0
- package/tests/{BookReader → jest/BookReader}/ReduceSet.test.js +1 -1
- package/tests/{BookReader → jest/BookReader}/Toolbar/Toolbar.test.js +3 -3
- package/tests/jest/BookReader/utils/HTMLDimensionsCacher.test.js +59 -0
- package/tests/jest/BookReader/utils/ScrollClassAdder.test.js +49 -0
- package/tests/jest/BookReader/utils/SelectionObserver.test.js +57 -0
- package/tests/{BookReader → jest/BookReader}/utils/classes.test.js +1 -1
- package/tests/jest/BookReader/utils.test.js +250 -0
- package/tests/jest/BookReader.keyboard.test.js +190 -0
- package/tests/{BookReader.options.test.js → jest/BookReader.options.test.js} +10 -2
- package/tests/{BookReader.test.js → jest/BookReader.test.js} +43 -53
- package/tests/jest/plugins/plugin.archive_analytics.test.js +20 -0
- package/tests/jest/plugins/plugin.autoplay.test.js +35 -0
- package/tests/jest/plugins/plugin.chapters.test.js +195 -0
- package/tests/{plugins → jest/plugins}/plugin.iframe.test.js +4 -4
- package/tests/{plugins → jest/plugins}/plugin.resume.test.js +22 -35
- package/tests/jest/plugins/plugin.text_selection.test.js +316 -0
- package/tests/{plugins → jest/plugins}/plugin.vendor-fullscreen.test.js +2 -2
- package/tests/{plugins → jest/plugins}/search/plugin.search.test.js +19 -47
- package/tests/{plugins → jest/plugins}/search/plugin.search.view.test.js +42 -9
- package/tests/jest/plugins/search/utils.js +25 -0
- package/tests/jest/plugins/search/utils.test.js +29 -0
- package/tests/{plugins → jest/plugins}/tts/AbstractTTSEngine.test.js +30 -10
- package/tests/{plugins → jest/plugins}/tts/FestivalTTSEngine.test.js +4 -4
- package/tests/{plugins → jest/plugins}/tts/PageChunk.test.js +1 -1
- package/tests/{plugins → jest/plugins}/tts/PageChunkIterator.test.js +3 -3
- package/tests/{plugins → jest/plugins}/tts/WebTTSEngine.test.js +47 -1
- package/tests/{plugins → jest/plugins}/tts/utils.test.js +1 -60
- package/tests/jest/plugins/url/UrlPlugin.test.js +198 -0
- package/tests/{plugins → jest/plugins/url}/plugin.url.test.js +57 -18
- package/tests/jest/setup.js +3 -0
- package/tests/{util → jest/util}/browserSniffing.test.js +1 -1
- package/tests/jest/util/docCookies.test.js +24 -0
- package/tests/{util → jest/util}/strings.test.js +1 -1
- package/tests/{utils.js → jest/utils.js} +38 -0
- package/webpack.config.js +16 -10
- package/.babelrc +0 -12
- package/.dependabot/config.yml +0 -6
- 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/BookReaderJSAutoplay.js +0 -56
- package/BookReaderDemo/IIIFBookReader.js +0 -207
- package/BookReaderDemo/bookreader-template-bundle.js +0 -7178
- package/BookReaderDemo/demo-autoplay.html +0 -38
- package/BookReaderDemo/demo-iiif.js +0 -26
- package/BookReaderDemo/demo-plugin-menu-toggle.html +0 -34
- package/karma.conf.js +0 -23
- 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/BookReaderPublicFunctions.test.js +0 -171
- package/tests/BookReader/DebugConsole.test.js +0 -25
- package/tests/BookReader/Mode1Up.test.js +0 -164
- package/tests/BookReader/Mode2Up.test.js +0 -247
- package/tests/BookReader/PageContainer.test.js +0 -115
- package/tests/BookReader/utils.test.js +0 -109
- package/tests/e2e/helpers/desktopSearch.js +0 -72
- package/tests/e2e/helpers/mobileSearch.js +0 -85
- package/tests/e2e/ia-production/ia-prod-base.js +0 -17
- package/tests/karma/BookNavigator/book-navigator.test.js +0 -132
- package/tests/karma/BookNavigator/search/search-provider.test.js +0 -23
- 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.mobile_nav.test.js +0 -66
- package/tests/plugins/plugin.text_selection.test.js +0 -203
- package/tests/util/docCookies.test.js +0 -15
@@ -9,17 +9,15 @@ class SearchView {
|
|
9
9
|
*/
|
10
10
|
constructor({ br, searchCancelledCallback = () => {} }) {
|
11
11
|
this.br = br;
|
12
|
-
|
13
|
-
// Search results are returned as a text blob with the hits wrapped in
|
14
|
-
// triple mustaches. Hits occasionally include text beyond the search
|
15
|
-
// term, so everything within the staches is captured and wrapped.
|
16
|
-
this.matcher = new RegExp('{{{(.+?)}}}', 'g');
|
17
12
|
this.matches = [];
|
18
13
|
this.cacheDOMElements();
|
19
|
-
this.bindEvents();
|
20
14
|
this.cancelSearch = searchCancelledCallback;
|
21
15
|
}
|
22
16
|
|
17
|
+
init() {
|
18
|
+
this.bindEvents();
|
19
|
+
}
|
20
|
+
|
23
21
|
cacheDOMElements() {
|
24
22
|
this.dom = {};
|
25
23
|
// Search input within the top toolbar. Will be removed once the mobile menu is replaced.
|
@@ -142,17 +140,19 @@ class SearchView {
|
|
142
140
|
const start = pool.slice(0, pool.length / 2);
|
143
141
|
const end = pool.slice(pool.length / 2);
|
144
142
|
return closestTo((comparisonFn(start, end, comparator) ? start : end), comparator);
|
145
|
-
}
|
143
|
+
};
|
146
144
|
|
147
145
|
const closestPage = closestTo(matchPages, currentPage);
|
148
146
|
return this.matches.indexOf(this.matches.find((m) => m.par[0].page === closestPage));
|
149
147
|
}
|
150
148
|
|
151
149
|
updateResultsPosition() {
|
150
|
+
if (!this.dom.searchNavigation) return;
|
152
151
|
this.dom.searchNavigation.find('[data-id=resultsCount]').text(this.resultsPosition());
|
153
152
|
}
|
154
153
|
|
155
154
|
updateSearchNavigationButtons() {
|
155
|
+
if (!this.dom.searchNavigation) return;
|
156
156
|
this.dom.searchNavigation.find('.prev').attr('disabled', !this.currentMatchIndex);
|
157
157
|
this.dom.searchNavigation.find('.next').attr('disabled', this.currentMatchIndex + 1 === this.matches.length);
|
158
158
|
}
|
@@ -226,25 +226,20 @@ class SearchView {
|
|
226
226
|
*/
|
227
227
|
renderPins(matches) {
|
228
228
|
matches.forEach((match) => {
|
229
|
-
const
|
230
|
-
const pageIndex = this.br.leafNumToIndex(match.par[0].page);
|
231
|
-
const pageNumber = this.br.getPageNum(pageIndex);
|
229
|
+
const pageIndex = this.br.book.leafNumToIndex(match.par[0].page);
|
232
230
|
const uiStringSearch = "Search result"; // i18n
|
233
|
-
const
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
.replace(this.matcher, '<b>$1</b>')
|
245
|
-
+ '...';
|
231
|
+
const percentThrough = this.br.constructor.util.cssPercentage(pageIndex, this.br.book.getNumLeafs() - 1);
|
232
|
+
|
233
|
+
let html = match.html;
|
234
|
+
if (html.length > 200) {
|
235
|
+
const start = Math.max(0, html.indexOf('<mark>') - 100);
|
236
|
+
if (start != 0) {
|
237
|
+
html = '…' + match.html
|
238
|
+
.substring(start)
|
239
|
+
// Make sure at word boundary though
|
240
|
+
.replace(/^\S+/, '');
|
241
|
+
}
|
246
242
|
}
|
247
|
-
|
248
243
|
// draw marker
|
249
244
|
$('<div>')
|
250
245
|
.addClass('BRsearch')
|
@@ -254,35 +249,27 @@ class SearchView {
|
|
254
249
|
.attr('title', uiStringSearch)
|
255
250
|
.append(`
|
256
251
|
<div class="BRquery">
|
257
|
-
<
|
258
|
-
<
|
252
|
+
<main>${html}</main>
|
253
|
+
<footer>Page ${match.displayPageNumber}</footer>
|
259
254
|
</div>
|
260
255
|
`)
|
261
|
-
.data({ pageIndex })
|
262
256
|
.appendTo(this.br.$('.BRnavline'))
|
263
|
-
.
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
.click(function (event) {
|
280
|
-
// closures are nested and deep, using an arrow function breaks references.
|
281
|
-
// Todo: update to arrow function & clean up closures
|
282
|
-
// to remove `bind` dependency
|
283
|
-
this.br._searchPluginGoToResult(+$(event.target).data('pageIndex'));
|
284
|
-
this.br.updateSearchHilites();
|
285
|
-
}.bind(this));
|
257
|
+
.on("mouseenter", (event) => {
|
258
|
+
// remove from other markers then turn on just for this
|
259
|
+
// XXX should be done when nav slider moves
|
260
|
+
const marker = event.currentTarget;
|
261
|
+
const tooltip = marker.querySelector('.BRquery');
|
262
|
+
const tooltipOffset = tooltip.getBoundingClientRect();
|
263
|
+
const targetOffset = marker.getBoundingClientRect();
|
264
|
+
const boxSizeAdjust = parseInt(getComputedStyle(tooltip).paddingLeft) * 2;
|
265
|
+
if (tooltipOffset.x - boxSizeAdjust < 0) {
|
266
|
+
tooltip.style.setProperty('transform', `translateX(-${targetOffset.left - boxSizeAdjust}px)`);
|
267
|
+
}
|
268
|
+
$('.BRsearch,.BRchapter').removeClass('front');
|
269
|
+
$(event.target).addClass('front');
|
270
|
+
})
|
271
|
+
.on("mouseleave", (event) => $(event.target).removeClass('front'))
|
272
|
+
.on("click", () => { this.br._searchPluginGoToResult(match.matchIndex); });
|
286
273
|
});
|
287
274
|
}
|
288
275
|
|
@@ -386,14 +373,6 @@ class SearchView {
|
|
386
373
|
}
|
387
374
|
}
|
388
375
|
|
389
|
-
/**
|
390
|
-
* @param {Event} e
|
391
|
-
*/
|
392
|
-
handleNavToggledCallback(e) {
|
393
|
-
const is_visible = this.br.navigationIsVisible();
|
394
|
-
this.togglePinsFor(is_visible);
|
395
|
-
}
|
396
|
-
|
397
376
|
handleSearchStarted() {
|
398
377
|
this.emptyMatches();
|
399
378
|
this.br.removeSearchHilites();
|
@@ -428,7 +407,6 @@ class SearchView {
|
|
428
407
|
|
429
408
|
window.addEventListener(`${namespace}SearchCallbackError`, this.handleSearchCallbackError.bind(this));
|
430
409
|
$(document).on(`${namespace}SearchCallback`, this.handleSearchCallback.bind(this))
|
431
|
-
.on(`${namespace}navToggled`, this.handleNavToggledCallback.bind(this))
|
432
410
|
.on(`${namespace}SearchStarted`, this.handleSearchStarted.bind(this))
|
433
411
|
.on(`${namespace}SearchCallbackBookNotIndexed`, this.handleSearchCallbackBookNotIndexed.bind(this))
|
434
412
|
.on(`${namespace}SearchCallbackEmpty`, this.handleSearchCallbackEmpty.bind(this))
|
@@ -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,17 +71,21 @@ 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
|
-
bookPath: this.opts.bookPath,
|
88
|
+
pageChunkUrl: this.opts.pageChunkUrl,
|
85
89
|
pageBufferSize: 5,
|
86
90
|
});
|
87
91
|
|
@@ -92,6 +96,7 @@ export default class AbstractTTSEngine {
|
|
92
96
|
stop() {
|
93
97
|
if (this.activeSound) this.activeSound.stop();
|
94
98
|
this.playing = false;
|
99
|
+
this.paused = true;
|
95
100
|
this._chunkIterator = null;
|
96
101
|
this.activeSound = null;
|
97
102
|
this.events.trigger('stop');
|
@@ -124,13 +129,26 @@ export default class AbstractTTSEngine {
|
|
124
129
|
}
|
125
130
|
|
126
131
|
/** @public */
|
127
|
-
jumpBackward() {
|
128
|
-
Promise.all([
|
132
|
+
async jumpBackward() {
|
133
|
+
await Promise.all([
|
129
134
|
this.activeSound.stop(),
|
130
135
|
this._chunkIterator.decrement()
|
131
|
-
.then(() => this._chunkIterator.decrement())
|
132
|
-
])
|
133
|
-
|
136
|
+
.then(() => this._chunkIterator.decrement()),
|
137
|
+
]);
|
138
|
+
this.step();
|
139
|
+
}
|
140
|
+
|
141
|
+
/** @param {string} voiceURI */
|
142
|
+
setVoice(voiceURI) {
|
143
|
+
// if the user actively selects a voice, don't re-choose best voice anymore
|
144
|
+
// MS Edge fires voices changed randomly very often
|
145
|
+
this.events.off('voiceschanged', this.updateBestVoice);
|
146
|
+
this.voice = this.getVoices().find(voice => voice.voiceURI === voiceURI);
|
147
|
+
// if the current book has a language set, store the selected voice with the book language as a suffix
|
148
|
+
if (this.opts.bookLanguage && hasLocalStorage()) {
|
149
|
+
localStorage.setItem(`BRtts-voice-${this.opts.bookLanguage}`, this.voice.voiceURI);
|
150
|
+
}
|
151
|
+
if (this.activeSound) this.activeSound.setVoice(this.voice);
|
134
152
|
}
|
135
153
|
|
136
154
|
/** @param {number} newRate */
|
@@ -140,36 +158,33 @@ export default class AbstractTTSEngine {
|
|
140
158
|
}
|
141
159
|
|
142
160
|
/** @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
|
-
});
|
161
|
+
async step() {
|
162
|
+
const chunk = await this._chunkIterator.next();
|
163
|
+
if (chunk == PageChunkIterator.AT_END) {
|
164
|
+
this.stop();
|
165
|
+
this.opts.onDone();
|
166
|
+
return;
|
167
|
+
}
|
168
|
+
this.opts.onLoadingStart();
|
169
|
+
const sound = this.createSound(chunk);
|
170
|
+
sound.chunk = chunk;
|
171
|
+
sound.rate = this.playbackRate;
|
172
|
+
sound.voice = this.voice;
|
173
|
+
sound.load(() => this.opts.onLoadingComplete());
|
174
|
+
|
175
|
+
this.opts.onLoadingComplete();
|
176
|
+
|
177
|
+
await this.opts.beforeChunkPlay(chunk);
|
178
|
+
|
179
|
+
if (!this.playing) return;
|
180
|
+
|
181
|
+
const playPromise = await this.playSound(sound)
|
182
|
+
.then(()=> this.opts.afterChunkPlay(sound.chunk));
|
183
|
+
|
184
|
+
if (this.paused) this.pause();
|
185
|
+
await playPromise;
|
186
|
+
|
187
|
+
if (this.playing) return this.step();
|
173
188
|
}
|
174
189
|
|
175
190
|
/**
|
@@ -212,10 +227,12 @@ export default class AbstractTTSEngine {
|
|
212
227
|
// user languages that match the book language
|
213
228
|
const matchingUserLangs = userLanguages.filter(lang => lang.startsWith(bookLanguage));
|
214
229
|
|
215
|
-
//
|
216
|
-
return AbstractTTSEngine.
|
230
|
+
// First try to find the last chosen voice from localStorage for the current book language
|
231
|
+
return AbstractTTSEngine.getMatchingStoredVoice(bookLangVoices, bookLanguage)
|
232
|
+
// Try to find voices that intersect these two sets
|
233
|
+
|| AbstractTTSEngine.getMatchingVoice(matchingUserLangs, bookLangVoices)
|
217
234
|
// no user languages match the books; let's return the best voice for the book language
|
218
|
-
(bookLangVoices.find(v => v.default) || bookLangVoices[0])
|
235
|
+
|| (bookLangVoices.find(v => v.default) || bookLangVoices[0])
|
219
236
|
// No voices match the book language? let's find a voice in the user's language
|
220
237
|
// and ignore book lang
|
221
238
|
|| AbstractTTSEngine.getMatchingVoice(userLanguages, voices)
|
@@ -223,6 +240,19 @@ export default class AbstractTTSEngine {
|
|
223
240
|
|| (voices.find(v => v.default) || voices[0]);
|
224
241
|
}
|
225
242
|
|
243
|
+
/**
|
244
|
+
* @private
|
245
|
+
* Get the voice last selected by the user for the book language from localStorage.
|
246
|
+
* Returns undefined if no voice is stored or found.
|
247
|
+
* @param {SpeechSynthesisVoice[]} voices browser voices to choose from
|
248
|
+
* @param {ISO6391} bookLanguage book language to look for
|
249
|
+
* @return {SpeechSynthesisVoice | undefined}
|
250
|
+
*/
|
251
|
+
static getMatchingStoredVoice(voices, bookLanguage) {
|
252
|
+
const storedVoice = hasLocalStorage() && localStorage.getItem(`BRtts-voice-${bookLanguage}`);
|
253
|
+
return (storedVoice ? voices.find(v => v.voiceURI === storedVoice) : undefined);
|
254
|
+
}
|
255
|
+
|
226
256
|
/**
|
227
257
|
* @private
|
228
258
|
* 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
|
|
@@ -107,7 +98,7 @@ class FestivalTTSSound {
|
|
107
98
|
this.sound = null;
|
108
99
|
this.rate = 1;
|
109
100
|
/** @type {function} calling this resolves the "play" promise */
|
110
|
-
this._finishResolver = null
|
101
|
+
this._finishResolver = null;
|
111
102
|
}
|
112
103
|
|
113
104
|
get loaded() {
|
@@ -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,20 @@ 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
|
-
|
31
|
-
|
32
|
-
url: `https://${server}/BookReader/BookReaderGetTextWrapper.php`,
|
33
|
-
dataType:'jsonp',
|
34
|
-
cache: true,
|
35
|
-
data: {
|
36
|
-
path: `${bookPath}_djvu.xml`,
|
37
|
-
page: leafIndex
|
38
|
-
},
|
39
|
-
error: rej,
|
40
|
-
})
|
41
|
-
.then(chunks => {
|
42
|
-
res(PageChunk._fromTextWrapperResponse(leafIndex, chunks));
|
43
|
-
});
|
25
|
+
static async fetch(pageChunkUrl, leafIndex) {
|
26
|
+
const chunks = await $.ajax({
|
27
|
+
type: 'GET',
|
28
|
+
url: applyVariables(pageChunkUrl, { pageIndex: leafIndex }),
|
29
|
+
cache: true,
|
30
|
+
xhrFields: {
|
31
|
+
withCredentials: window.br.protected,
|
32
|
+
},
|
44
33
|
});
|
34
|
+
return PageChunk._fromTextWrapperResponse(leafIndex, chunks);
|
45
35
|
}
|
46
36
|
|
47
37
|
/**
|
@@ -97,7 +87,10 @@ export default class PageChunk {
|
|
97
87
|
* @return {string}
|
98
88
|
*/
|
99
89
|
static _removeDanglingHyphens(text) {
|
100
|
-
|
90
|
+
// Some books mis-OCR a dangling hyphen as a ¬ (mathematical not sign) . Since in math
|
91
|
+
// the not sign should not appear followed by a space, we think we can safely assume
|
92
|
+
// this should be replaced.
|
93
|
+
return text.replace(/[-¬]\s+/g, '');
|
101
94
|
}
|
102
95
|
}
|
103
96
|
|
@@ -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
|
*/
|