@internetarchive/bookreader 5.0.0-71 → 5.0.0-72

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/CHANGELOG.md CHANGED
@@ -1,3 +1,9 @@
1
+ # 5.0.0-72
2
+ - Fix: Play/pause button out of sync with ReadAloud @sbwhitt
3
+ - Fix: BookReader not loading in sandboxed iframe @cdrini
4
+ - Dev: Fix noisy sentry error firing on any selection @cdrini
5
+ - Dev: Update to Node 20 @cdrini
6
+
1
7
  # 5.0.0-71
2
8
  - Dev: update jest monorepo @renovate
3
9
  - Fix: Share & Mutliple View menu panel refactor @iisa
package/netlify.toml CHANGED
@@ -1,6 +1,6 @@
1
1
  [build.environment]
2
2
  # Keep in sync with CI in .github/workflows/node.js.yml
3
- NODE_VERSION = "16"
3
+ NODE_VERSION = "20"
4
4
 
5
5
  [[headers]]
6
6
  # Define which paths this specific [[headers]] block will cover.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@internetarchive/bookreader",
3
- "version": "5.0.0-71",
3
+ "version": "5.0.0-72",
4
4
  "description": "The Internet Archive BookReader.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -46,7 +46,7 @@
46
46
  "@babel/plugin-proposal-decorators": "7.22.7",
47
47
  "@babel/preset-env": "7.22.9",
48
48
  "@open-wc/testing-helpers": "^2.3.0",
49
- "@types/jest": "29.5.5",
49
+ "@types/jest": "29.5.6",
50
50
  "@webcomponents/webcomponentsjs": "^2.6.0",
51
51
  "babel-loader": "9.1.3",
52
52
  "codecov": "^3.8.3",
@@ -67,10 +67,9 @@
67
67
  "jquery-ui-touch-punch": "0.2.3",
68
68
  "jquery.browser": "0.1.0",
69
69
  "live-server": "1.2.2",
70
- "node-fetch": "3.3.2",
71
70
  "regenerator-runtime": "0.13.11",
72
71
  "sass": "1.64.2",
73
- "sinon": "^15.1.0",
72
+ "sinon": "^17.0.0",
74
73
  "soundmanager2": "2.97.20170602",
75
74
  "svgo": "3.0.2",
76
75
  "testcafe": "2.6.2",
