@internetarchive/bookreader 5.0.0-5 → 5.0.0-50-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 +77 -6
- package/.github/workflows/npm-publish.yml +6 -20
- package/.testcaferc.js +10 -0
- package/BookReader/BookReader.css +131 -339
- 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 +1493 -0
- package/BookReader/ia-bookreader-bundle.js.LICENSE.txt +17 -0
- 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/pause.svg +1 -1
- package/BookReader/icons/playback-speed.svg +1 -1
- package/BookReader/icons/read-aloud.svg +1 -1
- package/BookReader/icons/voice.svg +1 -0
- package/BookReader/images/BRicons.svg +2 -2
- package/BookReader/images/books_graphic.svg +1 -1
- package/BookReader/images/icon_book.svg +1 -1
- package/BookReader/images/icon_gear.svg +1 -1
- package/BookReader/images/icon_info.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_speaker.svg +1 -1
- package/BookReader/images/icon_speaker_open.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/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 +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 +148 -0
- package/BookReaderDemo/demo-advanced.html +2 -2
- package/BookReaderDemo/demo-autoplay.html +2 -1
- package/BookReaderDemo/demo-embed-iframe-src.html +2 -1
- package/BookReaderDemo/demo-fullscreen-mobile.html +2 -1
- package/BookReaderDemo/demo-fullscreen.html +2 -1
- package/BookReaderDemo/demo-iiif.html +2 -1
- package/BookReaderDemo/demo-internetarchive.html +84 -17
- package/BookReaderDemo/demo-multiple.html +2 -1
- package/BookReaderDemo/demo-preview-pages.html +2 -1
- package/BookReaderDemo/demo-simple.html +2 -1
- package/BookReaderDemo/demo-vendor-fullscreen.html +2 -1
- package/BookReaderDemo/ia-multiple-volumes-manifest.js +170 -0
- package/BookReaderDemo/immersion-1up.html +2 -1
- package/BookReaderDemo/immersion-mode.html +2 -1
- package/BookReaderDemo/toggle_controls.html +2 -1
- package/BookReaderDemo/view_mode.html +2 -1
- package/BookReaderDemo/viewmode-cycle.html +2 -3
- package/CHANGELOG.md +202 -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 +66 -56
- package/renovate.json +52 -0
- package/scripts/preversion.js +4 -1
- 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 +583 -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 +3 -8
- package/src/BookNavigator/bookmarks/bookmarks-provider.js +21 -8
- package/src/BookNavigator/bookmarks/ia-bookmarks.js +102 -66
- package/src/BookNavigator/delete-modal-actions.js +1 -1
- package/src/BookNavigator/downloads/downloads-provider.js +36 -21
- package/src/BookNavigator/downloads/downloads.js +41 -25
- package/src/BookNavigator/search/a-search-result.js +18 -13
- package/src/BookNavigator/search/search-provider.js +80 -28
- package/src/BookNavigator/search/search-results.js +10 -18
- package/src/BookNavigator/sharing.js +27 -0
- package/src/BookNavigator/visual-adjustments/visual-adjustments-provider.js +11 -10
- package/src/BookNavigator/visual-adjustments/visual-adjustments.js +3 -3
- package/src/BookNavigator/volumes/volumes-provider.js +114 -0
- package/src/BookNavigator/volumes/volumes.js +188 -0
- package/src/BookReader/BookModel.js +0 -29
- 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 +120 -105
- package/src/BookReader/ModeSmoothZoom.js +179 -0
- package/src/BookReader/ModeThumb.js +17 -11
- package/src/BookReader/Navbar/Navbar.js +10 -36
- package/src/BookReader/PageContainer.js +69 -6
- package/src/BookReader/ReduceSet.js +1 -1
- package/src/BookReader/Toolbar/Toolbar.js +10 -37
- 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 +92 -13
- package/src/BookReader.js +431 -620
- 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 +25 -216
- package/src/css/_TextSelection.scss +14 -17
- package/src/css/_colorbox.scss +2 -2
- package/src/css/_controls.scss +17 -5
- package/src/css/_icons.scss +6 -0
- package/src/ia-bookreader/ia-bookreader.js +224 -0
- package/src/plugins/plugin.autoplay.js +4 -4
- package/src/plugins/plugin.chapters.js +28 -35
- 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 +174 -116
- package/src/plugins/search/view.js +63 -179
- package/src/plugins/tts/AbstractTTSEngine.js +46 -37
- package/src/plugins/tts/FestivalTTSEngine.js +13 -14
- package/src/plugins/tts/PageChunk.js +15 -21
- package/src/plugins/tts/PageChunkIterator.js +8 -12
- package/src/plugins/tts/WebTTSEngine.js +66 -69
- package/src/plugins/tts/plugin.tts.js +92 -109
- package/src/plugins/tts/utils.js +0 -9
- package/src/plugins/url/UrlPlugin.js +184 -0
- package/src/plugins/{plugin.url.js → url/plugin.url.js} +28 -6
- package/src/util/manifestGenerator.js +0 -0
- 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 +9 -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 +13 -4
- package/tests/e2e/rightToLeft.test.js +4 -5
- package/tests/e2e/viewmode.test.js +38 -33
- package/tests/jest/BookNavigator/book-navigator.test.js +634 -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/BookNavigator → jest/BookNavigator/search}/search-results.test.js +102 -58
- package/tests/jest/BookNavigator/sharing/sharing-provider.test.js +49 -0
- package/tests/jest/BookNavigator/visual-adjustments.test.js +200 -0
- package/tests/jest/BookNavigator/volumes/volumes-provider.test.js +184 -0
- package/tests/jest/BookNavigator/volumes/volumes.test.js +97 -0
- package/tests/{BookReader → jest/BookReader}/BookModel.test.js +34 -14
- 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 +92 -0
- package/tests/{BookReader → jest/BookReader}/Mode2Up.test.js +36 -15
- 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 +88 -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 +186 -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} +18 -37
- package/tests/{plugins → jest/plugins}/plugin.archive_analytics.test.js +2 -2
- package/tests/{plugins → jest/plugins}/plugin.autoplay.test.js +4 -4
- package/tests/{plugins → jest/plugins}/plugin.chapters.test.js +10 -11
- 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 +63 -47
- package/tests/{plugins → jest/plugins}/search/plugin.search.view.test.js +35 -6
- package/tests/{plugins → jest/plugins}/tts/AbstractTTSEngine.test.js +9 -9
- 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 -28
- 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/webpack.config.js +11 -5
- 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/BookReaderDemo/bookreader-template-bundle.js +0 -7178
- 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 -438
- 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/Layers/sharing/sharing-provider.js +0 -22
- package/src/dragscrollable-br.js +0 -261
- package/src/plugins/menu_toggle/plugin.menu_toggle.js +0 -324
- package/src/plugins/plugin.bookmarks.js +0 -50
- 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/e2e/ia-production/ia-prod-base.js +0 -17
- package/tests/karma/BookNavigator/book-navigator.test.js +0 -132
- package/tests/karma/BookNavigator/visual-adjustments.test.js +0 -201
- package/tests/plugins/menu_toggle/plugin.menu_toggle.test.js +0 -68
@@ -1,12 +1,12 @@
|
|
1
1
|
import sinon from 'sinon';
|
2
2
|
import { afterEventLoop } from '../../utils.js';
|
3
|
-
import AbstractTTSEngine from '
|
4
|
-
import PageChunkIterator from '
|
5
|
-
/** @typedef {import('
|
3
|
+
import AbstractTTSEngine from '@/src/plugins/tts/AbstractTTSEngine.js';
|
4
|
+
import PageChunkIterator from '@/src/plugins/tts/PageChunkIterator.js';
|
5
|
+
/** @typedef {import('@/src/plugins/tts/AbstractTTSEngine.js').TTSEngineOptions} TTSEngineOptions */
|
6
6
|
|
7
7
|
// Skipping because it's flaky. Fix in #672
|
8
8
|
describe.skip('AbstractTTSEngine', () => {
|
9
|
-
test('stops playing once done', () => {
|
9
|
+
test('stops playing once done', async () => {
|
10
10
|
class DummyEngine extends AbstractTTSEngine {
|
11
11
|
getVoices() { return []; }
|
12
12
|
}
|
@@ -15,12 +15,12 @@ describe.skip('AbstractTTSEngine', () => {
|
|
15
15
|
const stopStub = sinon.stub(d, 'stop');
|
16
16
|
expect(stopStub.callCount).toBe(0);
|
17
17
|
d.step();
|
18
|
-
|
19
|
-
|
18
|
+
await afterEventLoop();
|
19
|
+
expect(stopStub.callCount).toBe(1);
|
20
20
|
});
|
21
21
|
});
|
22
22
|
|
23
|
-
for (const dummyVoice of [
|
23
|
+
for (const dummyVoice of [dummyVoiceHyphens, dummyVoiceUnderscores]) {
|
24
24
|
describe(`getBestBookVoice with BCP47 ${dummyVoice == dummyVoiceUnderscores ? '+' : '-'} underscores`, () => {
|
25
25
|
const { getBestBookVoice } = AbstractTTSEngine;
|
26
26
|
|
@@ -130,7 +130,7 @@ export const DUMMY_TTS_ENGINE_OPTS = {
|
|
130
130
|
* @param {SpeechSynthesisVoice}
|
131
131
|
* @return {SpeechSynthesisVoice}
|
132
132
|
**/
|
133
|
-
function
|
133
|
+
function dummyVoiceHyphens(overrides) {
|
134
134
|
return Object.assign({
|
135
135
|
default: false,
|
136
136
|
lang: "en-US",
|
@@ -147,7 +147,7 @@ function dummyVoice(overrides) {
|
|
147
147
|
* @return {SpeechSynthesisVoice}
|
148
148
|
**/
|
149
149
|
function dummyVoiceUnderscores(overrides) {
|
150
|
-
const voice =
|
150
|
+
const voice = dummyVoiceHyphens(overrides);
|
151
151
|
voice.lang = voice.lang.replace('-', '_');
|
152
152
|
return voice;
|
153
153
|
}
|
@@ -1,10 +1,10 @@
|
|
1
|
-
import FestivalTTSEngine from '
|
1
|
+
import FestivalTTSEngine from '@/src/plugins/tts/FestivalTTSEngine.js';
|
2
2
|
import sinon from 'sinon';
|
3
3
|
import { afterEventLoop } from '../../utils.js';
|
4
4
|
import { DUMMY_TTS_ENGINE_OPTS } from './AbstractTTSEngine.test.js';
|
5
|
-
import PageChunk from '
|
6
|
-
import PageChunkIterator from '
|
7
|
-
/** @typedef {import('
|
5
|
+
import PageChunk from '@/src/plugins/tts/PageChunk.js';
|
6
|
+
import PageChunkIterator from '@/src/plugins/tts/PageChunkIterator.js';
|
7
|
+
/** @typedef {import('@/src/plugins/tts/AbstractTTSEngine.js').TTSEngineOptions} TTSEngineOptions */
|
8
8
|
|
9
9
|
describe('iOSCaptureUserIntentHack', () => {
|
10
10
|
test('synchronously calls createSound/play to capture user intent', () => {
|
@@ -1,6 +1,6 @@
|
|
1
1
|
import sinon from 'sinon';
|
2
|
-
import PageChunkIterator from "
|
3
|
-
import PageChunk from '
|
2
|
+
import PageChunkIterator from "@/src/plugins/tts/PageChunkIterator";
|
3
|
+
import PageChunk from '@/src/plugins/tts/PageChunk';
|
4
4
|
|
5
5
|
describe('Buffers pages', () => {
|
6
6
|
test('Does not error if no room for reverse buffer', async () => {
|
@@ -109,7 +109,7 @@ describe('Iterates pages', () => {
|
|
109
109
|
expect(iterator._cursor.chunk).toBe(0);
|
110
110
|
|
111
111
|
for (let i = 2; i >= 0; i--) {
|
112
|
-
await iterator.decrement()
|
112
|
+
await iterator.decrement();
|
113
113
|
expect(iterator._cursor.page).toBe(49);
|
114
114
|
expect(iterator._cursor.chunk).toBe(i);
|
115
115
|
}
|
@@ -1,6 +1,6 @@
|
|
1
1
|
import sinon from 'sinon';
|
2
2
|
import { afterEventLoop, eventTargetMixin } from '../../utils.js';
|
3
|
-
import * as utils from '
|
3
|
+
import * as utils from '@/src/plugins/tts/utils.js';
|
4
4
|
|
5
5
|
describe('promisifyEvent', () => {
|
6
6
|
const { promisifyEvent } = utils;
|
@@ -10,7 +10,7 @@ describe('promisifyEvent', () => {
|
|
10
10
|
const resolveSpy = sinon.spy();
|
11
11
|
promisifyEvent(fakeTarget, 'pause').then(resolveSpy);
|
12
12
|
|
13
|
-
await afterEventLoop()
|
13
|
+
await afterEventLoop();
|
14
14
|
expect(resolveSpy.callCount).toBe(0);
|
15
15
|
fakeTarget.dispatchEvent('pause', {});
|
16
16
|
await afterEventLoop();
|
@@ -22,7 +22,7 @@ describe('promisifyEvent', () => {
|
|
22
22
|
const resolveSpy = sinon.spy();
|
23
23
|
promisifyEvent(fakeTarget, 'pause').then(resolveSpy);
|
24
24
|
|
25
|
-
await afterEventLoop()
|
25
|
+
await afterEventLoop();
|
26
26
|
expect(resolveSpy.callCount).toBe(0);
|
27
27
|
fakeTarget.dispatchEvent('pause', {});
|
28
28
|
fakeTarget.dispatchEvent('pause', {});
|
@@ -66,31 +66,6 @@ describe('approximateWordCount', () => {
|
|
66
66
|
});
|
67
67
|
});
|
68
68
|
|
69
|
-
describe('sleep', () => {
|
70
|
-
const { sleep } = utils;
|
71
|
-
|
72
|
-
test('Sleep 0 doest not called immediately', async () => {
|
73
|
-
const spy = sinon.spy();
|
74
|
-
sleep(0).then(spy);
|
75
|
-
expect(spy.callCount).toBe(0);
|
76
|
-
await afterEventLoop();
|
77
|
-
expect(spy.callCount).toBe(1);
|
78
|
-
});
|
79
|
-
|
80
|
-
test('Waits the appropriate ms', async () => {
|
81
|
-
const clock = sinon.useFakeTimers();
|
82
|
-
const spy = sinon.spy();
|
83
|
-
sleep(10).then(spy);
|
84
|
-
expect(spy.callCount).toBe(0);
|
85
|
-
clock.tick(10);
|
86
|
-
expect(spy.callCount).toBe(0);
|
87
|
-
clock.restore();
|
88
|
-
|
89
|
-
await afterEventLoop();
|
90
|
-
expect(spy.callCount).toBe(1);
|
91
|
-
});
|
92
|
-
});
|
93
|
-
|
94
69
|
describe('toISO6391', () => {
|
95
70
|
const { toISO6391 } = utils;
|
96
71
|
|
@@ -0,0 +1,190 @@
|
|
1
|
+
import { UrlPlugin } from '@/src/plugins/url/UrlPlugin';
|
2
|
+
|
3
|
+
afterEach(() => {
|
4
|
+
jest.clearAllMocks();
|
5
|
+
});
|
6
|
+
|
7
|
+
describe('UrlPlugin tests', () => {
|
8
|
+
const urlPlugin = new UrlPlugin();
|
9
|
+
|
10
|
+
describe('urlStateToUrlString tests', () => {
|
11
|
+
test('urlStateToUrlString with known states in schema', () => {
|
12
|
+
const urlState = { page: 'n7', mode: '1up', search: 'foo' };
|
13
|
+
const urlStateWithQueries = { page: 'n7', mode: '1up', q: 'hello', view: 'theater', sort: 'title_asc' };
|
14
|
+
|
15
|
+
const expectedUrlFromState = 'page/n7/mode/1up?q=foo';
|
16
|
+
const expectedUrlFromStateWithQueries = 'page/n7/mode/1up?q=hello&view=theater&sort=title_asc';
|
17
|
+
|
18
|
+
expect(urlPlugin.urlStateToUrlString(urlState)).toBe(expectedUrlFromState);
|
19
|
+
expect(urlPlugin.urlStateToUrlString(urlStateWithQueries)).toBe(expectedUrlFromStateWithQueries);
|
20
|
+
});
|
21
|
+
|
22
|
+
test('urlStateToUrlString with unknown states in schema', () => {
|
23
|
+
const urlState = { page: 'n7', mode: '1up' };
|
24
|
+
const urlStateWithQueries = { page: 'n7', mode: '1up', q: 'hello', viewer: 'theater', sortBy: 'title_asc' };
|
25
|
+
|
26
|
+
const expectedUrlFromState = 'page/n7/mode/1up';
|
27
|
+
const expectedUrlFromStateWithQueries = 'page/n7/mode/1up?q=hello&viewer=theater&sortBy=title_asc';
|
28
|
+
|
29
|
+
expect(urlPlugin.urlStateToUrlString(urlState)).toBe(expectedUrlFromState);
|
30
|
+
expect(urlPlugin.urlStateToUrlString(urlStateWithQueries)).toBe(expectedUrlFromStateWithQueries);
|
31
|
+
});
|
32
|
+
|
33
|
+
test('urlStateToUrlString with boolean value', () => {
|
34
|
+
const urlState = { page: 'n7', mode: '1up', search: 'foo', view: 'theater', wrapper: 'false' };
|
35
|
+
const expectedUrlFromState = 'page/n7/mode/1up?q=foo&view=theater&wrapper=false';
|
36
|
+
|
37
|
+
expect(urlPlugin.urlStateToUrlString(urlState)).toBe(expectedUrlFromState);
|
38
|
+
});
|
39
|
+
});
|
40
|
+
|
41
|
+
describe('urlStringToUrlState tests', () => {
|
42
|
+
test('urlStringToUrlState without query string', () => {
|
43
|
+
const url = '/page/n7/mode/2up';
|
44
|
+
const url1 = '/page/n7/mode/1up';
|
45
|
+
|
46
|
+
expect(urlPlugin.urlStringToUrlState(url)).toEqual({page: 'n7', mode: '2up'});
|
47
|
+
expect(urlPlugin.urlStringToUrlState(url1)).toEqual({page: 'n7', mode: '1up'});
|
48
|
+
});
|
49
|
+
|
50
|
+
test('urlStringToUrlState with deprecated_for', () => {
|
51
|
+
const url = '/page/n7/mode/2up/search/hello';
|
52
|
+
|
53
|
+
expect(urlPlugin.urlStringToUrlState(url)).toEqual({page: 'n7', mode: '2up', q: 'hello'});
|
54
|
+
});
|
55
|
+
|
56
|
+
test('urlStringToUrlState with query string', () => {
|
57
|
+
const url = '/page/n7/mode/2up/search/hello?view=theather&foo=bar&sort=title_asc';
|
58
|
+
const url1 = '/mode/2up?ref=ol&ui=embed&wrapper=false&view=theater';
|
59
|
+
|
60
|
+
expect(urlPlugin.urlStringToUrlState(url)).toEqual(
|
61
|
+
{page: 'n7', mode: '2up', q: 'hello', view: 'theather', foo: 'bar', sort: 'title_asc'}
|
62
|
+
);
|
63
|
+
expect(urlPlugin.urlStringToUrlState(url1)).toEqual(
|
64
|
+
{mode: '2up', ref: 'ol', ui: 'embed', wrapper: 'false', view: 'theater'}
|
65
|
+
);
|
66
|
+
});
|
67
|
+
|
68
|
+
test('urlStringToUrlState compare search and ?q', () => {
|
69
|
+
const url = '/page/n7/mode/2up/search/hello';
|
70
|
+
urlPlugin.urlState = { q: 'hello' };
|
71
|
+
|
72
|
+
expect(urlPlugin.urlStringToUrlState(url)).toEqual({page: 'n7', mode: '2up', q: 'hello'});
|
73
|
+
});
|
74
|
+
});
|
75
|
+
|
76
|
+
describe('url plugin helper functions', () => {
|
77
|
+
test('setUrlParam', () => {
|
78
|
+
urlPlugin.urlState = {};
|
79
|
+
urlPlugin.setUrlParam('page', '20');
|
80
|
+
urlPlugin.setUrlParam('mode', '2up');
|
81
|
+
|
82
|
+
expect(urlPlugin.urlState).toEqual({page: '20', mode: '2up'});
|
83
|
+
});
|
84
|
+
|
85
|
+
test('removeUrlParam', () => {
|
86
|
+
urlPlugin.setUrlParam('page', '20');
|
87
|
+
urlPlugin.setUrlParam('mode', '2up');
|
88
|
+
urlPlugin.removeUrlParam('mode');
|
89
|
+
|
90
|
+
expect(urlPlugin.urlState).toEqual({page: '20'});
|
91
|
+
});
|
92
|
+
|
93
|
+
test('getUrlParam', () => {
|
94
|
+
urlPlugin.setUrlParam('page', '20');
|
95
|
+
urlPlugin.setUrlParam('mode', '2up');
|
96
|
+
expect(urlPlugin.getUrlParam('page')).toEqual('20');
|
97
|
+
expect(urlPlugin.getUrlParam('mode')).toEqual('2up');
|
98
|
+
});
|
99
|
+
});
|
100
|
+
|
101
|
+
describe('pullFromAddressBar and pushToAddressBar - hash mode', () => {
|
102
|
+
test('url first load - empty state', () => {
|
103
|
+
urlPlugin.urlState = {};
|
104
|
+
urlPlugin.urlMode = 'hash';
|
105
|
+
|
106
|
+
urlPlugin.pullFromAddressBar({ pathname: '', search: '', hash: '#' });
|
107
|
+
expect(urlPlugin.urlState).toEqual({});
|
108
|
+
|
109
|
+
urlPlugin.pushToAddressBar();
|
110
|
+
expect(window.location.hash).toEqual('');
|
111
|
+
});
|
112
|
+
|
113
|
+
test('url without mode state value - use default', () => {
|
114
|
+
urlPlugin.urlState = {};
|
115
|
+
urlPlugin.urlMode = 'hash';
|
116
|
+
|
117
|
+
urlPlugin.pullFromAddressBar({ pathname: '', search: '', hash: '#page/12' });
|
118
|
+
expect(urlPlugin.urlState).toEqual({page: '12'});
|
119
|
+
|
120
|
+
urlPlugin.pushToAddressBar();
|
121
|
+
expect(window.location.hash).toEqual('#page/12');
|
122
|
+
});
|
123
|
+
|
124
|
+
test('url with query param', () => {
|
125
|
+
urlPlugin.urlState = {};
|
126
|
+
urlPlugin.urlMode = 'hash';
|
127
|
+
|
128
|
+
urlPlugin.pullFromAddressBar({ pathname: '', search: '', hash: '#page/12?q=hello&view=theater' });
|
129
|
+
expect(urlPlugin.urlState).toEqual({page: '12', q: 'hello', view: 'theater'});
|
130
|
+
|
131
|
+
urlPlugin.pushToAddressBar();
|
132
|
+
expect(window.location.hash).toEqual('#page/12?q=hello&view=theater');
|
133
|
+
});
|
134
|
+
});
|
135
|
+
|
136
|
+
describe('pullFromAddressBar and pushToAddressBar - history mode', () => {
|
137
|
+
test('url first load - empty state', () => {
|
138
|
+
urlPlugin.urlState = {};
|
139
|
+
urlPlugin.urlHistoryBasePath = '/details/foo';
|
140
|
+
urlPlugin.urlMode = 'history';
|
141
|
+
|
142
|
+
urlPlugin.pullFromAddressBar({ pathname: '', search: '', hash: '' });
|
143
|
+
expect(urlPlugin.urlState).toEqual({});
|
144
|
+
|
145
|
+
urlPlugin.pushToAddressBar();
|
146
|
+
expect(window.location.pathname).toEqual('/details/foo');
|
147
|
+
});
|
148
|
+
|
149
|
+
test('url without mode state value', () => {
|
150
|
+
urlPlugin.urlState = {};
|
151
|
+
urlPlugin.urlHistoryBasePath = '/details/foo/';
|
152
|
+
urlPlugin.urlMode = 'history';
|
153
|
+
|
154
|
+
urlPlugin.pullFromAddressBar({ pathname: '/details/foo/page/12', search: '', hash: '' });
|
155
|
+
expect(urlPlugin.urlState).toEqual({page: '12'});
|
156
|
+
|
157
|
+
urlPlugin.pushToAddressBar();
|
158
|
+
expect(window.location.pathname).toEqual('/details/foo/page/12');
|
159
|
+
});
|
160
|
+
|
161
|
+
test('url with query param', () => {
|
162
|
+
urlPlugin.urlState = {};
|
163
|
+
urlPlugin.urlHistoryBasePath = '/details/foo/';
|
164
|
+
urlPlugin.urlMode = 'history';
|
165
|
+
|
166
|
+
urlPlugin.pullFromAddressBar({ pathname: '/details/foo/page/12', search: '?q=hello&view=theater', hash: '' });
|
167
|
+
expect(urlPlugin.urlState).toEqual({page: '12', q: 'hello', view: 'theater'});
|
168
|
+
|
169
|
+
urlPlugin.pushToAddressBar();
|
170
|
+
const locationUrl = `${window.location.pathname}${window.location.search}`;
|
171
|
+
expect(locationUrl).toEqual('/details/foo/page/12?q=hello&view=theater');
|
172
|
+
});
|
173
|
+
|
174
|
+
test('strips leading slash of incoming path name for no double slash', () => {
|
175
|
+
const urlPlugin = new UrlPlugin();
|
176
|
+
urlPlugin.urlMode = 'history';
|
177
|
+
|
178
|
+
urlPlugin.urlHistoryBasePath = '/details/SubBookTest/book1/GPORFP/';
|
179
|
+
urlPlugin.urlState = {
|
180
|
+
"mode": "1up",
|
181
|
+
};
|
182
|
+
|
183
|
+
urlPlugin.setUrlParam('sort', 'title_asc');
|
184
|
+
urlPlugin.setUrlParam('mode', 'thumb');
|
185
|
+
|
186
|
+
expect(window.location.href).toEqual('http://localhost/details/SubBookTest/book1/GPORFP/mode/thumb?sort=title_asc');
|
187
|
+
});
|
188
|
+
});
|
189
|
+
|
190
|
+
});
|
@@ -1,6 +1,6 @@
|
|
1
|
-
|
2
|
-
import
|
3
|
-
import '
|
1
|
+
import BookReader from '@/src/BookReader.js';
|
2
|
+
import '@/src/plugins/url/plugin.url.js';
|
3
|
+
import sinon from 'sinon';
|
4
4
|
|
5
5
|
let br;
|
6
6
|
beforeAll(() => {
|
@@ -10,6 +10,7 @@ beforeAll(() => {
|
|
10
10
|
|
11
11
|
afterEach(() => {
|
12
12
|
jest.clearAllMocks();
|
13
|
+
sinon.restore();
|
13
14
|
});
|
14
15
|
|
15
16
|
describe('Plugin: URL controller', () => {
|
@@ -26,10 +27,10 @@ describe('Plugin: URL controller', () => {
|
|
26
27
|
expect(defaultOptions).toHaveProperty('updateWindowTitle');
|
27
28
|
expect(defaultOptions).toHaveProperty('defaults');
|
28
29
|
expect(defaultOptions).toHaveProperty('bookId');
|
29
|
-
})
|
30
|
+
});
|
30
31
|
|
31
32
|
test('has a whitelist of params that it tracks', () => {
|
32
|
-
['page', 'search', 'mode', 'region', 'highlight']
|
33
|
+
['page', 'search', 'mode', 'region', 'highlight'];
|
33
34
|
const { defaultOptions: { urlTrackedParams } } = BookReader;
|
34
35
|
expect(Array.isArray(urlTrackedParams)).toEqual(true);
|
35
36
|
expect(urlTrackedParams.find(param => param === 'page')).toBeTruthy();
|
@@ -37,7 +38,8 @@ describe('Plugin: URL controller', () => {
|
|
37
38
|
expect(urlTrackedParams.find(param => param === 'mode')).toBeTruthy();
|
38
39
|
expect(urlTrackedParams.find(param => param === 'region')).toBeTruthy();
|
39
40
|
expect(urlTrackedParams.find(param => param === 'highlight')).toBeTruthy();
|
40
|
-
|
41
|
+
expect(urlTrackedParams.find(param => param === 'view')).toBeTruthy();
|
42
|
+
});
|
41
43
|
|
42
44
|
test('initializes polling for url changes if using hash', () => {
|
43
45
|
BookReader.prototype.urlStartLocationPolling = jest.fn();
|
@@ -60,7 +62,7 @@ describe('Plugin: URL controller', () => {
|
|
60
62
|
br.urlUpdateFragment();
|
61
63
|
|
62
64
|
expect(window.history.replaceState).toHaveBeenCalled();
|
63
|
-
})
|
65
|
+
});
|
64
66
|
|
65
67
|
test('updates URL when mode changes', () => {
|
66
68
|
window.history.replaceState = jest.fn();
|
@@ -76,7 +78,7 @@ describe('Plugin: URL controller', () => {
|
|
76
78
|
br.urlUpdateFragment();
|
77
79
|
|
78
80
|
expect(window.history.replaceState).toHaveBeenCalled();
|
79
|
-
})
|
81
|
+
});
|
80
82
|
|
81
83
|
test('updates URL when search changes', () => {
|
82
84
|
window.history.replaceState = jest.fn();
|
@@ -93,7 +95,24 @@ describe('Plugin: URL controller', () => {
|
|
93
95
|
br.urlUpdateFragment();
|
94
96
|
|
95
97
|
expect(window.history.replaceState).toHaveBeenCalled();
|
96
|
-
})
|
98
|
+
});
|
99
|
+
|
100
|
+
test('updates URL when view changes', () => {
|
101
|
+
window.history.replaceState = jest.fn();
|
102
|
+
BookReader.prototype.currentIndex = jest.fn(() => 1);
|
103
|
+
BookReader.prototype.urlReadFragment = jest.fn(() => '');
|
104
|
+
BookReader.prototype.paramsFromCurrent = jest.fn(() => ({
|
105
|
+
index: 1,
|
106
|
+
mode: 2,
|
107
|
+
view: 'theater'
|
108
|
+
}));
|
109
|
+
BookReader.prototype.search = jest.fn();
|
110
|
+
br.options.urlMode = 'history';
|
111
|
+
br.init();
|
112
|
+
br.urlUpdateFragment();
|
113
|
+
|
114
|
+
expect(window.history.replaceState).toHaveBeenCalled();
|
115
|
+
});
|
97
116
|
|
98
117
|
test('does not update URL when search in query string', () => {
|
99
118
|
window.history.replaceState = jest.fn();
|
@@ -112,18 +131,18 @@ describe('Plugin: URL controller', () => {
|
|
112
131
|
br.urlUpdateFragment();
|
113
132
|
|
114
133
|
expect(window.history.replaceState).toHaveBeenCalledTimes(0);
|
115
|
-
})
|
134
|
+
});
|
116
135
|
|
117
136
|
test('only q= param is selected from url query params', () => {
|
118
|
-
const INTIAL_URL = "http://127.0.0.1:8080/BookReaderDemo/demo-internetarchive.html?ocaid=adventuresofoli00dick&q=foo"
|
137
|
+
const INTIAL_URL = "http://127.0.0.1:8080/BookReaderDemo/demo-internetarchive.html?ocaid=adventuresofoli00dick&q=foo";
|
119
138
|
const result = br.urlParamsFiltersOnlySearch(INTIAL_URL);
|
120
139
|
expect(result).toBe("?q=foo");
|
121
|
-
})
|
140
|
+
});
|
122
141
|
|
123
142
|
test('only q= param is selected from url query params with special character', () => {
|
124
|
-
const INTIAL_URL = "http://127.0.0.1:8080/BookReaderDemo/demo-internetarchive.html?ocaid=adventuresofoli00dick&q=foo%24%24"
|
143
|
+
const INTIAL_URL = "http://127.0.0.1:8080/BookReaderDemo/demo-internetarchive.html?ocaid=adventuresofoli00dick&q=foo%24%24";
|
125
144
|
const result = br.urlParamsFiltersOnlySearch(INTIAL_URL);
|
126
145
|
expect(result).toBe("?q=foo%24%24");
|
127
|
-
})
|
146
|
+
});
|
128
147
|
});
|
129
148
|
|
@@ -31,6 +31,44 @@ export function eventTargetMixin() {
|
|
31
31
|
};
|
32
32
|
}
|
33
33
|
|
34
|
+
/** @implements {EventTarget} */
|
35
|
+
export class EventTargetSpy {
|
36
|
+
/** @type {Record<string, Function[]} */
|
37
|
+
_listeners = {}
|
38
|
+
get _totalListenerCount() {
|
39
|
+
return Object.values(this._listeners)
|
40
|
+
.map(a => a.length)
|
41
|
+
.reduce((a, b) => a + b, 0);
|
42
|
+
}
|
43
|
+
|
44
|
+
addEventListener(evName, listener) {
|
45
|
+
const listeners = this._listeners[evName] || [];
|
46
|
+
listeners.push(listener);
|
47
|
+
this._listeners[evName] = listeners;
|
48
|
+
}
|
49
|
+
|
50
|
+
dispatchEvent(evName, ev) {
|
51
|
+
const listeners = this._listeners[evName] || [];
|
52
|
+
listeners.forEach(fn => fn(ev));
|
53
|
+
}
|
54
|
+
|
55
|
+
removeEventListener(evName, listener) {
|
56
|
+
const listeners = this._listeners[evName] || [];
|
57
|
+
this._listeners[evName] = listeners.filter(fn => fn != listener);
|
58
|
+
}
|
59
|
+
|
60
|
+
/**
|
61
|
+
* @param {EventTarget} realEventTarget
|
62
|
+
*/
|
63
|
+
static wrap(realEventTarget) {
|
64
|
+
const spy = new EventTargetSpy();
|
65
|
+
realEventTarget.addEventListener = spy.addEventListener.bind(spy);
|
66
|
+
realEventTarget.removeEventListener = spy.removeEventListener.bind(spy);
|
67
|
+
realEventTarget.dispatchEvent = spy.dispatchEvent.bind(spy);
|
68
|
+
return spy;
|
69
|
+
}
|
70
|
+
}
|
71
|
+
|
34
72
|
/**
|
35
73
|
* Lazy deep copy function; only supports objects (no classes)
|
36
74
|
* @template T
|
package/webpack.config.js
CHANGED
@@ -14,7 +14,11 @@ const shared = {
|
|
14
14
|
|
15
15
|
module: {
|
16
16
|
rules: [
|
17
|
-
{
|
17
|
+
{
|
18
|
+
test: /\.js$/,
|
19
|
+
exclude: /node_modules[/\\](?!(lit-element|lit-html|lit|@lit)[/\\]).*/,
|
20
|
+
loader: "babel-loader",
|
21
|
+
}
|
18
22
|
]
|
19
23
|
},
|
20
24
|
|
@@ -31,6 +35,9 @@ module.exports = [
|
|
31
35
|
|
32
36
|
// Output file -> srcfile
|
33
37
|
entry: {
|
38
|
+
// Polyfill bundles
|
39
|
+
'webcomponents-bundle.js': { import: '@webcomponents/webcomponentsjs/webcomponents-bundle.js' },
|
40
|
+
|
34
41
|
// BookReader
|
35
42
|
'BookReader.js': './src/BookReader.js',
|
36
43
|
|
@@ -39,15 +46,14 @@ module.exports = [
|
|
39
46
|
'plugins/plugin.autoplay.js': { import: './src/plugins/plugin.autoplay.js', dependOn: 'BookReader.js' },
|
40
47
|
'plugins/plugin.chapters.js': { import: './src/plugins/plugin.chapters.js', dependOn: 'BookReader.js' },
|
41
48
|
'plugins/plugin.iframe.js': { import: './src/plugins/plugin.iframe.js', dependOn: 'BookReader.js' },
|
42
|
-
'plugins/plugin.menu_toggle.js': { import: './src/plugins/menu_toggle/plugin.menu_toggle.js', dependOn: 'BookReader.js' },
|
43
49
|
'plugins/plugin.mobile_nav.js': { import: './src/plugins/plugin.mobile_nav.js', dependOn: 'BookReader.js' },
|
44
50
|
'plugins/plugin.resume.js': { import: './src/plugins/plugin.resume.js', dependOn: 'BookReader.js' },
|
45
51
|
'plugins/plugin.search.js': { import: './src/plugins/search/plugin.search.js', dependOn: 'BookReader.js' },
|
46
52
|
'plugins/plugin.text_selection.js': { import: './src/plugins/plugin.text_selection.js', dependOn: 'BookReader.js' },
|
47
53
|
'plugins/plugin.tts.js': { import: './src/plugins/tts/plugin.tts.js', dependOn: 'BookReader.js' },
|
48
|
-
'plugins/plugin.url.js': { import: './src/plugins/plugin.url.js', dependOn: 'BookReader.js' },
|
54
|
+
'plugins/plugin.url.js': { import: './src/plugins/url/plugin.url.js', dependOn: 'BookReader.js' },
|
49
55
|
'plugins/plugin.vendor-fullscreen.js': { import: './src/plugins/plugin.vendor-fullscreen.js', dependOn: 'BookReader.js' },
|
50
|
-
'bookreader-
|
56
|
+
'ia-bookreader-bundle.js': { import: './src/ia-bookreader/ia-bookreader.js', dependOn: 'BookReader.js' }
|
51
57
|
},
|
52
58
|
|
53
59
|
externals: {
|
@@ -80,7 +86,7 @@ module.exports = [
|
|
80
86
|
...shared,
|
81
87
|
|
82
88
|
entry: {
|
83
|
-
'jquery-
|
89
|
+
'jquery-3.js': { import: './src/jquery-wrapper.js' },
|
84
90
|
},
|
85
91
|
},
|
86
92
|
];
|
package/.babelrc
DELETED
package/.dependabot/config.yml
DELETED