@internetarchive/bookreader 5.0.0-33 → 5.0.0-34

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,4 +1,5 @@
1
1
  /* global BookReader, BookReaderJSIAinit */
2
+ import { extraVolOptions, custvolumesManifest } from './ia-multiple-volumes-manifest.js';
2
3
 
3
4
  /**
4
5
  * This is how Internet Archive loads bookreader
@@ -75,6 +76,18 @@ const initializeBookReader = (brManifest) => {
75
76
  }
76
77
  };
77
78
 
79
+ window.initializeBookReader = initializeBookReader;
80
+
81
+ const multiVolume = document.querySelector('#multi-volume');
82
+ multiVolume.addEventListener('click', () => {
83
+ // remove everything
84
+ $('#BookReader').empty();
85
+ delete window.br;
86
+ // and re-mount with a new book
87
+ BookReaderJSIAinit(custvolumesManifest, extraVolOptions);
88
+ });
89
+
90
+
78
91
  const fetchBookManifestAndInitializeBookreader = async (iaMetadata) => {
79
92
  document.querySelector('input[name="itemMD"]').checked = true;
80
93
  iaBookReader.item = iaMetadata;
@@ -38,9 +38,6 @@
38
38
  <!-- IA scripts -->
39
39
  <script src="https://archive.org/bookreader/BookReaderJSIA.js"></script>
40
40
 
41
- <!-- IA fetch demo -->
42
- <script type="module" src="IADemoBr.js"></script>
43
-
44
41
  </head>
45
42
 
46
43
  <body>
@@ -80,6 +77,9 @@
80
77
  <p>Features behind signed in gate: Bookmarks</p>
81
78
  <p>Logged In Status: <span id="logged-in-status">Logged Out</span></p>
82
79
  </div>
80
+ <div class="demo">
81
+ <button id="multi-volume">Multiple books</button>
82
+ </div>
83
83
  <div class="demo">
84
84
  <button id="start-fs">Start at Fullscreen</button>
85
85
  </div>
@@ -124,5 +124,8 @@
124
124
  placeholder.innerHTML = 'Dependencies are complete, bookreader has loaded';
125
125
  });
126
126
  </script>
127
+
128
+ <!-- IA fetch demo -->
129
+ <script type="module" src="IADemoBr.js"></script>
127
130
  </body>
128
131
  </html>
@@ -0,0 +1,170 @@
1
+ /* eslint-disable no-useless-escape */
2
+ const extraVolOptions = {
3
+ "isBeta": false,
4
+ "el": "#BookReader",
5
+ "enableBookTitleLink": false,
6
+ "bookUrlText": null,
7
+ "startFullscreen": false,
8
+ "initialSearchTerm": null,
9
+ "onePage": {
10
+ "autofit": "auto"
11
+ },
12
+ "showToolbar": false,
13
+ "autoResize": false,
14
+ "enableFSLogoShortcut": true,
15
+ "enableBookmarks": true,
16
+ "enableMultipleBooks": true,
17
+ "purchase_url": "",
18
+ "multipleBooksList": {
19
+ "by_subprefix": {
20
+ "book1/GPORFP": {
21
+ "url_path": "/details/SubBookTest",
22
+ "file_subprefix": "book1/GPORFP",
23
+ "title": "book1/GPORFP.pdf",
24
+ "file_source": "/book1/GPORFP_jp2.zip",
25
+ "orig_sort": 0
26
+ },
27
+ "subdir/book2/brewster_kahle_internet_archive": {
28
+ "url_path": "/details/SubBookTest/subdir/book2/brewster_kahle_internet_archive",
29
+ "file_subprefix": "subdir/book2/brewster_kahle_internet_archive",
30
+ "title": "subdir/book2/brewster_kahle_internet_archive.pdf",
31
+ "file_source": "/subdir/book2/brewster_kahle_internet_archive_jp2.zip",
32
+ "orig_sort": 1
33
+ },
34
+ "subdir/subsubdir/book3/Rfp008011ResponseInternetArchive-without-resume": {
35
+ "url_path": "/details/SubBookTest/subdir/subsubdir/book3/Rfp008011ResponseInternetArchive-without-resume",
36
+ "file_subprefix": "subdir/subsubdir/book3/Rfp008011ResponseInternetArchive-without-resume",
37
+ "title": "subdir/subsubdir/book3/Rfp008011ResponseInternetArchive-without-resume.pdf",
38
+ "file_source": "/subdir/subsubdir/book3/Rfp008011ResponseInternetArchive-without-resume_jp2.zip",
39
+ "orig_sort": 2
40
+ }
41
+ },
42
+ "main_dir": "/2/items/SubBookTest"
43
+ }
44
+ };
45
+ const custvolumesManifest = {
46
+ "data": {
47
+ "streamOnly": false,
48
+ "isRestricted": false,
49
+ "id": "SubBookTest",
50
+ "subPrefix": "book1/GPORFP",
51
+ "olHost": "https://openlibrary.org",
52
+ "bookUrl": "/details/SubBookTest",
53
+ "downloadUrls": [
54
+ [
55
+ "PDF",
56
+ "//archive.org/download/SubBookTest/book1/GPORFP.pdf"
57
+ ],
58
+ [
59
+ "ePub",
60
+ "//archive.org/download/SubBookTest/book1/GPORFP.epub"
61
+ ],
62
+ [
63
+ "Plain Text",
64
+ "//archive.org/download/SubBookTest/book1/GPORFP_djvu.txt"
65
+ ],
66
+ [
67
+ "DAISY",
68
+ "//archive.org/download/SubBookTest/book1/GPORFP_daisy.zip"
69
+ ],
70
+ [
71
+ "Kindle",
72
+ "//archive.org/download/SubBookTest/book1/GPORFP.mobi"
73
+ ]
74
+ ]
75
+ },
76
+ "brOptions": {
77
+ "bookId": "SubBookTest",
78
+ "bookPath": "/2/items/SubBookTest/book1/GPORFP",
79
+ "imageFormat": "jp2",
80
+ "server": "ia800304.us.archive.org",
81
+ "subPrefix": "book1/GPORFP",
82
+ "zip": "/2/items/SubBookTest/book1/GPORFP_jp2.zip",
83
+ "bookTitle": "Test with sub-dirs",
84
+ "ppi": "600",
85
+ "defaultStartLeaf": 0,
86
+ "pageProgression": "lr",
87
+ "vars": {
88
+ "bookId": "SubBookTest",
89
+ "bookPath": "/2/items/SubBookTest/book1/GPORFP",
90
+ "server": "ia800304.us.archive.org",
91
+ "subPrefix": "book1/GPORFP"
92
+ },
93
+ "plugins": {
94
+ "textSelection": {
95
+ "enabled": true,
96
+ "singlePageDjvuXmlUrl": "https://{{server}}/BookReader/BookReaderGetTextWrapper.php?path={{bookPath|urlencode}}_djvu.xml&mode=djvu_xml&page={{pageIndex}}"
97
+ }
98
+ },
99
+ "data": [
100
+ [
101
+ {
102
+ "width": 5213,
103
+ "height": 6566,
104
+ "uri": "https://ia800304.us.archive.org/BookReader/BookReaderImages.php?zip=/2/items/SubBookTest/book1/GPORFP_jp2.zip&file=GPORFP_jp2/GPORFP_0000.jp2&id=SubBookTest",
105
+ "leafNum": 0,
106
+ "uri_2": {
107
+ "link": "https://archive.org/download/SubBookTest/book1/GPORFP_jp2.zip/GPORFP_jp2%2FGPORFP_0000.jp2",
108
+ "base_params": "ext=jpg"
109
+ },
110
+ "pageType": "Title",
111
+ "pageSide": "R"
112
+ }
113
+ ]
114
+ ]
115
+ },
116
+ "lendingInfo": {
117
+ "lendingStatus": null,
118
+ "userid": 0,
119
+ "isAdmin": false,
120
+ "isArchiveOrgLending": false,
121
+ "isOpenLibraryLending": false,
122
+ "isLendingRequired": false,
123
+ "isBrowserBorrowable": false,
124
+ "isPrintDisabledOnly": false,
125
+ "isAvailable": false,
126
+ "isAvailableForBrowsing": false,
127
+ "userHasBorrowed": false,
128
+ "userHasBrowsed": false,
129
+ "userOnWaitingList": false,
130
+ "userHoldIsReady": false,
131
+ "userIsPrintDisabled": false,
132
+ "shouldProtectImages": false,
133
+ "daysLeftOnLoan": 0,
134
+ "secondsLeftOnLoan": 0,
135
+ "loansUrl": "",
136
+ "bookUrl": "",
137
+ "loanCount": 0,
138
+ "totalWaitlistCount": 0,
139
+ "userWaitlistPosition": -1,
140
+ "maxLoans": 10,
141
+ "loanRecord": [
142
+
143
+ ]
144
+ },
145
+ "metadata": {
146
+ "identifier": "SubBookTest",
147
+ "title": "Test with sub-dirs",
148
+ "mediatype": "texts",
149
+ "collection": [
150
+ "opensource",
151
+ "community"
152
+ ],
153
+ "publicdate": "2009-07-08 23:10:10",
154
+ "addeddate": "2009-07-08 23:09:09",
155
+ "uploader": "mang@archive.org",
156
+ "updatedate": "2009-07-08 23:10:24",
157
+ "updater": "mang@archive",
158
+ "language": "English",
159
+ "identifier-access": "http://www.archive.org/details/SubBookTest",
160
+ "identifier-ark": "ark:/13960/t08w3w21h",
161
+ "ppi": "600",
162
+ "ocr": "ABBYY FineReader 8.0",
163
+ "repub_state": "4",
164
+ "noindex": "true",
165
+ "curation": "[curator]validator@archive.org[/curator][date]20140402011645[/date][comment]checked for malware[/comment]",
166
+ "backup_location": "ia903603_14"
167
+ }
168
+ };
169
+
170
+ export { custvolumesManifest, extraVolOptions };
package/CHANGELOG.md CHANGED
@@ -1,3 +1,8 @@
1
+ # 5.0.0-34
2
+ Dev: udpate test dependencies @cdrini
3
+ Fix: Update hyphen stitching regex to include dangling "¬" @cdrini
4
+ Fix: pop open multiple files menu at proper width @iisa
5
+
1
6
  # 5.0.0-33
