@internetarchive/bookreader 5.0.0-92 → 5.0.0-94

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 (102) hide show
  1. package/BookReader/BookReader.css +2 -1
  2. package/BookReader/BookReader.js +1 -1
  3. package/BookReader/BookReader.js.map +1 -1
  4. package/BookReader/ia-bookreader-bundle.js +14 -14
  5. package/BookReader/ia-bookreader-bundle.js.map +1 -1
  6. package/BookReader/images/hypothesis.ico +0 -0
  7. package/BookReader/jquery-3.js +1 -1
  8. package/BookReader/plugins/plugin.archive_analytics.js +1 -1
  9. package/BookReader/plugins/plugin.archive_analytics.js.map +1 -1
  10. package/BookReader/plugins/plugin.autoplay.js +1 -1
  11. package/BookReader/plugins/plugin.autoplay.js.map +1 -1
  12. package/BookReader/plugins/plugin.chapters.js +2 -2
  13. package/BookReader/plugins/plugin.chapters.js.map +1 -1
  14. package/BookReader/plugins/plugin.experiments.js +3 -0
  15. package/BookReader/plugins/plugin.experiments.js.LICENSE.txt +1 -0
  16. package/BookReader/plugins/plugin.experiments.js.map +1 -0
  17. package/BookReader/plugins/plugin.iframe.js +1 -1
  18. package/BookReader/plugins/plugin.iiif.js +1 -1
  19. package/BookReader/plugins/plugin.iiif.js.map +1 -1
  20. package/BookReader/plugins/plugin.resume.js +1 -1
  21. package/BookReader/plugins/plugin.resume.js.map +1 -1
  22. package/BookReader/plugins/plugin.search.js +1 -1
  23. package/BookReader/plugins/plugin.search.js.map +1 -1
  24. package/BookReader/plugins/plugin.text_selection.js +1 -1
  25. package/BookReader/plugins/plugin.text_selection.js.map +1 -1
  26. package/BookReader/plugins/plugin.tts.js +1 -1
  27. package/BookReader/plugins/plugin.tts.js.map +1 -1
  28. package/BookReader/plugins/plugin.url.js +1 -1
  29. package/BookReader/plugins/plugin.url.js.map +1 -1
  30. package/BookReader/plugins/plugin.vendor-fullscreen.js +1 -1
  31. package/BookReader/plugins/plugin.vendor-fullscreen.js.map +1 -1
  32. package/BookReaderDemo/IADemoBr.js +1 -24
  33. package/BookReaderDemo/demo-internetarchive.html +1 -0
  34. package/CHANGELOG.md +14 -0
  35. package/package.json +8 -4
  36. package/scripts/postversion.js +3 -2
  37. package/scripts/preversion.js +3 -1
  38. package/scripts/version.js +4 -3
  39. package/src/BookNavigator/book-navigator.js +38 -12
  40. package/src/BookNavigator/downloads/downloads-provider.js +2 -2
  41. package/src/BookNavigator/search/search-provider.js +5 -5
  42. package/src/BookNavigator/search/search-results.js +1 -1
  43. package/src/BookNavigator/sharing.js +2 -2
  44. package/src/BookNavigator/viewable-files.js +2 -2
  45. package/src/BookNavigator/visual-adjustments/visual-adjustments-provider.js +3 -3
  46. package/src/BookNavigator/visual-adjustments/visual-adjustments.js +2 -2
  47. package/src/BookReader/BookModel.js +13 -3
  48. package/src/BookReader/ImageCache.js +2 -2
  49. package/src/BookReader/Mode1Up.js +2 -0
  50. package/src/BookReader/Mode1UpLit.js +5 -5
  51. package/src/BookReader/Mode2Up.js +2 -0
  52. package/src/BookReader/Mode2UpLit.js +5 -5
  53. package/src/BookReader/ModeCoordinateSpace.js +1 -1
  54. package/src/BookReader/ModeThumb.js +2 -0
  55. package/src/BookReader/PageContainer.js +4 -1
  56. package/src/BookReader/Toolbar/Toolbar.js +1 -1
  57. package/src/BookReader/options.js +5 -0
  58. package/src/BookReader/utils/HTMLDimensionsCacher.js +1 -1
  59. package/src/BookReader/utils.js +13 -0
  60. package/src/BookReader.js +57 -31
  61. package/src/assets/images/hypothesis.ico +0 -0
  62. package/src/css/_TextSelection.scss +3 -1
  63. package/src/plugins/plugin.autoplay.js +3 -3
  64. package/src/plugins/plugin.chapters.js +2 -2
  65. package/src/plugins/plugin.experiments.js +294 -0
  66. package/src/plugins/plugin.iiif.js +1 -1
  67. package/src/plugins/plugin.text_selection.js +112 -1
  68. package/src/plugins/search/plugin.search.js +2 -2
  69. package/src/plugins/search/view.js +5 -5
  70. package/src/plugins/tts/plugin.tts.js +3 -3
  71. package/src/plugins/url/plugin.url.js +2 -2
  72. package/tests/e2e/autoplay.test.js +1 -1
  73. package/tests/e2e/base.test.js +4 -4
  74. package/tests/e2e/helpers/base.js +2 -2
  75. package/tests/e2e/models/BookReader.js +1 -1
  76. package/tests/e2e/rightToLeft.test.js +4 -4
  77. package/tests/e2e/viewmode.test.js +2 -2
  78. package/tests/jest/BookNavigator/book-navigator.test.js +0 -13
  79. package/tests/jest/BookNavigator/downloads/downloads-provider.test.js +1 -1
  80. package/tests/jest/BookNavigator/downloads/downloads.test.js +1 -1
  81. package/tests/jest/BookNavigator/search/search-provider.test.js +5 -5
  82. package/tests/jest/BookReader/BookReaderPublicFunctions.test.js +1 -1
  83. package/tests/jest/BookReader/Mode2Up.test.js +1 -1
  84. package/tests/jest/BookReader/ModeCoordinateSpace.test.js +1 -1
  85. package/tests/jest/BookReader/PageContainer.test.js +14 -3
  86. package/tests/jest/BookReader/utils/HTMLDimensionsCacher.test.js +1 -1
  87. package/tests/jest/BookReader/utils/ScrollClassAdder.test.js +1 -1
  88. package/tests/jest/BookReader/utils/SelectionObserver.test.js +1 -1
  89. package/tests/jest/BookReader.test.js +10 -10
  90. package/tests/jest/plugins/plugin.autoplay.test.js +6 -6
  91. package/tests/jest/plugins/plugin.chapters.test.js +2 -2
  92. package/tests/jest/plugins/plugin.resume.test.js +13 -13
  93. package/tests/jest/plugins/plugin.text_selection.test.js +155 -24
  94. package/tests/jest/plugins/search/plugin.search.test.js +7 -7
  95. package/tests/jest/plugins/search/plugin.search.view.test.js +8 -8
  96. package/tests/jest/plugins/search/utils.js +1 -1
  97. package/tests/jest/plugins/tts/PageChunkIterator.test.js +2 -2
  98. package/tests/jest/plugins/url/UrlPlugin.test.js +1 -1
  99. package/webpack.config.js +8 -3
  100. /package/{.eslintrc.js → .eslintrc.cjs} +0 -0
  101. /package/{.testcaferc.js → .testcaferc.cjs} +0 -0
  102. /package/{babel.config.js → babel.config.cjs} +0 -0
