@internetarchive/bookreader 5.0.0-72 → 5.0.0-73-alpha1

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 (62) hide show
  1. package/BookReader/BookReader.css +9 -6
  2. package/BookReader/BookReader.js +1 -1
  3. package/BookReader/BookReader.js.map +1 -1
  4. package/BookReader/ia-bookreader-bundle.js +9 -9
  5. package/BookReader/ia-bookreader-bundle.js.map +1 -1
  6. package/BookReader/icons/1up.svg +1 -1
  7. package/BookReader/icons/2up.svg +1 -1
  8. package/BookReader/icons/advance.svg +1 -1
  9. package/BookReader/icons/close-circle-dark.svg +1 -1
  10. package/BookReader/icons/close-circle.svg +1 -1
  11. package/BookReader/icons/fullscreen.svg +1 -1
  12. package/BookReader/icons/fullscreen_exit.svg +1 -1
  13. package/BookReader/icons/hamburger.svg +1 -1
  14. package/BookReader/icons/left-arrow.svg +1 -1
  15. package/BookReader/icons/magnify-minus.svg +1 -1
  16. package/BookReader/icons/magnify-plus.svg +1 -1
  17. package/BookReader/icons/magnify.svg +1 -1
  18. package/BookReader/icons/pause.svg +1 -1
  19. package/BookReader/icons/play.svg +1 -1
  20. package/BookReader/icons/playback-speed.svg +1 -1
  21. package/BookReader/icons/read-aloud.svg +1 -1
  22. package/BookReader/icons/review.svg +1 -1
  23. package/BookReader/icons/thumbnails.svg +1 -1
  24. package/BookReader/images/BRicons.svg +2 -2
  25. package/BookReader/images/books_graphic.svg +1 -1
  26. package/BookReader/images/icon_book.svg +1 -1
  27. package/BookReader/images/icon_gear.svg +1 -1
  28. package/BookReader/images/icon_info.svg +1 -1
  29. package/BookReader/images/icon_one_page.svg +1 -1
  30. package/BookReader/images/icon_search_button.svg +1 -1
  31. package/BookReader/images/icon_share.svg +1 -1
  32. package/BookReader/images/icon_speaker.svg +1 -1
  33. package/BookReader/images/icon_speaker_open.svg +1 -1
  34. package/BookReader/images/icon_thumbnails.svg +1 -1
  35. package/BookReader/images/icon_toc.svg +1 -1
  36. package/BookReader/images/icon_two_pages.svg +1 -1
  37. package/BookReader/images/marker_chap-off.svg +1 -1
  38. package/BookReader/images/marker_chap-on.svg +1 -1
  39. package/BookReader/images/marker_srch-on.svg +1 -1
  40. package/BookReader/plugins/plugin.archive_analytics.js +1 -1
  41. package/BookReader/plugins/plugin.autoplay.js +1 -1
  42. package/BookReader/plugins/plugin.autoplay.js.map +1 -1
  43. package/BookReader/plugins/plugin.chapters.js +2 -2
  44. package/BookReader/plugins/plugin.chapters.js.map +1 -1
  45. package/BookReader/plugins/plugin.resume.js +1 -1
  46. package/BookReader/plugins/plugin.search.js +1 -1
  47. package/BookReader/plugins/plugin.search.js.map +1 -1
  48. package/BookReader/plugins/plugin.text_selection.js +1 -1
  49. package/BookReader/plugins/plugin.text_selection.js.map +1 -1
  50. package/BookReader/plugins/plugin.tts.js +1 -1
  51. package/BookReader/plugins/plugin.tts.js.map +1 -1
  52. package/BookReader/plugins/plugin.url.js +1 -1
  53. package/BookReader/plugins/plugin.url.js.map +1 -1
  54. package/BookReader/plugins/plugin.vendor-fullscreen.js +1 -1
  55. package/BookReader/plugins/plugin.vendor-fullscreen.js.map +1 -1
  56. package/BookReaderDemo/BookReaderDemo.css +3 -0
  57. package/CHANGELOG.md +6 -1
  58. package/package.json +16 -16
  59. package/src/BookReader/options.js +3 -0
  60. package/src/css/_BRsearch.scss +4 -6
  61. package/src/plugins/plugin.chapters.js +36 -16
  62. package/tests/jest/plugins/plugin.chapters.test.js +51 -3
package/CHANGELOG.md CHANGED
@@ -1,3 +1,8 @@
1
+ # 5.0.0-73
2
+ - Feature: Add `table_of_contents` option to work with chapters plugin @cdrini
3
+ - Fix: Simple demos not working @xonx4l
4
+ - Dev: Update test/build dependencies @cdrini
5
+
1
6
  # 5.0.0-72