2
7
  Fix: restricted books get cover image @iisa
3
8
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@internetarchive/bookreader",
3
- "version": "5.0.0-33",
3
+ "version": "5.0.0-34",
4
4
  "description": "The Internet Archive BookReader.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -45,41 +45,41 @@
45
45
  },
46
46
  "devDependencies": {
47
47
  "@babel/core": "7.15.0",
48
- "@babel/eslint-parser": "^7.15.7",
48
+ "@babel/eslint-parser": "^7.16.5",
49
49
  "@babel/plugin-proposal-class-properties": "^7.14.5",
50
50
  "@babel/plugin-proposal-decorators": "^7.14.5",
51
51
  "@babel/preset-env": "7.15.0",
52
52
  "@open-wc/testing": "^2.5.33",
53
53
  "@open-wc/testing-karma": "^4.0.9",
54
- "@types/jest": "27.0.1",
54
+ "@types/jest": "^27.4.0",
55
55
  "@webcomponents/webcomponentsjs": "^2.6.0",
56
56
  "babel-loader": "8.2.2",
57
- "codecov": "3.8.3",
57
+ "codecov": "^3.8.3",
58
58
  "concurrently": "6.0.2",
59
59
  "core-js": "3.16.2",
60
60
  "cpx2": "3.0.0",
61
61
  "eslint": "^7.32.0",
62
- "eslint-plugin-no-jquery": "^2.6.0",
63
- "eslint-plugin-testcafe": "0.2.1",
62
+ "eslint-plugin-no-jquery": "^2.7.0",
63
+ "eslint-plugin-testcafe": "^0.2.1",
64
64
  "hammerjs": "^2.0.8",
65
65
  "http-server": "0.12.3",
66
66
  "iso-language-codes": "1.1.0",
67
- "jest": "27.0.6",
67
+ "jest": "^27.4.7",
68
68
  "jquery": "1.11.3",
69
69
  "jquery-colorbox": "1.6.4",
70
70
  "jquery-ui": "1.12.1",
71
71
  "jquery-ui-touch-punch": "0.2.3",
72
72
  "jquery.browser": "0.1.0",
73
73
  "jquery.mmenu": "5.6.5",
74
- "karma-coverage": "^2.0.3",
74
+ "karma-coverage": "^2.1.0",
75
75
  "live-server": "1.2.1",
76
76
  "node-fetch": "2.6.1",
77
77
  "regenerator-runtime": "0.13.9",
78
78
  "sass": "1.38.2",
79
- "sinon": "11.1.2",
79
+ "sinon": "^12.0.1",
80
80
  "soundmanager2": "2.97.20170602",
81
81
  "svgo": "2.4.0",
82
- "testcafe": "^1.16.1",
82
+ "testcafe": "^1.18.3",
83
83
  "testcafe-browser-provider-browserstack": "^1.13.2-alpha.1",
84
84
  "webpack": "5.51.1",
85
85
  "webpack-cli": "4.8.0"
@@ -147,6 +147,9 @@ export class BookNavigator extends LitElement {
147
147
  };
148
148
  }
