@internetarchive/bookreader 5.0.0-42 → 5.0.0-44-a2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (74) hide show
  1. package/.github/workflows/node.js.yml +14 -14
  2. package/.github/workflows/npm-publish.yml +4 -4
  3. package/BookReader/BookReader.css +14 -15
  4. package/BookReader/BookReader.js +1 -1
  5. package/BookReader/BookReader.js.map +1 -1
  6. package/BookReader/ia-bookreader-bundle.js +87 -87
  7. package/BookReader/ia-bookreader-bundle.js.map +1 -1
  8. package/BookReader/icons/pause.svg +1 -1
  9. package/BookReader/icons/playback-speed.svg +1 -1
  10. package/BookReader/icons/read-aloud.svg +1 -1
  11. package/BookReader/images/BRicons.svg +2 -2
  12. package/BookReader/images/books_graphic.svg +1 -1
  13. package/BookReader/images/icon_book.svg +1 -1
  14. package/BookReader/images/icon_gear.svg +1 -1
  15. package/BookReader/images/icon_info.svg +1 -1
  16. package/BookReader/images/icon_playback-rate.svg +1 -1
  17. package/BookReader/images/icon_search_button.svg +1 -1
  18. package/BookReader/images/icon_share.svg +1 -1
  19. package/BookReader/images/icon_speaker.svg +1 -1
  20. package/BookReader/images/icon_speaker_open.svg +1 -1
  21. package/BookReader/images/marker_chap-off.svg +1 -1
  22. package/BookReader/images/marker_chap-on.svg +1 -1
  23. package/BookReader/images/marker_srch-on.svg +1 -1
  24. package/BookReader/jquery-1.10.1.js +1 -1
  25. package/BookReader/jquery-1.10.1.js.LICENSE.txt +6 -6
  26. package/BookReader/plugins/plugin.archive_analytics.js +1 -1
  27. package/BookReader/plugins/plugin.archive_analytics.js.map +1 -1
  28. package/BookReader/plugins/plugin.resume.js +1 -1
  29. package/BookReader/plugins/plugin.resume.js.map +1 -1
  30. package/BookReader/plugins/plugin.search.js +1 -1
  31. package/BookReader/plugins/plugin.search.js.map +1 -1
  32. package/BookReader/plugins/plugin.text_selection.js +1 -1
  33. package/BookReader/plugins/plugin.text_selection.js.map +1 -1
  34. package/BookReader/plugins/plugin.tts.js +1 -1
  35. package/BookReader/plugins/plugin.tts.js.map +1 -1
  36. package/BookReader/plugins/plugin.url.js +1 -1
  37. package/BookReader/plugins/plugin.url.js.map +1 -1
  38. package/BookReader/plugins/plugin.vendor-fullscreen.js +1 -1
  39. package/BookReader/plugins/plugin.vendor-fullscreen.js.map +1 -1
  40. package/BookReaderDemo/IADemoBr.js +22 -0
  41. package/BookReaderDemo/demo-internetarchive.html +3 -0
  42. package/CHANGELOG.md +5 -0
  43. package/babel.config.js +1 -1
  44. package/package.json +24 -29
  45. package/renovate.json +13 -4
  46. package/scripts/preversion.js +4 -1
  47. package/src/BookNavigator/book-navigator.js +4 -0
  48. package/src/BookNavigator/downloads/downloads-provider.js +14 -5
  49. package/src/BookNavigator/downloads/downloads.js +25 -1
  50. package/src/BookNavigator/search/a-search-result.js +4 -6
  51. package/src/BookNavigator/search/search-provider.js +1 -0
  52. package/src/BookNavigator/search/search-results.js +4 -0
  53. package/src/css/_controls.scss +1 -2
  54. package/src/plugins/search/plugin.search.js +25 -4
  55. package/src/plugins/search/view.js +1 -3
  56. package/src/plugins/tts/plugin.tts.js +15 -3
  57. package/tests/{karma → jest}/BookNavigator/book-navigator.test.js +119 -104
  58. package/tests/{karma → jest}/BookNavigator/bookmarks/bookmark-button.test.js +13 -14
  59. package/tests/{karma → jest}/BookNavigator/bookmarks/bookmark-edit.test.js +25 -26
  60. package/tests/{karma → jest}/BookNavigator/bookmarks/bookmarks-list.test.js +41 -42
  61. package/tests/jest/BookNavigator/bookmarks/ia-bookmarks.test.js +45 -0
  62. package/tests/{karma → jest}/BookNavigator/downloads/downloads-provider.test.js +18 -18
  63. package/tests/{karma → jest}/BookNavigator/downloads/downloads.test.js +7 -8
  64. package/tests/{karma → jest}/BookNavigator/search/search-provider.test.js +29 -29
  65. package/tests/{karma → jest}/BookNavigator/search/search-results.test.js +57 -56
  66. package/tests/{karma → jest}/BookNavigator/sharing/sharing-provider.test.js +8 -8
  67. package/tests/jest/BookNavigator/visual-adjustments.test.js +200 -0
  68. package/tests/{karma → jest}/BookNavigator/volumes/volumes-provider.test.js +38 -38
  69. package/tests/{karma → jest}/BookNavigator/volumes/volumes.test.js +15 -16
  70. package/tests/jest/plugins/search/plugin.search.test.js +40 -23
  71. package/tests/jest/plugins/tts/AbstractTTSEngine.test.js +3 -3
  72. package/karma.conf.js +0 -23
  73. package/tests/karma/BookNavigator/bookmarks/ia-bookmarks.test.js +0 -57
  74. package/tests/karma/BookNavigator/visual-adjustments.test.js +0 -201