2
7
  - Fix: Play/pause button out of sync with ReadAloud @sbwhitt
3
8
  - Fix: BookReader not loading in sandboxed iframe @cdrini
@@ -647,7 +652,7 @@ be no observable changes, but note this was a big change.
647
652
 
648
653
  # 4.2.5
649
654
  - Large refactor of plugin.tts.js
650
- - ES6 compliation step
655
+ - ES6 compilation step
651
656
  - Known bug: Clicking on page while TTS is playing won't stop the playback
652
657
 
653
658
  # 4.2.4
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@internetarchive/bookreader",
3
- "version": "5.0.0-72",
3
+ "version": "5.0.0-73-alpha1",
4
4
  "description": "The Internet Archive BookReader.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -26,7 +26,7 @@
26
26
  "private": false,
27
27
  "dependencies": {
28
28
  "@internetarchive/ia-activity-indicator": "^0.0.4",
29
- "@internetarchive/ia-item-navigator": "^2.0.3",
29
+ "@internetarchive/ia-item-navigator": "^2.0.3-alpha2",
30
30
  "@internetarchive/icon-bookmark": "^1.3.4",
31
31
  "@internetarchive/icon-dl": "^1.3.4",
32
32
  "@internetarchive/icon-edit-pencil": "^1.3.4",
@@ -40,18 +40,18 @@
40
40
  "lit": "^2.5.0"
41
41
  },
42
42
  "devDependencies": {
43
- "@babel/core": "7.22.9",
44
- "@babel/eslint-parser": "7.22.9",
43
+ "@babel/core": "7.23.3",
44
+ "@babel/eslint-parser": "7.23.3",
45
45
  "@babel/plugin-proposal-class-properties": "7.18.6",
46
- "@babel/plugin-proposal-decorators": "7.22.7",
47
- "@babel/preset-env": "7.22.9",
48
- "@open-wc/testing-helpers": "^2.3.0",
49
- "@types/jest": "29.5.6",
46
+ "@babel/plugin-proposal-decorators": "7.23.3",
47
+ "@babel/preset-env": "7.23.3",
48
+ "@open-wc/testing-helpers": "3.0.0",
49
+ "@types/jest": "29.5.10",
50
50
  "@webcomponents/webcomponentsjs": "^2.6.0",
51
51
  "babel-loader": "9.1.3",
52
52
  "codecov": "^3.8.3",
53
- "concurrently": "7.6.0",
54
- "core-js": "3.27.1",
53
+ "concurrently": "8.2.2",
54
+ "core-js": "3.33.3",
55
55
  "cpx2": "4.2.3",
56
56
  "eslint": "^7.32.0",
57
57
  "eslint-plugin-no-jquery": "^2.7.0",
@@ -67,14 +67,14 @@
67
67
  "jquery-ui-touch-punch": "0.2.3",
68
68
  "jquery.browser": "0.1.0",
69
69
  "live-server": "1.2.2",
70
- "regenerator-runtime": "0.13.11",
71
- "sass": "1.64.2",
72
- "sinon": "^17.0.0",
70
+ "regenerator-runtime": "0.14.0",
71
+ "sass": "1.69.5",
72
+ "sinon": "17.0.1",
73
73
  "soundmanager2": "2.97.20170602",
74
- "svgo": "3.0.2",
75
- "testcafe": "2.6.2",
74
+ "svgo": "3.0.4",
75
+ "testcafe": "3.4.0",
76
76
  "testcafe-browser-provider-browserstack": "^1.13.2-alpha.1",
77
- "webpack": "5.88.2",
77
+ "webpack": "5.89.0",
78
78
  "webpack-cli": "5.1.4"
79
79
  },