149
149
 
150
+ get isWideEnoughToOpenMenu() {
151
+ return this.brWidth >= 640;
152
+ }
150
153
  /**
151
154
  * Instantiates books submenus & their update callbacks
152
155
  *
@@ -181,8 +184,7 @@ export class BookNavigator extends LitElement {
181
184
  /* refresh br instance reference */
182
185
  this.bookreader = brInstance;
183
186
  }
184
- const wideEnoughToOpenMenu = this.brWidth >= 640;
185
- if (wideEnoughToOpenMenu && !searchUpdates?.searchCanceled) {
187
+ if (this.isWideEnoughToOpenMenu && !searchUpdates?.searchCanceled) {
186
188
  /* open side search menu */
187
189
  setTimeout(() => {
188
190
  this.updateSideMenu('search', 'open');
@@ -214,7 +216,12 @@ export class BookNavigator extends LitElement {
214
216
  this.bookreader = brInstance;
215
217
  }
216
218
  this.updateMenuContents();
217
- this.updateSideMenu('volumes', 'open');
219
+ if (this.isWideEnoughToOpenMenu) {
220
+ /* open side search menu */
221
+ setTimeout(() => {
222
+ this.updateSideMenu('volumes', 'open');
223
+ });
224
+ }
218
225
  }
219
226
  });
220
227
  }