@@ -81,7 +80,7 @@
81
80
  "jest": {
82
81
  "testEnvironment": "jsdom",
83
82
  "transformIgnorePatterns": [
84
- "node_modules/(?!(lit-html|lit-element|lit|@lit|@internetarchive|@open-wc)/)"
83
+ "node_modules/(?!(sinon|lit-html|lit-element|lit|@lit|@internetarchive|@open-wc)/)"
85
84
  ],
86
85
  "moduleNameMapper": {
87
86
  "^@/(.*)$": "<rootDir>/$1"
@@ -2,10 +2,6 @@ const { version: OLD_VERSION } = require('../package.json');
2
2
  const OLD_RELEASE_URL = `https://api.github.com/repos/internetarchive/bookreader/releases/tags/v${OLD_VERSION}`;
3
3
 
4
4
  async function main() {
5
- // Need this because fetch is ESM-only, and we're on Node 16. Someday we should
6
- // be able to move this up to the top without renaming this file to a .mjs or whatever
7
- const {default: fetch} = await import('node-fetch');
8
-
9
5
  const {created_at} = await fetch(OLD_RELEASE_URL).then(r => r.json());
10
6
  const today = new Date().toISOString().slice(0, -5);
11
7
  const searchUrl = 'https://github.com/internetarchive/bookreader/pulls?' + new URLSearchParams({
@@ -30,8 +30,10 @@ export class SelectionObserver {
30
30
  const sel = window.getSelection();
31
31
 
32
32
  if (!this.selecting && sel.toString()) {
33
+ const target = $(sel.anchorNode).closest(this.selector)[0];
34
+ if (!target) return;
35
+ this.target = target;
33
36
  this.selecting = true;
34
- this.target = $(sel.anchorNode).closest(this.selector)[0];
35
37
  this.handler('started', this.target);
36
38
  }
37
39
 
@@ -1,4 +1,5 @@
1
1
  import PageChunkIterator from './PageChunkIterator.js';
2
+ import { hasLocalStorage } from './utils.js';
2
3
  /** @typedef {import('./utils.js').ISO6391} ISO6391 */
3
4
  /** @typedef {import('./PageChunk.js')} PageChunk */
4
5
 
@@ -80,6 +81,7 @@ export default class AbstractTTSEngine {
80
81
  */
81
82
  start(leafIndex, numLeafs) {
82
83
  this.playing = true;
84
+ this.paused = false;
83
85
  this.opts.onLoadingStart();
84
86
 
85
87
  this._chunkIterator = new PageChunkIterator(numLeafs, leafIndex, {
@@ -95,6 +97,7 @@ export default class AbstractTTSEngine {
95
97
  stop() {
96
98
  if (this.activeSound) this.activeSound.stop();
97
99
  this.playing = false;
100
+ this.paused = true;
98
101
  this._chunkIterator = null;
99
102
  this.activeSound = null;
100
103
  this.events.trigger('stop');
@@ -143,7 +146,7 @@ export default class AbstractTTSEngine {
143
146
  this.events.off('voiceschanged', this.updateBestVoice);
144
147
  this.voice = this.getVoices().find(voice => voice.voiceURI === voiceURI);
145
148
  // if the current book has a language set, store the selected voice with the book language as a suffix
146
- if (this.opts.bookLanguage) {
149
+ if (this.opts.bookLanguage && hasLocalStorage()) {
147
150
  localStorage.setItem(`BRtts-voice-${this.opts.bookLanguage}`, this.voice.voiceURI);
148
151
  }
149
152
  if (this.activeSound) this.activeSound.setVoice(this.voice);
@@ -247,7 +250,7 @@ export default class AbstractTTSEngine {
247
250
  * @return {SpeechSynthesisVoice | undefined}
248
251
  */
249
252
  static getMatchingStoredVoice(voices, bookLanguage) {
250
- const storedVoice = localStorage.getItem(`BRtts-voice-${bookLanguage}`);
253
+ const storedVoice = hasLocalStorage() && localStorage.getItem(`BRtts-voice-${bookLanguage}`);
251
254
  return (storedVoice ? voices.find(v => v.voiceURI === storedVoice) : undefined);
252
255
  }
253
256
 
@@ -251,7 +251,7 @@ BookReader.prototype.ttsPlayPause = function() {
251
251
  this.ttsToggle();
252
252
  } else {
253
253
  this.ttsEngine.togglePlayPause();
254
- this.ttsUpdateState(this.ttsEngine.paused);
254
+ this.ttsUpdateState();
255
255
  }
256
256
  };
257
257
 
@@ -64,3 +64,18 @@ function searchForISO6391(language, columnsToSearch) {
64
64
  }
65
65
  return null;
66
66
  }
67
+
68
+ /**
69
+ * Checks whether the current browser supports localStorage or
70
+ * if the current context has access to it.
71
+ * @return {boolean}
72
+ */
73
+ export function hasLocalStorage() {
74
+ try {
75
+ return !!window.localStorage;
76
+ } catch (e) {
77
+ // Will throw in sandboxed iframe
78
+ // DOMException: Window.localStorage getter: Forbidden in a sandboxed document without the 'allow-same-origin' flag.
79
+ return false;
80
+ }
81
+ }
@@ -40,4 +40,18 @@ describe("SelectionObserver", () => {
40
40
  observer._onSelectionChange();
41
41
  expect(handler.callCount).toBe(2);
42
42
  });
43
+
44
+ test('Only fires when selection started in selector', () => {
45
+ const handler = sinon.spy();
46
+ const observer = new SelectionObserver(".text-layer", handler);
47
+ const target = document.createElement("div");
48
+ target.classList.add("text-layer");
49
+
50
+ // stub window.getSelection
51
+ const getSelectionStub = sinon.stub(window, "getSelection");
52
+ getSelectionStub.returns({ toString: () => "test", anchorNode: document.body });
53
+ observer._onSelectionChange();
54
+ expect(handler.callCount).toBe(0);
55
+ expect(observer.selecting).toBe(false);
56
+ });
43
57
  });