80
80
  "jest": {
@@ -180,6 +180,9 @@ export const DEFAULT_OPTIONS = {
180
180
  */
181
181
  data: [],
182
182
 
183
+ /** @type {import('../plugins/plugin.chapters.js').TocEntry[]} */
184
+ table_of_contents: null,
185
+
183
186
  /** Advanced methods for page rendering */
184
187
  /** @type {() => number} */
185
188
  getNumLeafs: null,
@@ -9,8 +9,7 @@
9
9
  display: none;
10
10
  position: absolute;
11
11
  bottom: calc(100% + 5px);
12
- left: 50%;
13
- transform: translateX(-50%);
12
+ left: -14px;
14
13
  width: 350px;
15
14
  max-width: 100vw;
16
15
  padding: 12px 14px;
@@ -34,9 +33,7 @@
34
33
  position: absolute;
35
34
  content: "";
36
35
  bottom: -9px;
37
- left: 50%;
38
- margin-left: -1px;
39
- transform: translateX(-50%);
36
+ left: 0;
40
37
  width: 30px;
41
38
  height: 10px;
42
39
  clip-path: polygon(0 0, 100% 0, 50% 100%);
@@ -131,9 +128,10 @@
131
128
  main {
132
129
  @include ellipsis-lines(4);
133
130
  margin-bottom: 6px;
131
+ &:before { content: "“"; }
132
+ &:after { content: "”"; }
134
133
  }
135
134
  footer {
136
- text-align: center;
137
135
  font-size: 0.85em;
138
136
  opacity: .8;
139
137
  }
@@ -28,11 +28,28 @@ BookReader.prototype.init = (function(super_) {
28
28
  })(BookReader.prototype.init);
29
29
 
30
30
  BookReader.prototype._chapterInit = async function() {
31
- const olEdition = await this.getOpenLibraryRecord(this.options.olHost, this.options.bookId);
32
- if (olEdition?.table_of_contents?.length) {
33
- this._tocEntries = olEdition.table_of_contents.map(rawTOCEntry => (
34
- Object.assign({}, rawTOCEntry, {pageIndex: this.book.getPageIndex(rawTOCEntry.pagenum)})
35
- ));
31
+ let rawTableOfContents = null;
32
+ // Prefer IA TOC for now, until we update the second half to check for
33
+ // `openlibrary_edition` on the IA metadata instead of making a bunch of
34
+ // requests to OL.
35
+ if (this.options.table_of_contents?.length) {
36
+ rawTableOfContents = this.options.table_of_contents;
37
+ } else {
38
+ const olEdition = await this.getOpenLibraryRecord(this.options.olHost, this.options.bookId);
39
+ if (olEdition?.table_of_contents?.length) {
40
+ rawTableOfContents = olEdition.table_of_contents;
41
+ }
42
+ }
43
+
44
+ if (rawTableOfContents) {
45
+ this._tocEntries = rawTableOfContents
46
+ .map(rawTOCEntry => (Object.assign({}, rawTOCEntry, {
47
+ pageIndex: (
48
+ typeof(rawTOCEntry.leaf) == 'number' ? this.book.leafNumToIndex(rawTOCEntry.leaf) :
49
+ rawTOCEntry.pagenum ? this.book.getPageIndex(rawTOCEntry.pagenum) :
50
+ undefined
51
+ ),
52
+ })));
36
53
  this._chaptersRender(this._tocEntries);
37
54
  this.bind(BookReader.eventNames.pageChanged, () => this._chaptersUpdateCurrent());
38
55
  }
@@ -60,19 +77,18 @@ BookReader.prototype._chaptersRender = function() {
60
77
  />`,
61
78
  };
62
79
  shell.updateMenuContents();
63
- for (const tocEntry of this._tocEntries) {
64
- this._chaptersRenderMarker(tocEntry);
65
- }
80
+ this._tocEntries.forEach((tocEntry, i) => this._chaptersRenderMarker(tocEntry, i));
66
81
  };
67
82
 
68
83
  /**
69
84
  * @typedef {Object} TocEntry
70
85
  * Table of contents entry as defined by Open Library, with some extra values for internal use
71
- * @property {string} pagenum
72
- * @property {number} level
73
- * @property {string} label
74
- * @property {string} title
75
- * @property {number} pageIndex - Added
86
+ * @property {number} [level]
87
+ * @property {string} [label]
88
+ * @property {string} [title]
89
+ * @property {PageString} [pagenum]
90
+ * @property {LeafNum} [leaf]
91
+ * @property {number} [pageIndex] - Added
76
92
  *
77
93
  * @example {
78
94
  * "pagenum": "17",
@@ -84,21 +100,25 @@ BookReader.prototype._chaptersRender = function() {
84
100
 
85
101
  /**
86
102
  * @param {TocEntry} tocEntry
103
+ * @param {number} entryIndex
87
104
  */
88
- BookReader.prototype._chaptersRenderMarker = function(tocEntry) {
105
+ BookReader.prototype._chaptersRenderMarker = function(tocEntry, entryIndex) {
89
106
  if (tocEntry.pageIndex == undefined) return;
90
107
 
91
108
  //creates a string with non-void tocEntry.label and tocEntry.title
92
109
  const chapterStr = [tocEntry.label, tocEntry.title]
93
110
  .filter(x => x)
94
- .join(' ');
111
+ .join(' ') || `Chapter ${entryIndex + 1}`;
95
112
 
96
113
  const percentThrough = BookReader.util.cssPercentage(tocEntry.pageIndex, this.book.getNumLeafs() - 1);
97
114
  $(`<div></div>`)
98
115
  .append(
99
116
  $('<div />')
100
117
  .text(chapterStr)
101
- .append($('<div class="BRchapterPage" />').text(`Page ${tocEntry.pagenum}`))
118
+ .append(
119
+ $('<div class="BRchapterPage" />')
120
+ .text(this.book.getPageName(tocEntry.pageIndex))
121
+ )
102
122
  )
103
123
  .addClass('BRchapter')
104
124
  .css({ left: percentThrough })
@@ -4,7 +4,9 @@ import BookReader from "@/src/BookReader.js";
4
4
  import "@/src/plugins/plugin.chapters.js";
5
5
  import { BookModel } from "@/src/BookReader/BookModel";
6
6
  import { deepCopy } from "../utils";
7
+ /** @typedef {import('@/src/plugins/plugin.chapters').TocEntry} TocEntry */
7
8
 
9
+ /** @type {TocEntry[]} */
8
10
  const SAMPLE_TOC = [{
9
11
  "pagenum": "3",
10
12
  "level": 1,
@@ -34,16 +36,15 @@ const SAMPLE_TOC = [{
34
36
  "pageIndex": 40,
35
37
  }];
36
38
 
39
+ /** @type {TocEntry[]} */
37
40
  const SAMPLE_TOC_UNDEF = [
38
41
  {
39
- "pagenum": "undefined",
40
42
  "level": 1,
41
43
  "label": "CHAPTER I",
42
44
  "type": { "key": "/type/toc_item" },
43
45
  "title": "THE COUNTRY AND THE MISSION 1",
44
46
  },
45
47
  {
46
- "pagenum": "undefined",
47
48
  "level": 1,
48
49
  "label": "CHAPTER II",
49
50
  "type": { "key": "/type/toc_item" },
@@ -51,6 +52,18 @@ const SAMPLE_TOC_UNDEF = [
51
52
  },
52
53
  ];
53
54
 
55
+ /** @type {TocEntry[]} */
56
+ const SAMPLE_TOC_OPTION = [
57
+ {
58
+ "level": 1,
59
+ "title": "THE COUNTRY AND THE MISSION 1",
60
+ },
61
+ {
62
+ "level": 1,
63
+ "title": "THE COUNTRY AND THE MISSION 2",
64
+ },
65
+ ];
66
+
54
67
  afterEach(() => {
55
68
  sinon.restore();
56
69
  });
@@ -92,7 +105,7 @@ describe("BRChaptersPlugin", () => {
92
105
  },
93
106
  getOpenLibraryRecord: async () => ({
94
107
  "title": "The Adventures of Sherlock Holmes",
95
- "table_of_contents": deepCopy(SAMPLE_TOC_UNDEF),
108
+ "table_of_contents": deepCopy(SAMPLE_TOC_OPTION),
96
109
  "ocaid": "adventureofsherl0000unse",
97
110
  }),
98
111
  _chaptersRender: sinon.stub(),
@@ -100,6 +113,41 @@ describe("BRChaptersPlugin", () => {
100
113
  await BookReader.prototype._chapterInit.call(fakeBR);
101
114
  expect(fakeBR._chaptersRender.callCount).toBe(1);
102
115
  });
116
+
117
+ test("does not fetch open library record if table of contents in options", async () => {
118
+ const fakeBR = {
119
+ options: {
120
+ table_of_contents: deepCopy(SAMPLE_TOC_UNDEF),
121
+ },
122
+ bind: sinon.stub(),
123
+ getOpenLibraryRecord: sinon.stub(),
124
+ _chaptersRender: sinon.stub(),
125
+ };
126
+ await BookReader.prototype._chapterInit.call(fakeBR);
127
+ expect(fakeBR.getOpenLibraryRecord.callCount).toBe(0);
128
+ expect(fakeBR._chaptersRender.callCount).toBe(1);
129
+ });
130
+
131
+ test("converts leafs and pagenums to page index", async () => {
132
+ const table_of_contents = deepCopy(SAMPLE_TOC_UNDEF);
133
+ table_of_contents[0].leaf = 0;
134
+ table_of_contents[1].pagenum = '17';
135
+ const fakeBR = {
136
+ options: {
137
+ table_of_contents,
138
+ },
139
+ bind: sinon.stub(),
140
+ book: {
141
+ leafNumToIndex: (leaf) => leaf + 1,
142
+ getPageIndex: (str) => parseFloat(str),
143
+ },
144
+ _chaptersRender: sinon.stub(),
145
+ };
146
+ await BookReader.prototype._chapterInit.call(fakeBR);
147
+ expect(fakeBR._chaptersRender.callCount).toBe(1);
148
+ expect(fakeBR._tocEntries[0].pageIndex).toBe(1);
149
+ expect(fakeBR._tocEntries[1].pageIndex).toBe(17);
150
+ });
103
151
  });
104
152
 
105
153
  describe('_chaptersRender', () => {