@@ -52,6 +52,10 @@ export class IaBookReader extends LitElement {
52
52
  }
53
53
  }
54
54
 
55
+ get itemNav() {
56
+ return this.shadowRoot.querySelector('ia-item-navigator');
57
+ }
58
+
55
59
  /** Creates modal DOM & attaches to `<body>` */
56
60
  setModalManager() {
57
61
  let modalManager = document.querySelector('modal-manager');
@@ -95,11 +99,10 @@ export class IaBookReader extends LitElement {
95
99
  }
96
100
 
97
101
  if (action === 'open') {
98
- this.itemNav.openShortcut(menuId);
99
- this.openShortcut(menuId);
102
+ this.itemNav?.openShortcut(menuId);
100
103
  } else if (action === 'toggle') {
101
- this.itemNav.openMenu(menuId);
102
- this.itemNav.toggleMenu();
104
+ this.itemNav?.openMenu(menuId);
105
+ this.itemNav?.toggleMenu();
103
106
  }
104
107
  }
105
108
 
@@ -97,7 +97,10 @@ export default class PageChunk {
97
97
  * @return {string}
98
98
  */
99
99
  static _removeDanglingHyphens(text) {
100
- return text.replace(/-\s+/g, '');
100
+ // Some books mis-OCR a dangling hyphen as a ¬ (mathematical not sign) . Since in math
101
+ // the not sign should not appear followed by a space, we think we can safely assume
102
+ // this should be replaced.
103
+ return text.replace(/[-¬]\s+/g, '');
101
104
  }
102
105
  }
103
106
 
@@ -220,6 +220,18 @@ describe('<book-navigator>', () => {
220
220
 
221
221
  describe('Controlling Menu Side Panel & Shortcuts', () => {
222
222
  describe('Side Menu Panels', () => {
223
+ it('`isWideEnoughToOpenMenu` checks if menu should be open', async () => {
224
+ const el = fixtureSync(container());
225
+ el.brWidth = 300;
226
+ await el.elementUpdated;
227
+
228
+ expect(el.isWideEnoughToOpenMenu).to.equal(false);
229
+
230
+ el.brWidth = 641;
231
+ await el.elementUpdated;
232
+
233
+ expect(el.isWideEnoughToOpenMenu).to.equal(true);
234
+ });
223
235
  describe('Control which side menu to toggle open by using: `this.updateSideMenu`', () => {
224
236
  it('Emits `@updateSideMenu` to signal which menu gets the update', async () => {
225
237
  const el = fixtureSync(container());