@@ -45,23 +45,6 @@ BookReader.optionOverrides.imagesBaseURL = '/BookReader/images/';
45
45
  const initializeBookReader = (brManifest) => {
46
46
  console.log('initializeBookReader', brManifest);
47
47
 
48
- const {bookPath, subPrefix} = brManifest.data.brOptions;
49
- let path = bookPath;
50
- const subPrefixWithSlash = `/${subPrefix}`;
51
- if (bookPath.length - bookPath.lastIndexOf(subPrefixWithSlash) == subPrefixWithSlash.length) {
52
- path = bookPath.substr(0, bookPath.length - subPrefixWithSlash.length);
53
- }
54
-
55
- const searchInsideUrl = '//{{server}}/fulltext/inside.php?' + [
56
- 'item_id={{bookId|urlencode}}',
57
- 'doc={{subPrefix|urlencode}}',
58
- 'q={{query|urlencode}}',
59
- // This endpoint doesn't expect the path to be url encoded
60
- `path=${encodeURIComponent(path).replace(/%2F/g, '/')}`,
61
- 'pre_tag={{preTag|urlencode}}',
62
- 'post_tag={{postTag|urlencode}}',
63
- ].join('&');
64
-
65
48
  const options = {
66
49
  el: '#BookReader',
67
50
  /* Url plugin - IA uses History mode for URL */
@@ -74,6 +57,7 @@ const initializeBookReader = (brManifest) => {
74
57
  // urlTrackedParams: ['page', 'search', 'mode'],
75
58
  /* End url plugin */
76
59
  enableBookTitleLink: false,
60
+ bookUri: `https://archive.org/details/${ocaid}`,
77
61
  bookUrlText: null,
78
62
  startFullscreen: openFullImmersionTheater,
79
63
  // leaving this option commented out bc we change given user agent on archive.org
@@ -86,16 +70,9 @@ const initializeBookReader = (brManifest) => {
86
70
  /* End multiple volumes */
87
71
  enableBookmarks: true, // turn this on
88
72
  enableFSLogoShortcut: true,
89
-
90
- // TMP: To be replaced once BookReaderJSIA is updated to provide
91
- // these in the right spot.
92
73
  plugins: {
93
74
  search: {
94
- enabled: true,
95
75
  initialSearchTerm: searchTerm ? searchTerm : '',
96
- searchInsideUrl,
97
- preTag: brManifest.data.brOptions.searchInsidePreTag,
98
- postTag: brManifest.data.brOptions.searchInsidePostTag,
99
76
  },
100
77
  },
101
78
  };
@@ -30,6 +30,7 @@
30
30
  <script src="../BookReader/plugins/plugin.resume.js"></script>
31
31
  <script src="../BookReader/plugins/plugin.archive_analytics.js"></script>
32
32
  <script src="../BookReader/plugins/plugin.text_selection.js"></script>
33
+ <script src="../BookReader/plugins/plugin.experiments.js"></script>
33
34
 
34
35
  <script type="module" src="../BookReader/ia-bookreader-bundle.js"></script>
35
36
 
package/CHANGELOG.md CHANGED
@@ -1,3 +1,17 @@
1
+ # 5.0.0-94
2
+ - Refactor: Make bookreader package type: module @cdrini
3
+ - Fix: Search icon being fetched from wrong path @cdrini
4
+ - Refactor: Move BookReader._plugins -> BookReader.plugins , making it public @cdrini
5
+ - Feature: Add length restrictions for protected text selection @cdrini
6
+ - Extend BR to work correctly with Hypothesis @cdrini
7
+ - Creates new experiments plugin, with a Hypothesis experiment
8
+ - Adds no `bookUri` option for saving Hypothesis annotations
9
+ - Adds new public HTML attributes to the PageContainer DOM, `data-index` for `PageIndex`, and `data-page-num` for `PageNumString`
10
+ - Improves some of BookReader's public APIs. BookReader.bind/unbind are now deprecated in favor of BookReader.on/off
11
+
12
+ # 5.0.0-93
13
+ - Fix: Clicking on search result not making request_page request correctly @cdrini
14
+
1
15
  # 5.0.0-92
2
16
  - Refactor: Migrate search plugin to BookReaderPlugin system @cdrini
3
17
  - Breaking changes:
package/package.json CHANGED
@@ -1,7 +1,8 @@
1
1
  {
2
2
  "name": "@internetarchive/bookreader",
3
- "version": "5.0.0-92",
3
+ "version": "5.0.0-94",
4
4
  "description": "The Internet Archive BookReader.",
5
+ "type": "module",
5
6
  "repository": {
6
7
  "type": "git",
7
8
  "url": "git+https://github.com/internetarchive/bookreader.git"
@@ -58,6 +59,7 @@
58
59
  "eslint-plugin-no-jquery": "^2.7.0",
59
60
  "eslint-plugin-testcafe": "^0.2.1",
60
61
  "http-server": "14.1.1",
62
+ "hypothesis": "^1.1627.0",
61
63
  "interactjs": "^1.10.18",
62
64
  "iso-language-codes": "1.1.0",
63
65
  "jest": "29.7.0",
@@ -99,16 +101,18 @@
99
101
  "preversion": "npm run test && node scripts/preversion.js",
100
102
  "version": "node scripts/version.js",
101
103
  "postversion": "node scripts/postversion.js",
102
- "build": "npm run clean && npx concurrently --group npm:build-js npm:build-css npm:build-assets",
104
+ "build": "npm run clean && npx concurrently --group npm:build-js npm:build-css npm:build-assets npm:build-hypothesis",
103
105
  "build-assets": "npx cpx \"src/assets/**/*\" BookReader && npx svgo -f BookReader/icons && npx svgo -f BookReader/images",
104
106
  "build-assets:watch": "npx cpx --watch --verbose \"src/assets/**/*\" BookReader",
107
+ "build-hypothesis": "npx cpx \"node_modules/hypothesis/**/*\" BookReader/hypothesis",
108
+ "build-hypothesis:watch": "npx cpx --watch --verbose \"node_modules/hypothesis/**/*\" BookReader/hypothesis",
105
109
  "build-js": "npx webpack",
106
110
  "build-js:watch": "npx webpack --mode=development --watch",
107
111
  "build-css": "npx sass --no-source-map ./src/css/BookReader.scss ./BookReader/BookReader.css",
108
112
  "build-css:watch": "npx sass --watch --no-source-map ./src/css/BookReader.scss ./BookReader/BookReader.css",
109
113
  "clean": "rm -r BookReader/ || true",
110
- "lint": "npx eslint src/ tests/ *.js",
111
- "lint:fix": "npx eslint --fix src/ tests/ *.js",
114
+ "lint": "npx eslint src/ tests/ *.js *.cjs",
115
+ "lint:fix": "npx eslint --fix src/ tests/ *.js *.cjs",
112
116
  "serve": "npx http-server . --port=8000",
113
117
  "serve-live": "npx live-server . --cors --port=8000 --watch=index.html,BookReader,BookReaderDemo",
114
118
  "serve-dev": "env NODE_ENV='development' npm run build-css && env NODE_ENV='development' npx concurrently --kill-others npm:serve-live npm:build-*:watch",
@@ -1,5 +1,6 @@
1
- const fs = require('fs');
2
- const { version: NEW_VERSION } = require('../package.json');
1
+ import fs from 'fs';
2
+ import PACKAGE_JSON from '../package.json' assert { type: 'json' };
3
+ const NEW_VERSION = PACKAGE_JSON.version;
3
4
 
4
5
  const tag = `v${NEW_VERSION}`;
5
6
  const releaseBody = fs.readFileSync('CHANGELOG.md').toString()
@@ -1,4 +1,6 @@
1
- const { version: OLD_VERSION } = require('../package.json');
1
+ import PACKAGE_JSON from '../package.json' assert { type: 'json' };
2
+
3
+ const OLD_VERSION = PACKAGE_JSON.version;
2
4
  const OLD_RELEASE_URL = `https://api.github.com/repos/internetarchive/bookreader/releases/tags/v${OLD_VERSION}`;
3
5
 
4
6
  async function main() {
@@ -1,6 +1,7 @@
1
- const fs = require('fs');
2
- const { execSync } = require('child_process');
3
- const { version: NEW_VERSION } = require('../package.json');
1
+ import fs from 'fs';
2
+ import { execSync } from 'child_process';
3
+ import PACKAGE_JSON from '../package.json' assert { type: 'json' };
4
+ const NEW_VERSION = PACKAGE_JSON.version;
4
5
 
5
6
  async function main() {
6
7
  // Update the changelog
@@ -10,6 +10,7 @@ import BookmarksProvider from './bookmarks/bookmarks-provider.js';
10
10
  import SharingProvider from './sharing.js';
11
11
  import ViewableFilesProvider from './viewable-files.js';
12
12
  import iaLogo from './assets/ia-logo.js';
13
+ import { sortBy } from '../BookReader/utils.js';
13
14
  /** @typedef {import('@/src/BookReader.js').default} BookReader */
14
15
 
15
16
  const events = {
@@ -51,7 +52,20 @@ export class BookNavigator extends LitElement {
51
52
  this.isAdmin = false;
52
53
  this.lendingInitialized = false;
53
54
  this.lendingStatus = {};
54
- this.menuProviders = {};
55
+ this.menuProviders = {
56
+ /** @type {BookmarksProvider} */
57
+ bookmarks: null,
58
+ /** @type {SearchProvider} */
59
+ search: null,
60
+ /** @type {DownloadProvider} */
61
+ downloads: null,
62
+ /** @type {VisualAdjustmentProvider} */
63
+ visualAdjustments: null,
64
+ /** @type {SharingProvider} */
65
+ share: null,
66
+ /** @type {ViewableFilesProvider} */
67
+ volumes: null,
68
+ };
55
69
  this.menuShortcuts = [];
56
70
  this.signedIn = false;
57
71
  /** @type {ModalManager} */
@@ -73,6 +87,10 @@ export class BookNavigator extends LitElement {
73
87
  'chapters',
74
88
  'search',
75
89
  'bookmarks',
90
+ 'downloads',
91
+ 'visualAdjustments',
92
+ 'share',
93
+ 'experiments',
76
94
  ];
77
95
  }
78
96
 
@@ -313,14 +331,20 @@ export class BookNavigator extends LitElement {
313
331
  * Sets order of menu and emits custom event when done
314
332
  */
315
333
  updateMenuContents() {
316
- const {
317
- search, downloads, visualAdjustments, share, bookmarks, volumes, chapters,
318
- } = this.menuProviders;
319
- const availableMenus = [volumes, chapters, search, bookmarks, visualAdjustments, share].filter((menu) => !!menu);
334
+ const availableMenus = sortBy(
335
+ Object.entries(this.menuProviders)
336
+ .filter(([id, menu]) => !!menu)
337
+ .filter(([id, menu]) => {
338
+ return id === 'downloads' ? this.shouldShowDownloadsMenu() : true;
339
+ }),
340
+ ([id, menu]) => {
341
+ const index = this.shortcutOrder.indexOf(id);
342
+ return index === -1 ? this.shortcutOrder.length : index;
343
+ },
344
+ ).map(([id, menu]) => menu);
320
345
 
321
346
  if (this.shouldShowDownloadsMenu()) {
322
- downloads?.update(this.downloadableTypes);
323
- availableMenus.splice(-2, 0, downloads);
347
+ this.menuProviders.downloads?.update(this.downloadableTypes);
324
348
  }
325
349
 
326
350
  const event = new CustomEvent(
@@ -387,11 +411,13 @@ export class BookNavigator extends LitElement {
387
411
  * the id in each iteration over the shortcutOrder array.
388
412
  */
389
413
  sortMenuShortcuts() {
390
- this.menuShortcuts = this.shortcutOrder.reduce((shortcuts, id) => {
391
- const menu = this.menuShortcuts.find((m) => m.id === id);
392
- if (menu) { shortcuts.push(menu); }
393
- return shortcuts;
394
- }, []);
414
+ this.menuShortcuts = sortBy(
415
+ this.menuShortcuts,
416
+ (shortcut) => {
417
+ const index = this.shortcutOrder.indexOf(shortcut.id);
418
+ return index === -1 ? this.shortcutOrder.length : index;
419
+ },
420
+ );
395
421
  }
396
422
 
397
423
  emitMenuShortcutsUpdated() {
@@ -1,6 +1,6 @@
1
1
  import { html } from 'lit';
2
- import '@internetarchive/icon-dl/icon-dl';
3
- import './downloads';
2
+ import '@internetarchive/icon-dl/icon-dl.js';
3
+ import './downloads.js';
4
4
 
5
5
  const menuBase = {
6
6
  pdf: {
@@ -1,7 +1,7 @@
1
1
  // @ts-check
2
2
  import { html, nothing } from 'lit';
3
- import '@internetarchive/icon-search/icon-search';
4
- import './search-results';
3
+ import '@internetarchive/icon-search/icon-search.js';
4
+ import './search-results.js';
5
5
  /** @typedef {import('@/src/plugins/search/plugin.search.js').SearchInsideMatch} SearchInsideMatch */
6
6
  /** @typedef {import('@/src/plugins/search/plugin.search.js').SearchInsideResults} SearchInsideResults */
7
7
  /** @typedef {import('@/src/BookReader.js').default} BookReader */
@@ -143,7 +143,7 @@ export default class SearchProvider {
143
143
  }
144
144
 
145
145
  searchCanceledInMenu() {
146
- this.bookreader._plugins.search.cancelSearchRequest();
146
+ this.bookreader.plugins.search.cancelSearchRequest();
147
147
  }
148
148
 
149
149
  onSearchResultsCleared() {
@@ -155,7 +155,7 @@ export default class SearchProvider {
155
155
  errorMessage: '',
156
156
  };
157
157
  this.updateMenu({ openMenu: false });
158
- this.bookreader._plugins.search.searchView.clearSearchFieldAndResults(false);
158
+ this.bookreader.plugins.search.searchView.clearSearchFieldAndResults(false);
159
159
  if (this.bookreader.urlPlugin) {
160
160
  this.updateSearchInUrl();
161
161
  }
@@ -204,6 +204,6 @@ export default class SearchProvider {
204
204
  * @param {{ detail: {match: SearchInsideMatch} }} param0
205
205
  */
206
206
  onSearchResultsClicked({ detail }) {
207
- this.bookreader._plugins.search.jumpToMatch(detail.match.matchIndex);
207
+ this.bookreader.plugins.search.jumpToMatch(detail.match.matchIndex);
208
208
  }
209
209
  }
@@ -1,7 +1,7 @@
1
1
  /* eslint-disable class-methods-use-this */
2
2
  import { unsafeHTML } from 'lit/directives/unsafe-html.js';
3
3
  import { css, html, LitElement, nothing } from 'lit';
4
- import '@internetarchive/ia-activity-indicator/ia-activity-indicator';
4
+ import '@internetarchive/ia-activity-indicator/ia-activity-indicator.js';
5
5
  import checkmarkIcon from '../assets/icon_checkmark.js';
6
6
  import closeIcon from '../assets/icon_close.js';
7
7
  import buttonCSS from '../assets/button-base.js';
@@ -1,6 +1,6 @@
1
1
  import { html } from 'lit';
2
- import { iauxShareIcon } from '@internetarchive/ia-item-navigator/dist/src/menus/share-panel';
3
- import '@internetarchive/ia-item-navigator/dist/src/menus/share-panel';
2
+ import { iauxShareIcon } from '@internetarchive/ia-item-navigator/dist/src/menus/share-panel.js';
3
+ import '@internetarchive/ia-item-navigator/dist/src/menus/share-panel.js';
4
4
 
5
5
  export default class SharingProvider {
6
6
  constructor({
@@ -1,7 +1,7 @@
1
1
  import { html } from 'lit';
2
2
 
3
- import { viewableFilesIcon } from '@internetarchive/ia-item-navigator/dist/src/menus/viewable-files';
4
- import '@internetarchive/ia-item-navigator/dist/src/menus/viewable-files';
3
+ import { viewableFilesIcon } from '@internetarchive/ia-item-navigator/dist/src/menus/viewable-files.js';
4
+ import '@internetarchive/ia-item-navigator/dist/src/menus/viewable-files.js';
5
5
 
6
6
  /**
7
7
  * * @typedef { 'title_asc' | 'title_desc' | 'default'} SortTypesT
@@ -1,6 +1,6 @@
1
1
  import { html } from 'lit';
2
- import '@internetarchive/icon-visual-adjustment/icon-visual-adjustment';
3
- import './visual-adjustments';
2
+ import '@internetarchive/icon-visual-adjustment/icon-visual-adjustment.js';
3
+ import './visual-adjustments.js';
4
4
 
5
5
  const visualAdjustmentOptions = [{
6
6
  id: 'brightness',
@@ -45,7 +45,7 @@ export default class VisualAdjustmentsProvider {
45
45
  this.icon = html`<ia-icon-visual-adjustment style="width: var(--iconWidth); height: var(--iconHeight);"></ia-icon-visual-adjustment>`;
46
46
  this.label = 'Visual Adjustments';
47
47
  this.menuDetails = this.updateOptionsCount();
48
- this.id = 'adjustment';
48
+ this.id = 'visualAdjustments';
49
49
  this.component = html`
50
50
  <ia-book-visual-adjustments
51
51
  .options=${visualAdjustmentOptions}
@@ -2,8 +2,8 @@ import { css, html, LitElement } from "lit";
2
2
  import { repeat } from "lit/directives/repeat.js";
3
3
  import { nothing } from "lit";
4
4
  import checkmarkIcon from '../assets/icon_checkmark.js';
5
- import "@internetarchive/icon-magnify-minus/icon-magnify-minus";
6
- import "@internetarchive/icon-magnify-plus/icon-magnify-plus";
5
+ import "@internetarchive/icon-magnify-minus/icon-magnify-minus.js";
6
+ import "@internetarchive/icon-magnify-plus/icon-magnify-plus.js";
7
7
 
8
8
  const namespacedEvent = (eventName) => `visualAdjustment${eventName}`;
9
9
 
@@ -461,6 +461,15 @@ export class PageModel {
461
461
  return this.book.getPageURI(this.index, reduce, rotate);
462
462
  }
463
463
 
464
+ /**
465
+ * Return the asserted page number for this page, or, if one is not
466
+ * present, the n-prefixed page index.
467
+ * @returns {PageNumString}
468
+ */
469
+ getPageNum() {
470
+ return this.book.getPageNum(this.index);
471
+ }
472
+
464
473
  /**
465
474
  * Returns the srcset with correct URIs or void string if out of range
466
475
  * @param {number} reduce
@@ -539,12 +548,13 @@ export class PageModel {
539
548
  // There are a few main ways we can reference a specific page in a book:
540
549
  /**
541
550
  * @typedef {string} PageNumString
542
- * Possible values: /^n?\d+$/. Example: 'n7', '18'
543
- * Not necessarily unique
551
+ * The way page numbers are usually displayed in the UI. Either
552
+ * an asserted page number if the book has one (e.g. '18', or 'A-1'),
553
+ * or the n-prefixed 0-based index (e.g. 'n7')
544
554
  */
545
555
  /**
546
556
  * @typedef {number} LeafNum
547
- * No clue if 0 or 1 indexed or consecutive; generally from IA book info.
557
+ * Internal number to IA scans. Can be 0 or 1 indexed. Unclear it it's consecutive.
548
558
  */
549
559
  /**
550
560
  * @typedef {string} PageString
@@ -9,8 +9,8 @@
9
9
  /** @typedef {import("./ReduceSet").ReduceSet} ReduceSet */
10
10
  /** @typedef {import("./options").BookReaderOptions} BookReaderOptions */
11
11
 
12
- import { Pow2ReduceSet } from "./ReduceSet";
13
- import { DEFAULT_OPTIONS } from "./options";
12
+ import { Pow2ReduceSet } from "./ReduceSet.js";
13
+ import { DEFAULT_OPTIONS } from "./options.js";
14
14
 
15
15
  export class ImageCache {
16
16
  /**
@@ -6,6 +6,8 @@ import { DragScrollable } from './DragScrollable.js';
6
6
  /** @typedef {import('./BookModel.js').PageIndex} PageIndex */
7
7
 
8
8
  export class Mode1Up {
9
+ name = '1up'
10
+
9
11
  /**
10
12
  * @param {BookReader} br
11
13
  * @param {BookModel} bookModel
@@ -2,11 +2,11 @@
2
2
  import { customElement, property, query } from 'lit/decorators.js';
3
3
  import {LitElement, html} from 'lit';
4
4
  import { styleMap } from 'lit/directives/style-map.js';
5
- import { ModeSmoothZoom } from './ModeSmoothZoom';
6
- import { arrChanged, genToArray, sum, throttle } from './utils';
7
- import { HTMLDimensionsCacher } from "./utils/HTMLDimensionsCacher";
8
- import { ScrollClassAdder } from './utils/ScrollClassAdder';
9
- import { ModeCoordinateSpace } from './ModeCoordinateSpace';
5
+ import { ModeSmoothZoom } from './ModeSmoothZoom.js';
6
+ import { arrChanged, genToArray, sum, throttle } from './utils.js';
7
+ import { HTMLDimensionsCacher } from "./utils/HTMLDimensionsCacher.js";
8
+ import { ScrollClassAdder } from './utils/ScrollClassAdder.js';
9
+ import { ModeCoordinateSpace } from './ModeCoordinateSpace.js';
10
10
  /** @typedef {import('./BookModel').BookModel} BookModel */
11
11
  /** @typedef {import('./BookModel').PageIndex} PageIndex */
12
12
  /** @typedef {import('./BookModel').PageModel} PageModel */
@@ -6,6 +6,8 @@ import { DragScrollable } from './DragScrollable.js';
6
6
  /** @typedef {import('./BookModel.js').PageIndex} PageIndex */
7
7
 
8
8
  export class Mode2Up {
9
+ name = '2up';
10
+
9
11
  /**
10
12
  * @param {BookReader} br
11
13
  * @param {BookModel} bookModel
@@ -2,11 +2,11 @@
2
2
  import { customElement, property, query } from 'lit/decorators.js';
3
3
  import {LitElement, html} from 'lit';
4
4
  import { styleMap } from 'lit/directives/style-map.js';
5
- import { ModeSmoothZoom } from './ModeSmoothZoom';
6
- import { arrChanged, promisifyEvent } from './utils';
7
- import { HTMLDimensionsCacher } from "./utils/HTMLDimensionsCacher";
8
- import { PageModel } from './BookModel';
9
- import { ModeCoordinateSpace } from './ModeCoordinateSpace';
5
+ import { ModeSmoothZoom } from './ModeSmoothZoom.js';
6
+ import { arrChanged, promisifyEvent } from './utils.js';
7
+ import { HTMLDimensionsCacher } from "./utils/HTMLDimensionsCacher.js";
8
+ import { PageModel } from './BookModel.js';
9
+ import { ModeCoordinateSpace } from './ModeCoordinateSpace.js';
10
10
  /** @typedef {import('./BookModel').BookModel} BookModel */
11
11
  /** @typedef {import('./BookModel').PageIndex} PageIndex */
12
12
  /** @typedef {import('./ModeSmoothZoom').SmoothZoomable} SmoothZoomable */
@@ -1,4 +1,4 @@
1
- import { calcScreenDPI } from './utils';
1
+ import { calcScreenDPI } from './utils.js';
2
2
 
3
3
  /**
4
4
  * There are a few different "coordinate spaces" at play in BR:
@@ -9,6 +9,8 @@ import { DragScrollable } from './DragScrollable.js';
9
9
  /** @typedef {JQuery} $lazyLoadImgPlaceholder * jQuery element with data attributes: leaf, reduce */
10
10
 
11
11
  export class ModeThumb {
12
+ name = 'thumb'
13
+
12
14
  /**
13
15
  * @param {BookReader} br
14
16
  * @param {BookModel} bookModel
@@ -18,7 +18,10 @@ export class PageContainer {
18
18
  this.$container = $('<div />', {
19
19
  'class': `BRpagecontainer ${page ? `pagediv${page.index}` : 'BRemptypage'}`,
20
20
  css: { position: 'absolute' },
21
- }).attr('data-side', page?.pageSide);
21
+ })
22
+ .attr('data-side', page?.pageSide)
23
+ .attr('data-index', page?.index)
24
+ .attr('data-page-num', page?.getPageNum());
22
25
 
23
26
  if (isProtected) {
24
27
  this.$container.append($('<div class="BRscreen" />'));
@@ -60,7 +60,7 @@ export class Toolbar {
60
60
  }
61
61
 
62
62
  // Call _bindNavigationHandlers on the plugins
63
- for (const plugin of Object.values(br._plugins)) {
63
+ for (const plugin of Object.values(br.plugins)) {
64
64
  plugin._configureToolbar(br.refs.$BRtoolbar);
65
65
  }
66
66
 
@@ -97,6 +97,11 @@ export const DEFAULT_OPTIONS = {
97
97
  /** @type {string} */
98
98
  bookUrlTitle: null,
99
99
  enableBookTitleLink: true,
100
+ /**
101
+ * @type {string} A globally unique URI for the book. This is used to
102
+ * save data like annotations the user makes to the book.
103
+ */
104
+ bookUri: null,
100
105
  /**
101
106
  * @type {string} language in ISO 639-1 (PRIVATE: Will also
102
107
  * handle language name in English, native name, 639-2/T, or 639-2/B . (archive.org books
@@ -1,5 +1,5 @@
1
1
  // @ts-check
2
- import { debounce } from '../utils';
2
+ import { debounce } from '../utils.js';
3
3
 
4
4
  /**
5
5
  * Computing these things repeatedly is expensive (the browser needs to
@@ -298,3 +298,16 @@ export function parseAnimationSpeed(speed) {
298
298
  if (speed === 'fast') return 200;
299
299
  return parseInt(speed, 10);
300
300
  }
301
+
302
+ /**
303
+ * @template T
304
+ * @param {T[]} array
305
+ * @param {function(T): number} [valueFn]
306
+ */
307
+ export function sortBy(array, valueFn) {
308
+ return array.sort((a, b) => {
309
+ const aValue = valueFn ? valueFn(a) : a;
310
+ const bValue = valueFn ? valueFn(b) : b;
311
+ return aValue < bValue ? -1 : aValue > bValue ? 1 : 0;
312
+ });
313
+ }