@@ -1,11 +1,10 @@
1
1
  import {
2
2
  html,
3
3
  fixture,
4
- expect,
5
4
  fixtureCleanup,
6
- } from '@open-wc/testing';
5
+ } from '@open-wc/testing-helpers';
7
6
  import sinon from 'sinon';
8
- import '../../../../src/BookNavigator/volumes/volumes.js';
7
+ import '@/src/BookNavigator/volumes/volumes.js';
9
8
 
10
9
 
11
10
  const brOptions = {
@@ -58,30 +57,30 @@ afterEach(() => {
58
57
  });
59
58
 
60
59
  describe('<viewable-files>', () => {
61
- it('sets default properties', async () => {
60
+ test('sets default properties', async () => {
62
61
  const files = brOptions.options.multipleBooksList?.by_subprefix;
63
62
  const viewableFiles = Object.keys(files).map(item => files[item]);
64
63
  const el = await fixture(container(viewableFiles));
65
64
  await el.updateComplete;
66
65
 
67
- expect(el.viewableFiles).to.equal(viewableFiles);
68
- expect(el.viewableFiles.length).to.equal(3);
69
- expect(el.shadowRoot.querySelectorAll("ul li").length).to.equal(3);
66
+ expect(el.viewableFiles).toEqual(viewableFiles);
67
+ expect(el.viewableFiles.length).toEqual(3);
68
+ expect(el.shadowRoot.querySelectorAll("ul li").length).toEqual(3);
70
69
 
71
- expect(el.shadowRoot.querySelector(".item-title").innerText).to.include(`${viewableFiles[0].title}`);
70
+ expect(el.shadowRoot.querySelector(".item-title").textContent).toContain(`${viewableFiles[0].title}`);
72
71
  });
73
72
 
74
- it('render empty volumes', async () => {
73
+ test('render empty volumes', async () => {
75
74
  const viewableFiles = [];
76
75
  const el = await fixture(container(viewableFiles));
77
76
  await el.updateComplete;
78
77
 
79
- expect(el.viewableFiles).to.equal(viewableFiles);
80
- expect(el.viewableFiles.length).to.equal(0);
81
- expect(el.shadowRoot.childElementCount).to.equal(0);
78
+ expect(el.viewableFiles).toEqual(viewableFiles);
79
+ expect(el.viewableFiles.length).toEqual(0);
80
+ expect(el.shadowRoot.childElementCount).not.toEqual(0);
82
81
  });
83
82
 
84
- it('render active volume item set as first viewable item ', async () => {
83
+ test('render active volume item set as first viewable item ', async () => {
85
84
  const files = brOptions.options.multipleBooksList?.by_subprefix;
86
85
  const viewableFiles = Object.keys(files).map(item => files[item]);
87
86
  const prefix = viewableFiles[0].file_subprefix;
@@ -89,10 +88,10 @@ describe('<viewable-files>', () => {
89
88
  const el = await fixture(container(viewableFiles, prefix));
90
89
  await el.updateComplete;
91
90
 
92
- expect(el.viewableFiles).to.equal(viewableFiles);
93
- expect(el.viewableFiles.length).to.equal(3);
91
+ expect(el.viewableFiles).toEqual(viewableFiles);
92
+ expect(el.viewableFiles.length).toEqual(3);
94
93
 
95
- expect(el.shadowRoot.querySelectorAll("ul li div")[1].className).to.equal("content active");
94
+ expect(el.shadowRoot.querySelectorAll("ul li div")[1].className).toEqual("content active");
96
95
  });
97
96
 
98
97
  });
@@ -1,7 +1,7 @@
1
-
2
1
  import BookReader from '@/src/BookReader.js';
3
2
  import '@/src/plugins/plugin.mobile_nav.js';
4
- import '@/src/plugins/search/plugin.search.js';
3
+ import { marshallSearchResults } from '@/src/plugins/search/plugin.search.js';
4
+ import { deepCopy } from '../../utils.js';
5
5
 
6
6
  jest.mock('@/src/plugins/search/view.js');
7
7
 
@@ -14,31 +14,33 @@ const triggeredEvents = () => {
14
14
  });
15
15
  };
16
16
 
17
+ const DUMMY_RESULTS = {
18
+ ia: "adventuresofoli00dick",
19
+ q: "child",
20
+ indexed: true,
21
+ page_count: 644,
22
+ body_length: 666,
23
+ leaf0_missing: false,
24
+ matches: [{
25
+ text: 'For a long; time after it was ushered into this world of sorrow and trouble, by the parish surgeon, it remained a matter of considerable doubt wliether the {{{child}}} Avould survi^ e to bear any name at all; in which case it is somewhat more than probable that these memoirs would never have appeared; or, if they had, that being comprised within a couple of pages, they would have possessed the inestimable meiit of being the most concise and faithful specimen of biography, extant in the literature of any age or country.',
26
+ par: [{
27
+ boxes: [{r: 1221, b: 2121, t: 2075, page: 37, l: 1107}],
28
+ b: 2535,
29
+ t: 1942,
30
+ page_width: 1790,
31
+ r: 1598,
32
+ l: 50,
33
+ page_height: 2940,
34
+ page: 37
35
+ }]
36
+ }]
37
+ };
38
+
17
39
  beforeEach(() => {
18
40
  $.ajax = jest.fn().mockImplementation(() => {
19
41
  // return from:
20
42
  // `https://ia800304.us.archive.org/fulltext/inside.php?item_id=adventuresofoli00dick&doc=adventuresofoli00dick&path=/30/items/adventuresofoli00dick&q=child&callback=<serialized jQ CB>`
21
- return Promise.resolve({
22
- ia: "adventuresofoli00dick",
23
- q: "child",
24
- indexed: true,
25
- page_count: 644,
26
- body_length: 666,
27
- leaf0_missing: false,
28
- matches: [{
29
- text: 'For a long; time after it was ushered into this world of sorrow and trouble, by the parish surgeon, it remained a matter of considerable doubt wliether the {{{child}}} Avould survi^ e to bear any name at all; in which case it is somewhat more than probable that these memoirs would never have appeared; or, if they had, that being comprised within a couple of pages, they would have possessed the inestimable meiit of being the most concise and faithful specimen of biography, extant in the literature of any age or country.',
30
- par: [{
31
- boxes: [{r: 1221, b: 2121, t: 2075, page: 37, l: 1107}],
32
- b: 2535,
33
- t: 1942,
34
- page_width: 1790,
35
- r: 1598,
36
- l: 50,
37
- page_height: 2940,
38
- page: 37
39
- }]
40
- }]
41
- });
43
+ return Promise.resolve(deepCopy(DUMMY_RESULTS));
42
44
  });
43
45
 
44
46
  $.fn.trigger = jest.fn();
@@ -163,3 +165,18 @@ describe('Plugin: Search', () => {
163
165
  expect(triggeredEvents()).toContain(`${namespace}SearchCallbackEmpty`);
164
166
  });
165
167
  });
168
+
169
+ describe('marshallSearchResults', () => {
170
+ test('Adds match index', () => {
171
+ const results = deepCopy(DUMMY_RESULTS);
172
+ marshallSearchResults(results, x => x.toString());
173
+ expect(results.matches[0]).toHaveProperty('matchIndex', 0);
174
+ expect(results.matches[0].par[0].boxes[0]).toHaveProperty('matchIndex', 0);
175
+ });
176
+
177
+ test('Adds display page number', () => {
178
+ const results = deepCopy(DUMMY_RESULTS);
179
+ marshallSearchResults(results, x => `n${x}`);
180
+ expect(results.matches[0]).toHaveProperty('displayPageNumber', 'n37');
181
+ });
182
+ });
@@ -20,7 +20,7 @@ describe.skip('AbstractTTSEngine', () => {
20
20
  });
21
21
  });
22
22
 
23
- for (const dummyVoice of [dummyVoice, dummyVoiceUnderscores]) {
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 dummyVoice(overrides) {
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 = dummyVoice(overrides);
150
+ const voice = dummyVoiceHyphens(overrides);
151
151
  voice.lang = voice.lang.replace('-', '_');
152
152
  return voice;
153
153
  }
package/karma.conf.js DELETED
@@ -1,23 +0,0 @@
1
- const { createDefaultConfig } = require('@open-wc/testing-karma');
2
- const merge = require('deepmerge');
3
-
4
- module.exports = (config) => {
5
- config.set(
6
- merge(createDefaultConfig(config), {
7
- files: [
8
- // runs all files ending with .test in the test folder,
9
- // can be overwritten by passing a --grep flag. examples:
10
- //
11
- // npm run test -- --grep test/foo/bar.test.js
12
- // npm run test -- --grep test/bar/*
13
- { pattern: config.grep ? config.grep : 'tests/karma/**/*.test.js', type: 'module' },
14
- ],
15
-
16
- esm: {
17
- nodeResolve: true,
18
- },
19
- // you can overwrite/extend the config further
20
- }),
21
- );
22
- return config;
23
- };
@@ -1,57 +0,0 @@
1
- import {
2
- html,
3
- fixtureSync,
4
- expect,
5
- fixtureCleanup,
6
- } from '@open-wc/testing';
7
- import '../../../../src/BookNavigator/bookmarks/ia-bookmarks.js';
8
- import sinon from 'sinon';
9
-
10
- afterEach(() => {
11
- sinon.restore();
12
- fixtureCleanup();
13
- });
14
-
15
- describe('<ia-bookmarks>', () => {
16
- it('uses `setup` to start component', async () => {
17
- const el = fixtureSync(html`<ia-bookmarks></ia-bookmarks>`);
18
- await el.updateComplete;
19
-
20
- let fetchHappened = false;
21
- el.bookreader.bookId = 'foo';
22
- el.displayMode = 'bookmarks';
23
-
24
- el.fetchBookmarks = async () => {
25
- fetchHappened = true;
26
- return await Promise.resolve();
27
- };
28
-
29
- const fetchSpy = sinon.spy(el, 'fetchUserBookmarks');
30
-
31
- el.setup();
32
- await el.updateComplete;
33
-
34
- expect(fetchSpy.callCount).to.equal(1);
35
- expect(fetchHappened).to.equal(true);
36
- });
37
- it('does not fetch user bookmarks if displayMode = login', async () => {
38
- const el = fixtureSync(html`<ia-bookmarks></ia-bookmarks>`);
39
- await el.updateComplete;
40
-
41
- let fetchHappened = false;
42
- el.displayMode = 'login';
43
-
44
- el.fetchBookmarks = async () => {
45
- fetchHappened = true;
46
- return await Promise.resolve();
47
- };
48
-
49
- const fetchSpy = sinon.spy(el, 'fetchUserBookmarks');
50
-
51
- el.setup();
52
- await el.updateComplete;
53
-
54
- expect(fetchSpy.callCount).to.equal(0);
55
- expect(fetchHappened).to.equal(false);
56
- });
57
- });
@@ -1,201 +0,0 @@
1
- import {
2
- html,
3
- fixture,
4
- expect,
5
- oneEvent,
6
- } from '@open-wc/testing';
7
- import sinon from 'sinon';
8
- import { IABookVisualAdjustments } from '../../../src/BookNavigator/visual-adjustments/visual-adjustments.js';
9
-
10
- const options = [{
11
- id: 'contrast',
12
- name: 'Adjust contrast',
13
- active: true,
14
- min: 0,
15
- max: 150,
16
- step: 1,
17
- value: 100,
18
- }, {
19
- id: 'invert',
20
- name: 'Invert colors',
21
- active: false,
22
- }, {
23
- id: 'brightness',
24
- name: 'Adjust brightness',
25
- active: false,
26
- value: 100,
27
- }];
28
-
29
- const container = (renderHeader = false) => (
30
- html`<ia-book-visual-adjustments .options=${options} ?renderHeader=${renderHeader}></ia-book-visual-adjustments>`
31
- );
32
-
33
- describe('<ia-book-visual-adjustments>', () => {
34
- afterEach(() => {
35
- sinon.restore();
36
- });
37
-
38
- it('sets default properties', async () => {
39
- const el = await fixture(container());
40
-
41
- expect(el.options).to.exist;
42
- expect(el.options.length).to.equal(options.length);
43
- expect(el.renderHeader).to.exist;
44
- expect(el.renderHeader).to.be.false;
45
- expect(el.activeCount).to.exist;
46
- expect(el.showZoomControls).to.be.true;
47
- });
48
-
49
- it('renders all properties of a visual adjustment option', async () => {
50
- const el = await fixture(container());
51
-
52
- await el.updateComplete;
53
-
54
- const label = el.shadowRoot.querySelector('label');
55
- const name = label.querySelector('.name');
56
- const checkbox = label.querySelector('input');
57
- expect(name.innerText).to.equal(options[0].name);
58
- expect(checkbox.checked).to.equal(true);
59
- });
60
-
61
- it('can render header with active options count', async () => {
62
- const renderHeader = true;
63
- const el = await fixture(container(renderHeader));
64
- expect(el.shadowRoot.querySelector('header p').innerText).to.include('1');
65
- });
66
-
67
- it('does not render active options count element when none are selected', async () => {
68
- const el = await fixture(container());
69
-
70
- el.options = [options[1]];
71
- await el.updateComplete;
72
-
73
- expect(el.shadowRoot.querySelector('header p')).not.to.exist;
74
- });
75
-
76
- it('changes option\'s active state when input changed', async () => {
77
- const el = await fixture(container());
78
-
79
- el.shadowRoot.querySelector('li input').dispatchEvent(new Event('change'));
80
- await el.updateComplete;
81
-
82
- expect(el.options[0].active).to.equal(false);
83
- });
84
-
85
- it('renders zoom in and out controls when enabled', async () => {
86
- const el = await fixture(container());
87
-
88
- expect(el.shadowRoot.querySelector('.zoom_out')).to.exist;
89
- expect(el.shadowRoot.querySelector('.zoom_in')).to.exist;
90
- });
91
-
92
- it('does not render zoom controls when disabled', async () => {
93
- const el = await fixture(container());
94
-
95
- el.showZoomControls = false;
96
- await el.updateComplete;
97
-
98
- expect(el.shadowRoot.querySelector('.zoom_out')).not.to.exist;
99
- expect(el.shadowRoot.querySelector('.zoom_in')).not.to.exist;
100
- });
101
-
102
- describe('Custom events', () => {
103
- it('prepareEventDetails returns proper params', async () => {
104
- const el = await fixture(container());
105
- await el.updateComplete;
106
- const params = el.prepareEventDetails();
107
-
108
- expect(params.activeCount).to.exist;
109
- expect(typeof (params.activeCount)).to.be.equal('number');
110
- expect(params.changedOptionId).to.exist;
111
- expect(typeof (params.changedOptionId)).to.be.equal('string');
112
- expect(params.options).to.exist;
113
- expect(params.options.length).to.exist;
114
- expect(params.options.length).to.be.greaterThan(0);
115
- });
116
- it('emitOptionChangedEvent calls for the params', async () => {
117
- IABookVisualAdjustments.prototype.prepareEventDetails = sinon.fake();
118
- const el = await fixture(container());
119
- await el.updateComplete;
120
-
121
- expect(el.prepareEventDetails.callCount).to.equal(1);
122
- });
123
- it('triggers an emitOptionChangedEvent event at firstUpdate', async () => {
124
- IABookVisualAdjustments.prototype.emitOptionChangedEvent = sinon.fake();
125
- const el = await fixture(container());
126
-
127
- expect(el.emitOptionChangedEvent.callCount).to.equal(1);
128
- });
129
-
130
- it('triggers an emitOptionChangedEvent event when a checkbox\'s change event fires', async () => {
131
- IABookVisualAdjustments.prototype.emitOptionChangedEvent = sinon.fake();
132
- const el = await fixture(container());
133
-
134
- expect(el.emitOptionChangedEvent.callCount).to.equal(1); // firstUpdate fire
135
-
136
- el.shadowRoot.querySelector('li input').dispatchEvent(new Event('change'));
137
- expect(el.emitOptionChangedEvent.callCount).to.equal(2);
138
- });
139
-
140
- it('triggers an emitOptionChangedEvent event when a range\'s change event fires', async () => {
141
- IABookVisualAdjustments.prototype.emitOptionChangedEvent = sinon.fake();
142
-
143
- const el = await fixture(container());
144
- expect(el.emitOptionChangedEvent.callCount).to.equal(1); // firstUpdate fire
145
-
146
- el.shadowRoot.querySelector('[name="brightness_range"]').dispatchEvent(new Event('change'));
147
- expect(el.emitOptionChangedEvent.callCount).to.equal(2);
148
- });
149
-
150
- it('emits a zoom out event when zoom out button clicked', async () => {
151
- const el = await fixture(container());
152
-
153
- setTimeout(() => (
154
- el.shadowRoot.querySelector('.zoom_out').click()
155
- ));
156
- const response = await oneEvent(el, 'visualAdjustmentZoomOut');
157
-
158
- expect(response).to.exist;
159
- });
160
-
161
- it('emits a zoom in event when zoom in button clicked', async () => {
162
- const el = await fixture(container());
163
-
164
- setTimeout(() => (
165
- el.shadowRoot.querySelector('.zoom_in').click()
166
- ));
167
- const response = await oneEvent(el, 'visualAdjustmentZoomIn');
168
-
169
- expect(response).to.exist;
170
- });
171
- });
172
-
173
- it('sets range defaults when none supplied', async () => {
174
- const el = await fixture(container());
175
- const brightnessRange = el.shadowRoot.querySelector('[name="brightness_range"]');
176
-
177
- expect(brightnessRange.getAttribute('min')).to.equal('0');
178
- expect(brightnessRange.getAttribute('max')).to.equal('100');
179
- expect(brightnessRange.getAttribute('step')).to.equal('1');
180
- });
181
-
182
- it('sets the updated range value on the options prop', async () => {
183
- const el = await fixture(container());
184
- const { id } = options[0];
185
- const newValue = 120;
186
-
187
- el.setRangeValue(id, newValue);
188
- await el.updateComplete;
189
-
190
- expect(el.options[0].value).to.equal(newValue);
191
- });
192
-
193
- it('triggers a setRangeValue event when a range\'s input event fires', async () => {
194
- IABookVisualAdjustments.prototype.setRangeValue = sinon.fake();
195
-
196
- const el = await fixture(container());
197
-
198
- el.shadowRoot.querySelector('[name="brightness_range"]').dispatchEvent(new Event('input'));
199
- expect(el.setRangeValue.callCount).to.equal(1);
200
- });
201
- });