@internetarchive/bookreader 5.0.0-4 → 5.0.0-40-a1
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 +17 -15
- package/.github/workflows/node.js.yml +75 -4
- package/.github/workflows/npm-publish.yml +2 -16
- package/.testcaferc.js +10 -0
- package/BookReader/BookReader.css +83 -323
- package/BookReader/BookReader.js +1 -1
- package/BookReader/BookReader.js.LICENSE.txt +24 -0
- package/BookReader/BookReader.js.map +1 -1
- package/BookReader/ia-bookreader-bundle.js +1623 -0
- package/BookReader/{bookreader-component-bundle.js.LICENSE.txt → ia-bookreader-bundle.js.LICENSE.txt} +14 -10
- package/BookReader/ia-bookreader-bundle.js.map +1 -0
- package/BookReader/icons/close-circle-dark.svg +1 -0
- package/BookReader/icons/magnify-minus.svg +1 -1
- package/BookReader/icons/magnify-plus.svg +1 -1
- package/BookReader/icons/voice.svg +1 -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 +1 -1
- 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.mobile_nav.js +1 -1
- package/BookReader/plugins/plugin.mobile_nav.js.map +1 -1
- package/BookReader/plugins/plugin.resume.js +1 -1
- package/BookReader/plugins/plugin.resume.js.map +1 -1
- package/BookReader/plugins/plugin.search.js +1 -1
- package/BookReader/plugins/plugin.search.js.map +1 -1
- package/BookReader/plugins/plugin.text_selection.js +1 -1
- package/BookReader/plugins/plugin.text_selection.js.map +1 -1
- package/BookReader/plugins/plugin.tts.js +1 -1
- package/BookReader/plugins/plugin.tts.js.map +1 -1
- package/BookReader/plugins/plugin.url.js +1 -1
- package/BookReader/plugins/plugin.url.js.map +1 -1
- package/BookReader/plugins/plugin.vendor-fullscreen.js +1 -1
- package/BookReader/plugins/plugin.vendor-fullscreen.js.map +1 -1
- package/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 +14 -1
- package/BookReaderDemo/IADemoBr.js +120 -0
- package/BookReaderDemo/demo-advanced.html +1 -1
- package/BookReaderDemo/demo-autoplay.html +1 -0
- package/BookReaderDemo/demo-embed-iframe-src.html +1 -0
- package/BookReaderDemo/demo-fullscreen-mobile.html +1 -0
- package/BookReaderDemo/demo-fullscreen.html +1 -0
- package/BookReaderDemo/demo-iiif.html +1 -0
- package/BookReaderDemo/demo-internetarchive.html +74 -17
- package/BookReaderDemo/demo-multiple.html +1 -0
- package/BookReaderDemo/demo-preview-pages.html +1 -0
- package/BookReaderDemo/demo-simple.html +1 -0
- package/BookReaderDemo/demo-vendor-fullscreen.html +1 -0
- package/BookReaderDemo/ia-multiple-volumes-manifest.js +170 -0
- package/BookReaderDemo/immersion-1up.html +1 -0
- package/BookReaderDemo/immersion-mode.html +1 -0
- package/BookReaderDemo/toggle_controls.html +1 -0
- package/BookReaderDemo/view_mode.html +1 -0
- package/BookReaderDemo/viewmode-cycle.html +1 -2
- package/CHANGELOG.md +166 -0
- package/README.md +14 -1
- package/babel.config.js +18 -0
- package/codecov.yml +6 -0
- package/index.html +3 -0
- package/jsconfig.json +19 -0
- package/package.json +62 -47
- package/renovate.json +43 -0
- package/src/BookNavigator/assets/bookmark-colors.js +1 -1
- package/src/BookNavigator/assets/button-base.js +9 -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/assets/icon_sort_asc.js +5 -0
- package/src/BookNavigator/assets/icon_sort_desc.js +5 -0
- package/src/BookNavigator/assets/icon_sort_neutral.js +5 -0
- package/src/BookNavigator/assets/icon_volumes.js +11 -0
- package/src/BookNavigator/book-navigator.js +556 -0
- package/src/BookNavigator/bookmarks/bookmark-button.js +3 -2
- package/src/BookNavigator/bookmarks/bookmark-edit.js +4 -4
- package/src/BookNavigator/bookmarks/bookmarks-list.js +3 -3
- package/src/BookNavigator/bookmarks/bookmarks-loginCTA.js +3 -8
- package/src/BookNavigator/bookmarks/bookmarks-provider.js +23 -12
- package/src/BookNavigator/bookmarks/ia-bookmarks.js +98 -62
- package/src/BookNavigator/delete-modal-actions.js +1 -1
- package/src/BookNavigator/downloads/downloads-provider.js +23 -17
- package/src/BookNavigator/downloads/downloads.js +17 -25
- package/src/BookNavigator/search/a-search-result.js +3 -3
- package/src/BookNavigator/search/search-provider.js +57 -24
- package/src/BookNavigator/search/search-results.js +8 -20
- package/src/BookNavigator/sharing.js +27 -0
- package/src/BookNavigator/visual-adjustments/visual-adjustments-provider.js +11 -13
- package/src/BookNavigator/visual-adjustments/visual-adjustments.js +4 -3
- package/src/BookNavigator/volumes/volumes-provider.js +114 -0
- package/src/BookNavigator/volumes/volumes.js +188 -0
- package/src/BookReader/DebugConsole.js +3 -3
- package/src/BookReader/DragScrollable.js +233 -0
- package/src/BookReader/Mode1Up.js +51 -351
- package/src/BookReader/Mode1UpLit.js +441 -0
- package/src/BookReader/Mode2Up.js +104 -71
- package/src/BookReader/ModeSmoothZoom.js +179 -0
- package/src/BookReader/ModeThumb.js +16 -8
- package/src/BookReader/Navbar/Navbar.js +2 -31
- package/src/BookReader/PageContainer.js +57 -6
- package/src/BookReader/ReduceSet.js +1 -1
- package/src/BookReader/Toolbar/Toolbar.js +7 -7
- package/src/BookReader/options.js +10 -0
- package/src/BookReader/utils/HTMLDimensionsCacher.js +44 -0
- package/src/BookReader/utils/ScrollClassAdder.js +31 -0
- package/src/BookReader/utils.js +68 -13
- package/src/BookReader.js +375 -289
- 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/voice.svg +1 -0
- package/src/css/BookReader.scss +0 -12
- package/src/css/_BRComponent.scss +1 -1
- package/src/css/_BRmain.scss +19 -24
- package/src/css/_BRnav.scss +4 -26
- package/src/css/_BRpages.scss +35 -0
- package/src/css/_BRsearch.scss +11 -215
- package/src/css/_TextSelection.scss +14 -17
- package/src/css/_colorbox.scss +2 -2
- package/src/css/_controls.scss +16 -3
- package/src/css/_icons.scss +6 -0
- package/src/ia-bookreader/ia-bookreader.js +224 -0
- package/src/plugins/plugin.chapters.js +26 -33
- package/src/plugins/plugin.mobile_nav.js +11 -10
- package/src/plugins/plugin.resume.js +3 -3
- package/src/plugins/plugin.text_selection.js +26 -39
- package/src/plugins/plugin.vendor-fullscreen.js +4 -4
- package/src/plugins/search/plugin.search.js +106 -107
- package/src/plugins/search/view.js +50 -163
- package/src/plugins/tts/AbstractTTSEngine.js +46 -37
- package/src/plugins/tts/FestivalTTSEngine.js +12 -13
- package/src/plugins/tts/PageChunk.js +15 -21
- package/src/plugins/tts/PageChunkIterator.js +8 -12
- package/src/plugins/tts/WebTTSEngine.js +64 -68
- package/src/plugins/tts/plugin.tts.js +79 -108
- package/src/plugins/url/UrlPlugin.js +184 -0
- package/src/plugins/{plugin.url.js → url/plugin.url.js} +28 -6
- package/tests/e2e/README.md +37 -0
- package/tests/e2e/autoplay.test.js +2 -2
- package/tests/e2e/base.test.js +7 -7
- package/tests/e2e/helpers/base.js +8 -3
- package/tests/e2e/helpers/debug.js +1 -1
- package/tests/e2e/helpers/desktopSearch.js +14 -13
- package/tests/e2e/helpers/mobileSearch.js +3 -3
- package/tests/e2e/helpers/params.js +17 -0
- package/tests/e2e/models/Navigation.js +12 -3
- package/tests/e2e/rightToLeft.test.js +4 -5
- package/tests/e2e/viewmode.test.js +38 -33
- package/tests/{BookReader → jest/BookReader}/BookModel.test.js +3 -3
- package/tests/jest/BookReader/BookReaderPublicFunctions.test.js +176 -0
- package/tests/{BookReader → jest/BookReader}/DebugConsole.test.js +1 -1
- package/tests/{BookReader → jest/BookReader}/ImageCache.test.js +4 -4
- package/tests/jest/BookReader/Mode1UpLit.test.js +88 -0
- package/tests/{BookReader → jest/BookReader}/Mode2Up.test.js +5 -7
- package/tests/jest/BookReader/ModeSmoothZoom.test.js +149 -0
- package/tests/jest/BookReader/ModeThumb.test.js +71 -0
- package/tests/{BookReader → jest/BookReader}/Navbar/Navbar.test.js +7 -7
- package/tests/{BookReader → jest/BookReader}/PageContainer.test.js +79 -6
- package/tests/{BookReader → jest/BookReader}/ReduceSet.test.js +1 -1
- package/tests/{BookReader → jest/BookReader}/Toolbar/Toolbar.test.js +2 -2
- package/tests/jest/BookReader/utils/HTMLDimensionsCacher.test.js +59 -0
- package/tests/jest/BookReader/utils/ScrollClassAdder.test.js +49 -0
- package/tests/{BookReader → jest/BookReader}/utils/classes.test.js +1 -1
- package/tests/jest/BookReader/utils.test.js +136 -0
- package/tests/jest/BookReader.keyboard.test.js +190 -0
- package/tests/{BookReader.options.test.js → jest/BookReader.options.test.js} +9 -1
- package/tests/{BookReader.test.js → jest/BookReader.test.js} +20 -4
- package/tests/{plugins → jest/plugins}/plugin.archive_analytics.test.js +2 -2
- package/tests/{plugins → jest/plugins}/plugin.autoplay.test.js +2 -2
- package/tests/{plugins → jest/plugins}/plugin.chapters.test.js +8 -8
- package/tests/{plugins → jest/plugins}/plugin.iframe.test.js +2 -2
- package/tests/{plugins → jest/plugins}/plugin.mobile_nav.test.js +5 -5
- package/tests/{plugins → jest/plugins}/plugin.resume.test.js +3 -3
- package/tests/{plugins → jest/plugins}/plugin.text_selection.test.js +39 -47
- package/tests/{plugins → jest/plugins}/plugin.vendor-fullscreen.test.js +2 -2
- package/tests/{plugins → jest/plugins}/search/plugin.search.test.js +24 -25
- package/tests/{plugins → jest/plugins}/search/plugin.search.view.test.js +6 -6
- package/tests/{plugins → jest/plugins}/tts/AbstractTTSEngine.test.js +6 -6
- 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 +1 -1
- package/tests/{plugins → jest/plugins}/tts/utils.test.js +3 -3
- package/tests/jest/plugins/url/UrlPlugin.test.js +190 -0
- package/tests/{plugins → jest/plugins/url}/plugin.url.test.js +33 -14
- package/tests/{util → jest/util}/browserSniffing.test.js +1 -1
- package/tests/{util → jest/util}/docCookies.test.js +1 -1
- package/tests/{util → jest/util}/strings.test.js +1 -1
- package/tests/{utils.js → jest/utils.js} +38 -0
- package/tests/karma/BookNavigator/book-navigator.test.js +501 -0
- package/tests/karma/BookNavigator/bookmarks/bookmark-button.test.js +44 -0
- package/tests/karma/BookNavigator/bookmarks/bookmark-edit.test.js +1 -3
- package/tests/karma/BookNavigator/bookmarks/bookmarks-list.test.js +3 -4
- package/tests/karma/BookNavigator/bookmarks/ia-bookmarks.test.js +57 -0
- package/tests/karma/BookNavigator/downloads/downloads-provider.test.js +67 -0
- package/tests/karma/BookNavigator/downloads/downloads.test.js +54 -0
- package/tests/karma/BookNavigator/search/search-provider.test.js +123 -0
- package/tests/karma/BookNavigator/{search-results.test.js → search/search-results.test.js} +1 -4
- package/tests/karma/BookNavigator/sharing/sharing-provider.test.js +49 -0
- package/tests/karma/BookNavigator/visual-adjustments.test.js +0 -2
- package/tests/karma/BookNavigator/volumes/volumes-provider.test.js +184 -0
- package/tests/karma/BookNavigator/volumes/volumes.test.js +98 -0
- package/webpack.config.js +10 -4
- 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.map +0 -1
- package/BookReader/plugins/plugin.menu_toggle.js +0 -2
- package/BookReader/plugins/plugin.menu_toggle.js.map +0 -1
- package/BookReaderDemo/bookreader-template-bundle.js +0 -7178
- package/BookReaderDemo/demo-plugin-menu-toggle.html +0 -34
- package/src/BookNavigator/BookModel.js +0 -14
- package/src/BookNavigator/BookNavigator.js +0 -435
- package/src/BookNavigator/assets/book-loader.js +0 -27
- package/src/BookNavigator/br-fullscreen-mgr.js +0 -83
- package/src/BookReaderComponent/BookReaderComponent.js +0 -112
- package/src/ItemNavigator/ItemNavigator.js +0 -372
- package/src/ItemNavigator/providers/sharing.js +0 -29
- package/src/dragscrollable-br.js +0 -261
- package/src/plugins/menu_toggle/plugin.menu_toggle.js +0 -324
- package/tests/BookReader/BookReaderPublicFunctions.test.js +0 -171
- package/tests/BookReader/Mode1Up.test.js +0 -164
- package/tests/BookReader/utils.test.js +0 -109
- package/tests/plugins/menu_toggle/plugin.menu_toggle.test.js +0 -68
@@ -6,8 +6,9 @@ import FestivalTTSEngine from './FestivalTTSEngine.js';
|
|
6
6
|
import WebTTSEngine from './WebTTSEngine.js';
|
7
7
|
import { toISO6391, approximateWordCount } from './utils.js';
|
8
8
|
import { en as tooltips } from './tooltip_dict.js';
|
9
|
-
|
10
|
-
/** @typedef {import(
|
9
|
+
import { renderBoxesInPageContainerLayer } from '../../BookReader/PageContainer.js';
|
10
|
+
/** @typedef {import('./PageChunk.js').default} PageChunk */
|
11
|
+
/** @typedef {import("./AbstractTTSEngine.js").default} AbstractTTSEngine */
|
11
12
|
|
12
13
|
// Default options for TTS
|
13
14
|
jQuery.extend(BookReader.defaultOptions, {
|
@@ -22,7 +23,9 @@ BookReader.prototype.setup = (function (super_) {
|
|
22
23
|
super_.call(this, options);
|
23
24
|
|
24
25
|
if (this.options.enableTtsPlugin) {
|
25
|
-
|
26
|
+
/** @type { {[pageIndex: number]: Array<{ l: number, r: number, t: number, b: number }>} } */
|
27
|
+
this._ttsBoxesByIndex = {};
|
28
|
+
|
26
29
|
let TTSEngine = WebTTSEngine.isSupported() ? WebTTSEngine :
|
27
30
|
FestivalTTSEngine.isSupported() ? FestivalTTSEngine :
|
28
31
|
null;
|
@@ -54,17 +57,6 @@ BookReader.prototype.init = (function(super_) {
|
|
54
57
|
if (this.options.enableTtsPlugin) {
|
55
58
|
// Bind to events
|
56
59
|
|
57
|
-
// TODO move this to BookReader.js or something
|
58
|
-
this.bind(BookReader.eventNames.fragmentChange, () => {
|
59
|
-
if (this.mode == this.constMode2up) {
|
60
|
-
// clear highlights if they're no longer valid for this page
|
61
|
-
const visibleIndices = [this.twoPage.currentIndexL, this.twoPage.currentIndexR];
|
62
|
-
const visibleSelector = visibleIndices.map(i => `.BRReadAloudHilite.Leaf-${i}`).join(', ');
|
63
|
-
$(this.ttsHilites).filter(visibleSelector).show();
|
64
|
-
$(this.ttsHilites).not(visibleSelector).hide();
|
65
|
-
}
|
66
|
-
});
|
67
|
-
|
68
60
|
this.bind(BookReader.eventNames.PostInit, () => {
|
69
61
|
this.$('.BRicon.read').click(() => {
|
70
62
|
this.ttsToggle();
|
@@ -88,6 +80,17 @@ BookReader.prototype.init = (function(super_) {
|
|
88
80
|
};
|
89
81
|
})(BookReader.prototype.init);
|
90
82
|
|
83
|
+
/** @override */
|
84
|
+
BookReader.prototype._createPageContainer = (function (super_) {
|
85
|
+
return function (index) {
|
86
|
+
const pageContainer = super_.call(this, index);
|
87
|
+
if (this.options.enableTtsPlugin && pageContainer.page && index in this._ttsBoxesByIndex) {
|
88
|
+
const pageIndex = pageContainer.page.index;
|
89
|
+
renderBoxesInPageContainerLayer('ttsHiliteLayer', this._ttsBoxesByIndex[pageIndex], pageContainer.page, pageContainer.$container[0]);
|
90
|
+
}
|
91
|
+
return pageContainer;
|
92
|
+
};
|
93
|
+
})(BookReader.prototype._createPageContainer);
|
91
94
|
|
92
95
|
// Extend buildMobileDrawerElement
|
93
96
|
BookReader.prototype.buildMobileDrawerElement = (function (super_) {
|
@@ -146,15 +149,37 @@ BookReader.prototype.initNavbar = (function (super_) {
|
|
146
149
|
<div class="icon icon-advance"></div>
|
147
150
|
</button>
|
148
151
|
</li>
|
152
|
+
<li>
|
153
|
+
<select class="playback-voices" name="playback-voice" style="display: none" title="Change read aloud voices">
|
154
|
+
</select>
|
155
|
+
</li>
|
149
156
|
</ul>
|
150
157
|
`);
|
158
|
+
|
151
159
|
$el.find('.BRcontrols').prepend(this.refs.$BRReadAloudToolbar);
|
160
|
+
|
161
|
+
const renderVoicesMenu = (voicesMenu) => {
|
162
|
+
voicesMenu.empty();
|
163
|
+
if (this.ttsEngine.getVoices().length > 1) {
|
164
|
+
voicesMenu.append(this.ttsEngine.getVoices().map(
|
165
|
+
voice =>
|
166
|
+
$(`<option value="${voice.voiceURI}">${voice.lang} - ${voice.name}</option>`)));
|
167
|
+
voicesMenu.val(this.ttsEngine.voice.voiceURI);
|
168
|
+
voicesMenu.show();
|
169
|
+
} else {
|
170
|
+
voicesMenu.hide();
|
171
|
+
}
|
172
|
+
};
|
173
|
+
const voicesMenu = this.refs.$BRReadAloudToolbar.find('[name=playback-voice]');
|
174
|
+
renderVoicesMenu(voicesMenu);
|
175
|
+
voicesMenu.on("change", ev => this.ttsEngine.setVoice(voicesMenu.val()));
|
152
176
|
this.ttsEngine.events.on('pause resume start', () => this.ttsUpdateState());
|
153
|
-
this.
|
154
|
-
this.refs.$BRReadAloudToolbar.find('[name=
|
155
|
-
this.refs.$BRReadAloudToolbar.find('[name=
|
177
|
+
this.ttsEngine.events.on('voiceschanged', () => renderVoicesMenu(voicesMenu));
|
178
|
+
this.refs.$BRReadAloudToolbar.find('[name=play]').on("click", this.ttsPlayPause.bind(this));
|
179
|
+
this.refs.$BRReadAloudToolbar.find('[name=advance]').on("click", this.ttsJumpForward.bind(this));
|
180
|
+
this.refs.$BRReadAloudToolbar.find('[name=review]').on("click", this.ttsJumpBackward.bind(this));
|
156
181
|
const $rateSelector = this.refs.$BRReadAloudToolbar.find('select[name="playback-speed"]');
|
157
|
-
$rateSelector.change
|
182
|
+
$rateSelector.on("change", ev => this.ttsEngine.setPlaybackRate(parseFloat($rateSelector.val())));
|
158
183
|
$(`<li>
|
159
184
|
<button class="BRicon read js-tooltip" title="${tooltips.readAloud}">
|
160
185
|
<div class="icon icon-read-aloud"></div>
|
@@ -233,12 +258,10 @@ BookReader.prototype.ttsStop = function () {
|
|
233
258
|
* @param {PageChunk} chunk
|
234
259
|
* @return {PromiseLike<void>} returns once the flip is done
|
235
260
|
*/
|
236
|
-
BookReader.prototype.ttsBeforeChunkPlay = function(chunk) {
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
this.ttsScrollToChunk(chunk);
|
241
|
-
});
|
261
|
+
BookReader.prototype.ttsBeforeChunkPlay = async function(chunk) {
|
262
|
+
await this.ttsMaybeFlipToIndex(chunk.leafIndex);
|
263
|
+
this.ttsHighlightChunk(chunk);
|
264
|
+
this.ttsScrollToChunk(chunk);
|
242
265
|
};
|
243
266
|
|
244
267
|
/**
|
@@ -267,113 +290,61 @@ BookReader.prototype.ttsMaybeFlipToIndex = function (leafIndex) {
|
|
267
290
|
resolve();
|
268
291
|
} else {
|
269
292
|
this.animationFinishedCallback = resolve;
|
270
|
-
|
271
|
-
if (mustGoNext) this.next();
|
272
|
-
else this.prev();
|
273
|
-
promise.then(this.ttsMaybeFlipToIndex.bind(this, leafIndex));
|
293
|
+
this.jumpToIndex(leafIndex);
|
274
294
|
}
|
275
295
|
}
|
276
296
|
|
277
297
|
return promise;
|
278
|
-
}
|
279
|
-
|
280
|
-
/**
|
281
|
-
* @param {PageChunk} chunk
|
282
|
-
*/
|
283
|
-
BookReader.prototype.ttsHighlightChunk = function(chunk) {
|
284
|
-
this.ttsRemoveHilites();
|
285
|
-
|
286
|
-
if (this.constMode2up == this.mode) {
|
287
|
-
this.ttsHilite2UP(chunk);
|
288
|
-
} else {
|
289
|
-
this.ttsHilite1UP(chunk);
|
290
|
-
}
|
291
298
|
};
|
292
299
|
|
293
300
|
/**
|
294
301
|
* @param {PageChunk} chunk
|
295
302
|
*/
|
296
|
-
BookReader.prototype.
|
297
|
-
|
298
|
-
|
299
|
-
let leafTop = 0;
|
300
|
-
let h;
|
301
|
-
let i;
|
302
|
-
for (i = 0; i < chunk.leafIndex; i++) {
|
303
|
-
h = parseInt(this._getPageHeight(i) / this.reduce);
|
304
|
-
leafTop += h + this.padding;
|
305
|
-
}
|
306
|
-
|
307
|
-
const chunkTop = chunk.lineRects[0][3]; //coords are in l,b,r,t order
|
308
|
-
const chunkBot = chunk.lineRects[chunk.lineRects.length - 1][1];
|
309
|
-
|
310
|
-
const topOfFirstChunk = leafTop + chunkTop / this.reduce;
|
311
|
-
const botOfLastChunk = leafTop + chunkBot / this.reduce;
|
312
|
-
|
313
|
-
if (window?.soundManager?.debugMode) console.log('leafTop = ' + leafTop + ' topOfFirstChunk = ' + topOfFirstChunk + ' botOfLastChunk = ' + botOfLastChunk);
|
303
|
+
BookReader.prototype.ttsHighlightChunk = function(chunk) {
|
304
|
+
// The poorly-named variable leafIndex
|
305
|
+
const pageIndex = chunk.leafIndex;
|
314
306
|
|
315
|
-
|
316
|
-
const containerBot = containerTop + this.refs.$brContainer.height();
|
317
|
-
if (window?.soundManager?.debugMode) console.log('containerTop = ' + containerTop + ' containerBot = ' + containerBot);
|
307
|
+
this.ttsRemoveHilites();
|
318
308
|
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
};
|
309
|
+
// group by index; currently only possible to have chunks on one page :/
|
310
|
+
this._ttsBoxesByIndex = {
|
311
|
+
[pageIndex]: chunk.lineRects.map(([l, b, r, t]) => ({l, r, b, t}))
|
312
|
+
};
|
323
313
|
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
const l = chunk.lineRects[i][0];
|
331
|
-
const b = chunk.lineRects[i][1];
|
332
|
-
const r = chunk.lineRects[i][2];
|
333
|
-
const t = chunk.lineRects[i][3];
|
334
|
-
|
335
|
-
const div = document.createElement('div');
|
336
|
-
this.ttsHilites.push(div);
|
337
|
-
$(div).prop('className', 'BookReaderSearchHilite').appendTo(
|
338
|
-
this.$('.pagediv' + chunk.leafIndex)
|
339
|
-
);
|
340
|
-
|
341
|
-
$(div).css({
|
342
|
-
width: (r - l) / this.reduce + 'px',
|
343
|
-
height: (b - t) / this.reduce + 'px',
|
344
|
-
left: l / this.reduce + 'px',
|
345
|
-
top: t / this.reduce + 'px'
|
346
|
-
});
|
314
|
+
// update any already created pages
|
315
|
+
for (const [pageIndexString, boxes] of Object.entries(this._ttsBoxesByIndex)) {
|
316
|
+
const pageIndex = parseFloat(pageIndexString);
|
317
|
+
const page = this._models.book.getPage(pageIndex);
|
318
|
+
const pageContainers = this.getActivePageContainerElementsForIndex(pageIndex);
|
319
|
+
pageContainers.forEach(container => renderBoxesInPageContainerLayer('ttsHiliteLayer', boxes, page, container));
|
347
320
|
}
|
348
|
-
|
349
321
|
};
|
350
322
|
|
351
323
|
/**
|
352
324
|
* @param {PageChunk} chunk
|
353
325
|
*/
|
354
|
-
BookReader.prototype.
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
}
|
326
|
+
BookReader.prototype.ttsScrollToChunk = function(chunk) {
|
327
|
+
// It behaves weird if used in thumb mode
|
328
|
+
if (this.constModeThumb == this.mode) return;
|
329
|
+
|
330
|
+
$(`.pagediv${chunk.leafIndex} .ttsHiliteLayer rect`).last()?.[0]?.scrollIntoView({
|
331
|
+
// Only vertically center the highlight if we're in 1up or in full screen. In
|
332
|
+
// 2up, if we're not fullscreen, the whole body gets scrolled around to try to
|
333
|
+
// center the highlight 🙄 See:
|
334
|
+
// https://stackoverflow.com/questions/11039885/scrollintoview-causing-the-whole-page-to-move/11041376
|
335
|
+
// Note: nearest doesn't quite work great, because the ReadAloud toolbar is now
|
336
|
+
// full-width, and covers up the last line of the highlight.
|
337
|
+
block: this.constMode1up == this.mode || this.isFullscreenActive ? 'center' : 'nearest',
|
338
|
+
inline: 'center',
|
339
|
+
behavior: 'smooth',
|
340
|
+
});
|
370
341
|
};
|
371
342
|
|
372
343
|
// ttsRemoveHilites()
|
373
344
|
//______________________________________________________________________________
|
374
345
|
BookReader.prototype.ttsRemoveHilites = function () {
|
375
|
-
$(this.
|
376
|
-
this.
|
346
|
+
$(this.getActivePageContainerElements()).find('.ttsHiliteLayer').remove();
|
347
|
+
this._ttsBoxesByIndex = {};
|
377
348
|
};
|
378
349
|
|
379
350
|
/**
|
@@ -0,0 +1,184 @@
|
|
1
|
+
export class UrlPlugin {
|
2
|
+
constructor(options = {}) {
|
3
|
+
this.bookReaderOptions = options;
|
4
|
+
|
5
|
+
// the canonical order of elements is important in the path and query string
|
6
|
+
this.urlSchema = [
|
7
|
+
{ name: 'page', position: 'path', default: 'n0' },
|
8
|
+
{ name: 'mode', position: 'path', default: '2up' },
|
9
|
+
{ name: 'search', position: 'path', deprecated_for: 'q' },
|
10
|
+
{ name: 'q', position: 'query_param' },
|
11
|
+
{ name: 'sort', position: 'query_param' },
|
12
|
+
{ name: 'view', position: 'query_param' },
|
13
|
+
{ name: 'admin', position: 'query_param' },
|
14
|
+
];
|
15
|
+
|
16
|
+
this.urlState = {};
|
17
|
+
this.urlMode = this.bookReaderOptions.urlMode || 'hash';
|
18
|
+
this.urlHistoryBasePath = this.bookReaderOptions.urlHistoryBasePath || '/';
|
19
|
+
this.urlLocationPollId = null;
|
20
|
+
this.oldLocationHash = null;
|
21
|
+
this.oldUserHash = null;
|
22
|
+
}
|
23
|
+
|
24
|
+
/**
|
25
|
+
* Parse JSON object URL state to string format
|
26
|
+
* Arrange path names in an order that it is positioned on the urlSchema
|
27
|
+
* @param {Object} urlState
|
28
|
+
* @returns {string}
|
29
|
+
*/
|
30
|
+
urlStateToUrlString(urlState) {
|
31
|
+
const searchParams = new URLSearchParams();
|
32
|
+
const pathParams = {};
|
33
|
+
|
34
|
+
Object.keys(urlState).forEach(key => {
|
35
|
+
let schema = this.urlSchema.find(schema => schema.name === key);
|
36
|
+
if (schema?.deprecated_for) {
|
37
|
+
schema = this.urlSchema.find(schemaKey => schemaKey.name === schema.deprecated_for);
|
38
|
+
}
|
39
|
+
if (schema?.position == 'path') {
|
40
|
+
pathParams[schema?.name] = urlState[key];
|
41
|
+
} else {
|
42
|
+
searchParams.append(schema?.name || key, urlState[key]);
|
43
|
+
}
|
44
|
+
});
|
45
|
+
|
46
|
+
const strPathParams = this.urlSchema
|
47
|
+
.filter(s => s.position == 'path')
|
48
|
+
.map(schema => pathParams[schema.name] ? `${schema.name}/${pathParams[schema.name]}` : '')
|
49
|
+
.join('/');
|
50
|
+
|
51
|
+
// replace consecutive slashes with a single slash + remove trailing slashes
|
52
|
+
const strStrippedTrailingSlash = `${strPathParams.replace(/\/+/g, '/').replace(/\/+$/, '')}`;
|
53
|
+
const concatenatedPath = `${strStrippedTrailingSlash}?${searchParams.toString()}`;
|
54
|
+
return searchParams.toString() ? concatenatedPath : `${strStrippedTrailingSlash}`;
|
55
|
+
}
|
56
|
+
|
57
|
+
/**
|
58
|
+
* Parse string URL and add it in the current urlState
|
59
|
+
* Example:
|
60
|
+
* /page/n7/mode/2up => {page: 'n7', mode: '2up'}
|
61
|
+
* /page/n7/mode/2up/search/hello => {page: 'n7', mode: '2up', q: 'hello'}
|
62
|
+
* @param {string} urlString
|
63
|
+
* @returns {object}
|
64
|
+
*/
|
65
|
+
urlStringToUrlState(urlString) {
|
66
|
+
const urlState = {};
|
67
|
+
|
68
|
+
// Fetch searchParams from given {str}
|
69
|
+
// Note: whole URL path is needed for URL parsing
|
70
|
+
const urlPath = new URL(urlString, 'http://example.com');
|
71
|
+
const urlSearchParamsObj = Object.fromEntries(urlPath.searchParams.entries());
|
72
|
+
const splitUrlMatches = urlPath.pathname.match(/[^\\/]+\/[^\\/]+/g);
|
73
|
+
const urlStrSplitSlashObj = splitUrlMatches ? Object.fromEntries(splitUrlMatches.map(x => x.split('/'))) : {};
|
74
|
+
|
75
|
+
const doesKeyExists = (_object, _key) => {
|
76
|
+
return Object.keys(_object).some(value => value == _key);
|
77
|
+
};
|
78
|
+
|
79
|
+
// Add path objects to urlState
|
80
|
+
this.urlSchema
|
81
|
+
.filter(schema => schema.position == 'path')
|
82
|
+
.forEach(schema => {
|
83
|
+
const hasPropertyKey = doesKeyExists(urlStrSplitSlashObj, schema.name);
|
84
|
+
const hasDeprecatedKey = doesKeyExists(schema, 'deprecated_for') && hasPropertyKey;
|
85
|
+
|
86
|
+
if (hasDeprecatedKey) {
|
87
|
+
urlState[schema.deprecated_for] = urlStrSplitSlashObj[schema.name];
|
88
|
+
return;
|
89
|
+
}
|
90
|
+
|
91
|
+
if (hasPropertyKey) {
|
92
|
+
urlState[schema.name] = urlStrSplitSlashObj[schema.name];
|
93
|
+
return;
|
94
|
+
}
|
95
|
+
});
|
96
|
+
|
97
|
+
// Add searchParams to urlState
|
98
|
+
Object.entries(urlSearchParamsObj).forEach(([key, value]) => {
|
99
|
+
urlState[key] = value;
|
100
|
+
});
|
101
|
+
|
102
|
+
return urlState;
|
103
|
+
}
|
104
|
+
|
105
|
+
/**
|
106
|
+
* Add or update key-value to the urlState
|
107
|
+
* @param {string} key
|
108
|
+
* @param {string} val
|
109
|
+
*/
|
110
|
+
setUrlParam(key, value) {
|
111
|
+
this.urlState[key] = value;
|
112
|
+
|
113
|
+
this.pushToAddressBar();
|
114
|
+
}
|
115
|
+
|
116
|
+
/**
|
117
|
+
* Delete key-value to the urlState
|
118
|
+
* @param {string} key
|
119
|
+
*/
|
120
|
+
removeUrlParam(key) {
|
121
|
+
delete this.urlState[key];
|
122
|
+
|
123
|
+
this.pushToAddressBar();
|
124
|
+
}
|
125
|
+
|
126
|
+
/**
|
127
|
+
* Get key-value from the urlState
|
128
|
+
* @param {string} key
|
129
|
+
* @return {string}
|
130
|
+
*/
|
131
|
+
getUrlParam(key) {
|
132
|
+
return this.urlState[key];
|
133
|
+
}
|
134
|
+
|
135
|
+
/**
|
136
|
+
* Push URL params to addressbar
|
137
|
+
*/
|
138
|
+
pushToAddressBar() {
|
139
|
+
const urlStrPath = this.urlStateToUrlString(this.urlState);
|
140
|
+
const concatenatedPath = urlStrPath !== '/' ? urlStrPath : '';
|
141
|
+
if (this.urlMode == 'history') {
|
142
|
+
if (window.history && window.history.replaceState) {
|
143
|
+
const newUrlPath = `${this.urlHistoryBasePath}${concatenatedPath}`.trim().replace(/(\/+)/g, '/');
|
144
|
+
window.history.replaceState({}, null, newUrlPath);
|
145
|
+
}
|
146
|
+
} else {
|
147
|
+
window.location.replace('#' + concatenatedPath);
|
148
|
+
}
|
149
|
+
this.oldLocationHash = urlStrPath;
|
150
|
+
}
|
151
|
+
|
152
|
+
/**
|
153
|
+
* Get the url and check if it has changed
|
154
|
+
* If it was changeed, update the urlState
|
155
|
+
*/
|
156
|
+
listenForHashChanges() {
|
157
|
+
this.oldLocationHash = window.location.hash.substr(1);
|
158
|
+
if (this.urlLocationPollId) {
|
159
|
+
clearInterval(this.urlLocationPollId);
|
160
|
+
this.urlLocationPollId = null;
|
161
|
+
}
|
162
|
+
|
163
|
+
// check if the URL changes
|
164
|
+
const updateHash = () => {
|
165
|
+
const newFragment = window.location.hash.substr(1);
|
166
|
+
const hasFragmentChange = newFragment != this.oldLocationHash;
|
167
|
+
|
168
|
+
if (!hasFragmentChange) { return; }
|
169
|
+
|
170
|
+
this.urlState = this.urlStringToUrlState(newFragment);
|
171
|
+
};
|
172
|
+
this.urlLocationPollId = setInterval(updateHash, 500);
|
173
|
+
}
|
174
|
+
|
175
|
+
/**
|
176
|
+
* Will read either the hash or URL and return the bookreader fragment
|
177
|
+
*/
|
178
|
+
pullFromAddressBar (location = window.location) {
|
179
|
+
const path = this.urlMode === 'history'
|
180
|
+
? (location.pathname.substr(this.urlHistoryBasePath.length) + location.search)
|
181
|
+
: location.hash.substr(1);
|
182
|
+
this.urlState = this.urlStringToUrlState(path);
|
183
|
+
}
|
184
|
+
}
|
@@ -1,4 +1,7 @@
|
|
1
1
|
/* global BookReader */
|
2
|
+
|
3
|
+
import { UrlPlugin } from "./UrlPlugin";
|
4
|
+
|
2
5
|
/**
|
3
6
|
* Plugin for URL management in BookReader
|
4
7
|
* Note read more about the url "fragment" here:
|
@@ -22,7 +25,7 @@ jQuery.extend(BookReader.defaultOptions, {
|
|
22
25
|
urlHistoryBasePath: '/',
|
23
26
|
|
24
27
|
/** Only these params will be reflected onto the URL */
|
25
|
-
urlTrackedParams: ['page', 'search', 'mode', 'region', 'highlight'],
|
28
|
+
urlTrackedParams: ['page', 'search', 'mode', 'region', 'highlight', 'view'],
|
26
29
|
|
27
30
|
/** If true, don't update the URL when `page == n0 (eg "/page/n0")` */
|
28
31
|
urlTrackIndex0: false,
|
@@ -50,7 +53,7 @@ BookReader.prototype.init = (function(super_) {
|
|
50
53
|
this.bind(BookReader.eventNames.PostInit, () => {
|
51
54
|
const { updateWindowTitle, urlMode } = this.options;
|
52
55
|
if (updateWindowTitle) {
|
53
|
-
document.title = this.shortTitle(50);
|
56
|
+
document.title = this.shortTitle(this.bookTitle, 50);
|
54
57
|
}
|
55
58
|
if (urlMode === 'hash') {
|
56
59
|
this.urlStartLocationPolling();
|
@@ -86,7 +89,7 @@ BookReader.prototype.urlStartLocationPolling = function() {
|
|
86
89
|
this.oldLocationHash = this.urlReadFragment();
|
87
90
|
|
88
91
|
if (this.locationPollId) {
|
89
|
-
clearInterval(this.
|
92
|
+
clearInterval(this.locationPollId);
|
90
93
|
this.locationPollId = null;
|
91
94
|
}
|
92
95
|
|
@@ -110,7 +113,7 @@ BookReader.prototype.urlStartLocationPolling = function() {
|
|
110
113
|
updateParams();
|
111
114
|
}
|
112
115
|
this.oldUserHash = newFragment;
|
113
|
-
}
|
116
|
+
};
|
114
117
|
|
115
118
|
this.locationPollId = setInterval(updateHash, 500);
|
116
119
|
};
|
@@ -134,7 +137,7 @@ BookReader.prototype.urlUpdateFragment = function() {
|
|
134
137
|
if (paramName in allParams) {
|
135
138
|
validParams[paramName] = allParams[paramName];
|
136
139
|
}
|
137
|
-
return validParams
|
140
|
+
return validParams;
|
138
141
|
}, {});
|
139
142
|
|
140
143
|
const newFragment = this.fragmentFromParams(params, urlMode);
|
@@ -173,7 +176,7 @@ BookReader.prototype.urlUpdateFragment = function() {
|
|
173
176
|
BookReader.prototype.urlParamsFiltersOnlySearch = function(url) {
|
174
177
|
const params = new URLSearchParams(url);
|
175
178
|
return params.has('q') ? `?${new URLSearchParams({ q: params.get('q') })}` : '';
|
176
|
-
}
|
179
|
+
};
|
177
180
|
|
178
181
|
|
179
182
|
/**
|
@@ -196,3 +199,22 @@ BookReader.prototype.urlReadFragment = function() {
|
|
196
199
|
BookReader.prototype.urlReadHashFragment = function() {
|
197
200
|
return window.location.hash.substr(1);
|
198
201
|
};
|
202
|
+
export class BookreaderUrlPlugin extends BookReader {
|
203
|
+
init() {
|
204
|
+
if (this.options.enableUrlPlugin) {
|
205
|
+
this.urlPlugin = new UrlPlugin(this.options);
|
206
|
+
this.bind(BookReader.eventNames.PostInit, () => {
|
207
|
+
const { urlMode } = this.options;
|
208
|
+
|
209
|
+
if (urlMode === 'hash') {
|
210
|
+
this.urlPlugin.listenForHashChanges();
|
211
|
+
}
|
212
|
+
});
|
213
|
+
}
|
214
|
+
|
215
|
+
super.init();
|
216
|
+
}
|
217
|
+
}
|
218
|
+
|
219
|
+
window.BookReader = BookreaderUrlPlugin;
|
220
|
+
export default BookreaderUrlPlugin;
|
package/tests/e2e/README.md
CHANGED
@@ -48,6 +48,43 @@ To run a particular fixture, add the path to the file at the end of your argumen
|
|
48
48
|
|
49
49
|
`npm run test:e2e chrome tests/e2e/example.test.js`
|
50
50
|
|
51
|
+
### Testing netlify or archive.org
|
52
|
+
|
53
|
+
```sh
|
54
|
+
BASE_URL='https://lucid-poitras-9a1249.netlify.app' npx testcafe
|
55
|
+
BASE_URL='https://archive.org' npx testcafe
|
56
|
+
```
|
57
|
+
|
58
|
+
### Testing any OCAID
|
59
|
+
|
60
|
+
For OCAIDs you should pick the specific test file to run, since things like autoplay tests won't work. The main tests are in `base.test.js`.
|
61
|
+
|
62
|
+
```sh
|
63
|
+
OCAIDS='goody,goodytwoshoes00newyiala' npx testcafe tests/e2e/base.test.js
|
64
|
+
OCAIDS='goody,goodytwoshoes00newyiala' BASE_URL='https://archive.org' npx testcafe tests/e2e/base.test.js
|
65
|
+
|
66
|
+
# right to left book; note this also runs the base tests
|
67
|
+
OCAIDS='gendaitankashu00meijuoft' BASE_URL='https://archive.org' npx testcafe tests/e2e/rightToLeft.test.js
|
68
|
+
```
|
69
|
+
|
70
|
+
### Running tests with browserstack
|
71
|
+
|
72
|
+
Note these can only test a public url, so you either need to create a draft PR and use the netlify link, or use ngrok to publish your dev server's port.
|
73
|
+
|
74
|
+
Note: Windows users, there is a bug that prevents spaces in the browser field when using `npx`, so you'll need to have `testcafe` globally installed, and run it without `npx`. (See https://github.com/DevExpress/testcafe/issues/6600 ). Or, you can add browserstack browsers the `.testcaferc.js` file.
|
75
|
+
|
76
|
+
```sh
|
77
|
+
# Set auth; find yours at https://www.browserstack.com/accounts/settings
|
78
|
+
export BROWSERSTACK_USERNAME="YOUR_USERNAME"
|
79
|
+
export BROWSERSTACK_ACCESS_KEY="YOUR_ACCESS_KEY"
|
80
|
+
|
81
|
+
BASE_URL='https://archive.org' OCAIDS='goody,goodytwoshoes00newyiala' npx testcafe 'browserstack:iPad Pro 12.9 2018@15' tests/e2e/base.test.js
|
82
|
+
```
|
83
|
+
|
84
|
+
See a list of available browsers with `npx testcafe -b browserstack`. Note there are some browsers which appear to not work for some reason (eg `browserstack:iPad Mini 4@9.3`).
|
85
|
+
|
86
|
+
Read more about other options/etc at the browserstack docs: https://www.browserstack.com/docs/automate/selenium/getting-started/nodejs/testcafe .
|
87
|
+
|
51
88
|
## Pending (skip) tests
|
52
89
|
|
53
90
|
You can skip any tests by calling the method `.skip` on the test object rather
|
@@ -1,11 +1,11 @@
|
|
1
1
|
import { ClientFunction } from 'testcafe';
|
2
|
+
import params from './helpers/params';
|
2
3
|
|
3
|
-
const { BASE_URL } = process.env;
|
4
4
|
const getLocationHref = ClientFunction(() => window.location.href.toString());
|
5
5
|
const FLIP_SPEED = 1000;
|
6
6
|
const FIRST_PAGE_DELAY = 2000;
|
7
7
|
|
8
|
-
fixture `Autoplay plugin`.page `${
|
8
|
+
fixture `Autoplay plugin`.page `${params.baseUrl}/BookReaderDemo/demo-autoplay.html`;
|
9
9
|
|
10
10
|
test('page auto-advances after allotted flip speed and delay', async t => {
|
11
11
|
await t.wait(2 * FLIP_SPEED + FIRST_PAGE_DELAY);
|
package/tests/e2e/base.test.js
CHANGED
@@ -2,10 +2,9 @@ import { runBaseTests } from './helpers/base';
|
|
2
2
|
import BookReader from './models/BookReader';
|
3
3
|
import { runDesktopSearchTests } from './helpers/desktopSearch';
|
4
4
|
// import { runMobileSearchTests } from './helpers/mobileSearch';
|
5
|
+
import params from './helpers/params';
|
5
6
|
|
6
|
-
|
7
|
-
const { BASE_URL } = process.env;
|
8
|
-
const OCAIDS = [
|
7
|
+
const ocaids = params.ocaids || [
|
9
8
|
'theworksofplato01platiala',
|
10
9
|
// Removed because failing test 'Canonical URL with cookie shows paramters'
|
11
10
|
// in tests/e2e/helpers/base.js
|
@@ -15,18 +14,19 @@ const OCAIDS = [
|
|
15
14
|
// /BookReaderDemo/demo-ia-olivertwist.html/page/n13/mode/2up
|
16
15
|
// 'demo-ia-olivertwist.html',
|
17
16
|
];
|
18
|
-
const DEMO_PATH = 'demo-internetarchive.html?ocaid='
|
19
17
|
|
20
|
-
|
21
|
-
const url =
|
18
|
+
ocaids.forEach(ocaid => {
|
19
|
+
const url = params.getArchiveUrl(ocaid);
|
22
20
|
|
23
21
|
fixture `Base Tests for: ${ocaid}`.page `${url}`;
|
24
22
|
runBaseTests(new BookReader());
|
25
23
|
|
24
|
+
|
26
25
|
fixture `Desktop Search Tests for: ${ocaid}`
|
27
|
-
.page `${url}
|
26
|
+
.page `${url}`;
|
28
27
|
runDesktopSearchTests(new BookReader());
|
29
28
|
|
29
|
+
// Todo: deprecated, will remove once mmenu is removed.
|
30
30
|
// fixture `Mobile Search Tests for: ${ocaid}`
|
31
31
|
// .page `${url}`
|
32
32
|
// runMobileSearchTests(new BookReader());
|
@@ -96,7 +96,7 @@ export function runBaseTests (br) {
|
|
96
96
|
|
97
97
|
if (await usesResume()) {
|
98
98
|
await t.expect(isPageInUrl()).eql(true, initialUrl);
|
99
|
-
await t.expect(isModeInUrl('2up')).eql(true, initialUrl)
|
99
|
+
await t.expect(isModeInUrl('2up')).eql(true, initialUrl);
|
100
100
|
} else {
|
101
101
|
// No plugin, no br-resume cookie
|
102
102
|
await t.expect(getUrl()).notContains('#page/');
|
@@ -138,7 +138,7 @@ export function runBaseTests (br) {
|
|
138
138
|
|
139
139
|
// we aren't showing the same image in the new pages
|
140
140
|
await t.expect(prevImg1Src).notEql(prevImg2Src);
|
141
|
-
})
|
141
|
+
});
|
142
142
|
|
143
143
|
test('2up mode - Clicking `Next page` changes the page', async t => {
|
144
144
|
// Note: this will fail on a R to L book if at front cover
|
@@ -168,7 +168,7 @@ export function runBaseTests (br) {
|
|
168
168
|
|
169
169
|
// we aren't showing the same image in the new pages
|
170
170
|
await t.expect(nextImg1Src).notEql(nextImg2Src);
|
171
|
-
})
|
171
|
+
});
|
172
172
|
|
173
173
|
test('Clicking `page flip buttons` updates location', async t => {
|
174
174
|
const { nav } = br;
|
@@ -191,6 +191,11 @@ export function runBaseTests (br) {
|
|
191
191
|
test('Clicking `1 page view` brings up 1 at a time', async t => {
|
192
192
|
const { nav } = br;
|
193
193
|
await t.click(nav.desktop.mode1Up);
|
194
|
+
|
195
|
+
// Flip away from cover
|
196
|
+
await t.click(nav.desktop.goNext);
|
197
|
+
await t.wait(PAGE_FLIP_WAIT_TIME);
|
198
|
+
|
194
199
|
// we usually pre-fetch the page in question & the 2 after it
|
195
200
|
await t.expect(Selector('.BRpagecontainer').count).gte(3);
|
196
201
|
});
|