@internetarchive/bookreader 5.0.0-42-a2 → 5.0.0-44-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.
Files changed (72) 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 +30 -0
  41. package/BookReaderDemo/demo-internetarchive.html +3 -0
  42. package/CHANGELOG.md +9 -0
  43. package/babel.config.js +1 -1
  44. package/package.json +22 -27
  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 +23 -1
  50. package/src/BookNavigator/search/a-search-result.js +4 -6
  51. package/src/css/_controls.scss +1 -2
  52. package/src/plugins/search/plugin.search.js +17 -4
  53. package/src/plugins/search/view.js +1 -3
  54. package/src/plugins/tts/plugin.tts.js +15 -3
  55. package/tests/{karma → jest}/BookNavigator/book-navigator.test.js +119 -104
  56. package/tests/{karma → jest}/BookNavigator/bookmarks/bookmark-button.test.js +13 -14
  57. package/tests/{karma → jest}/BookNavigator/bookmarks/bookmark-edit.test.js +25 -26
  58. package/tests/{karma → jest}/BookNavigator/bookmarks/bookmarks-list.test.js +41 -42
  59. package/tests/jest/BookNavigator/bookmarks/ia-bookmarks.test.js +45 -0
  60. package/tests/{karma → jest}/BookNavigator/downloads/downloads-provider.test.js +18 -18
  61. package/tests/{karma → jest}/BookNavigator/downloads/downloads.test.js +7 -8
  62. package/tests/{karma → jest}/BookNavigator/search/search-provider.test.js +29 -29
  63. package/tests/{karma → jest}/BookNavigator/search/search-results.test.js +57 -56
  64. package/tests/{karma → jest}/BookNavigator/sharing/sharing-provider.test.js +8 -8
  65. package/tests/jest/BookNavigator/visual-adjustments.test.js +200 -0
  66. package/tests/{karma → jest}/BookNavigator/volumes/volumes-provider.test.js +38 -38
  67. package/tests/{karma → jest}/BookNavigator/volumes/volumes.test.js +15 -16
  68. package/tests/jest/plugins/search/plugin.search.test.js +40 -23
  69. package/tests/jest/plugins/tts/AbstractTTSEngine.test.js +3 -3
  70. package/karma.conf.js +0 -23
  71. package/tests/karma/BookNavigator/bookmarks/ia-bookmarks.test.js +0 -57
  72. 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
- });