@internetarchive/bookreader 5.0.0-116 → 5.0.0-118-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 (205) hide show
  1. package/README.md +3 -1
  2. package/package.json +35 -31
  3. package/src/BookReader.js +16 -0
  4. package/src/css/_TextSelection.scss +51 -18
  5. package/src/plugins/plugin.chapters.js +8 -4
  6. package/src/plugins/plugin.iframe.js +36 -37
  7. package/src/plugins/plugin.text_selection.js +36 -11
  8. package/src/plugins/search/plugin.search.js +2 -8
  9. package/src/plugins/tts/plugin.tts.js +27 -8
  10. package/src/util/TextSelectionManager.js +53 -8
  11. package/src/util/dom.js +88 -0
  12. package/BookReader/474.js +0 -2
  13. package/BookReader/474.js.map +0 -1
  14. package/BookReader/BookReader.css +0 -2425
  15. package/BookReader/BookReader.js +0 -3
  16. package/BookReader/BookReader.js.LICENSE.txt +0 -72
  17. package/BookReader/BookReader.js.map +0 -1
  18. package/BookReader/bergamot-translator-worker.js +0 -2966
  19. package/BookReader/bergamot-translator-worker.wasm +0 -0
  20. package/BookReader/hypothesis/LICENSE +0 -50
  21. package/BookReader/hypothesis/README.md +0 -55
  22. package/BookReader/hypothesis/build/boot.js +0 -1
  23. package/BookReader/hypothesis/build/manifest.json +0 -20
  24. package/BookReader/hypothesis/build/scripts/annotator.bundle.js +0 -184
  25. package/BookReader/hypothesis/build/scripts/annotator.bundle.js.map +0 -1
  26. package/BookReader/hypothesis/build/scripts/sidebar.bundle.js +0 -798
  27. package/BookReader/hypothesis/build/scripts/sidebar.bundle.js.map +0 -1
  28. package/BookReader/hypothesis/build/scripts/ui-playground.bundle.js +0 -711
  29. package/BookReader/hypothesis/build/scripts/ui-playground.bundle.js.map +0 -1
  30. package/BookReader/hypothesis/build/styles/annotator.css +0 -2235
  31. package/BookReader/hypothesis/build/styles/annotator.css.map +0 -1
  32. package/BookReader/hypothesis/build/styles/fonts/KaTeX_AMS-Regular.woff2 +0 -0
  33. package/BookReader/hypothesis/build/styles/fonts/KaTeX_Caligraphic-Bold.woff2 +0 -0
  34. package/BookReader/hypothesis/build/styles/fonts/KaTeX_Caligraphic-Regular.woff2 +0 -0
  35. package/BookReader/hypothesis/build/styles/fonts/KaTeX_Fraktur-Bold.woff2 +0 -0
  36. package/BookReader/hypothesis/build/styles/fonts/KaTeX_Fraktur-Regular.woff2 +0 -0
  37. package/BookReader/hypothesis/build/styles/fonts/KaTeX_Main-Bold.woff2 +0 -0
  38. package/BookReader/hypothesis/build/styles/fonts/KaTeX_Main-BoldItalic.woff2 +0 -0
  39. package/BookReader/hypothesis/build/styles/fonts/KaTeX_Main-Italic.woff2 +0 -0
  40. package/BookReader/hypothesis/build/styles/fonts/KaTeX_Main-Regular.woff2 +0 -0
  41. package/BookReader/hypothesis/build/styles/fonts/KaTeX_Math-BoldItalic.woff2 +0 -0
  42. package/BookReader/hypothesis/build/styles/fonts/KaTeX_Math-Italic.woff2 +0 -0
  43. package/BookReader/hypothesis/build/styles/fonts/KaTeX_SansSerif-Bold.woff2 +0 -0
  44. package/BookReader/hypothesis/build/styles/fonts/KaTeX_SansSerif-Italic.woff2 +0 -0
  45. package/BookReader/hypothesis/build/styles/fonts/KaTeX_SansSerif-Regular.woff2 +0 -0
  46. package/BookReader/hypothesis/build/styles/fonts/KaTeX_Script-Regular.woff2 +0 -0
  47. package/BookReader/hypothesis/build/styles/fonts/KaTeX_Size1-Regular.woff2 +0 -0
  48. package/BookReader/hypothesis/build/styles/fonts/KaTeX_Size2-Regular.woff2 +0 -0
  49. package/BookReader/hypothesis/build/styles/fonts/KaTeX_Size3-Regular.woff2 +0 -0
  50. package/BookReader/hypothesis/build/styles/fonts/KaTeX_Size4-Regular.woff2 +0 -0
  51. package/BookReader/hypothesis/build/styles/fonts/KaTeX_Typewriter-Regular.woff2 +0 -0
  52. package/BookReader/hypothesis/build/styles/highlights.css +0 -2
  53. package/BookReader/hypothesis/build/styles/highlights.css.map +0 -1
  54. package/BookReader/hypothesis/build/styles/katex.min.css +0 -2
  55. package/BookReader/hypothesis/build/styles/katex.min.css.map +0 -1
  56. package/BookReader/hypothesis/build/styles/pdfjs-overrides.css +0 -2
  57. package/BookReader/hypothesis/build/styles/pdfjs-overrides.css.map +0 -1
  58. package/BookReader/hypothesis/build/styles/sidebar.css +0 -2731
  59. package/BookReader/hypothesis/build/styles/sidebar.css.map +0 -1
  60. package/BookReader/hypothesis/build/styles/ui-playground.css +0 -2659
  61. package/BookReader/hypothesis/build/styles/ui-playground.css.map +0 -1
  62. package/BookReader/hypothesis/package.json +0 -126
  63. package/BookReader/ia-bookreader-bundle.js +0 -1886
  64. package/BookReader/ia-bookreader-bundle.js.LICENSE.txt +0 -19
  65. package/BookReader/ia-bookreader-bundle.js.map +0 -1
  66. package/BookReader/icons/1up.svg +0 -1
  67. package/BookReader/icons/2up.svg +0 -1
  68. package/BookReader/icons/advance.svg +0 -3
  69. package/BookReader/icons/chevron-right.svg +0 -1
  70. package/BookReader/icons/close-circle-dark.svg +0 -1
  71. package/BookReader/icons/close-circle.svg +0 -1
  72. package/BookReader/icons/fullscreen.svg +0 -1
  73. package/BookReader/icons/fullscreen_exit.svg +0 -1
  74. package/BookReader/icons/hamburger.svg +0 -1
  75. package/BookReader/icons/left-arrow.svg +0 -1
  76. package/BookReader/icons/magnify-minus.svg +0 -1
  77. package/BookReader/icons/magnify-plus.svg +0 -1
  78. package/BookReader/icons/magnify.svg +0 -1
  79. package/BookReader/icons/pause.svg +0 -1
  80. package/BookReader/icons/play.svg +0 -1
  81. package/BookReader/icons/playback-speed.svg +0 -1
  82. package/BookReader/icons/read-aloud.svg +0 -1
  83. package/BookReader/icons/review.svg +0 -3
  84. package/BookReader/icons/slider-toggle.svg +0 -1
  85. package/BookReader/icons/thumbnails.svg +0 -1
  86. package/BookReader/icons/voice.svg +0 -1
  87. package/BookReader/icons/volume-full.svg +0 -1
  88. package/BookReader/images/BRicons.png +0 -0
  89. package/BookReader/images/BRicons.svg +0 -5
  90. package/BookReader/images/BRicons_ia.png +0 -0
  91. package/BookReader/images/back_pages.png +0 -0
  92. package/BookReader/images/book_bottom_icon.png +0 -0
  93. package/BookReader/images/book_down_icon.png +0 -0
  94. package/BookReader/images/book_left_icon.png +0 -0
  95. package/BookReader/images/book_leftmost_icon.png +0 -0
  96. package/BookReader/images/book_right_icon.png +0 -0
  97. package/BookReader/images/book_rightmost_icon.png +0 -0
  98. package/BookReader/images/book_top_icon.png +0 -0
  99. package/BookReader/images/book_up_icon.png +0 -0
  100. package/BookReader/images/books_graphic.svg +0 -1
  101. package/BookReader/images/booksplit.png +0 -0
  102. package/BookReader/images/control_pause_icon.png +0 -0
  103. package/BookReader/images/control_play_icon.png +0 -0
  104. package/BookReader/images/embed_icon.png +0 -0
  105. package/BookReader/images/hypothesis.ico +0 -0
  106. package/BookReader/images/icon-home-ia.png +0 -0
  107. package/BookReader/images/icon_OL-logo-xs.png +0 -0
  108. package/BookReader/images/icon_alert-xs.png +0 -0
  109. package/BookReader/images/icon_book.svg +0 -1
  110. package/BookReader/images/icon_bookmark.svg +0 -1
  111. package/BookReader/images/icon_close-pop.png +0 -0
  112. package/BookReader/images/icon_download.png +0 -0
  113. package/BookReader/images/icon_experiment.svg +0 -1
  114. package/BookReader/images/icon_gear.svg +0 -1
  115. package/BookReader/images/icon_hamburger.svg +0 -1
  116. package/BookReader/images/icon_home.png +0 -0
  117. package/BookReader/images/icon_home.svg +0 -1
  118. package/BookReader/images/icon_home_ia.png +0 -0
  119. package/BookReader/images/icon_indicator.png +0 -0
  120. package/BookReader/images/icon_info.svg +0 -1
  121. package/BookReader/images/icon_one_page.svg +0 -1
  122. package/BookReader/images/icon_pause.svg +0 -1
  123. package/BookReader/images/icon_play.svg +0 -1
  124. package/BookReader/images/icon_playback-rate.svg +0 -1
  125. package/BookReader/images/icon_return.png +0 -0
  126. package/BookReader/images/icon_search_button.svg +0 -1
  127. package/BookReader/images/icon_share.svg +0 -1
  128. package/BookReader/images/icon_skip-ahead.svg +0 -1
  129. package/BookReader/images/icon_skip-back.svg +0 -2
  130. package/BookReader/images/icon_speaker.svg +0 -1
  131. package/BookReader/images/icon_speaker_open.svg +0 -1
  132. package/BookReader/images/icon_thumbnails.svg +0 -1
  133. package/BookReader/images/icon_toc.svg +0 -1
  134. package/BookReader/images/icon_two_pages.svg +0 -1
  135. package/BookReader/images/icon_zoomer.png +0 -0
  136. package/BookReader/images/loading.gif +0 -0
  137. package/BookReader/images/logo_icon.png +0 -0
  138. package/BookReader/images/marker_chap-off.png +0 -0
  139. package/BookReader/images/marker_chap-off.svg +0 -1
  140. package/BookReader/images/marker_chap-off_ia.png +0 -0
  141. package/BookReader/images/marker_chap-on.png +0 -0
  142. package/BookReader/images/marker_chap-on.svg +0 -1
  143. package/BookReader/images/marker_srch-on.svg +0 -1
  144. package/BookReader/images/marker_srchchap-off.png +0 -0
  145. package/BookReader/images/marker_srchchap-on.png +0 -0
  146. package/BookReader/images/nav_control-dn.png +0 -0
  147. package/BookReader/images/nav_control-dn_ia.png +0 -0
  148. package/BookReader/images/nav_control-up.png +0 -0
  149. package/BookReader/images/nav_control-up_ia.png +0 -0
  150. package/BookReader/images/nav_control.png +0 -0
  151. package/BookReader/images/one_page_mode_icon.png +0 -0
  152. package/BookReader/images/paper-badge.png +0 -0
  153. package/BookReader/images/print_icon.png +0 -0
  154. package/BookReader/images/progressbar.gif +0 -0
  155. package/BookReader/images/right_edges.png +0 -0
  156. package/BookReader/images/slider.png +0 -0
  157. package/BookReader/images/slider_ia.png +0 -0
  158. package/BookReader/images/thumbnail_mode_icon.png +0 -0
  159. package/BookReader/images/translate.svg +0 -1
  160. package/BookReader/images/transparent.png +0 -0
  161. package/BookReader/images/two_page_mode_icon.png +0 -0
  162. package/BookReader/images/unviewable_page.png +0 -0
  163. package/BookReader/images/zoom_in_icon.png +0 -0
  164. package/BookReader/images/zoom_out_icon.png +0 -0
  165. package/BookReader/jquery-3.js +0 -2
  166. package/BookReader/jquery-3.js.LICENSE.txt +0 -24
  167. package/BookReader/plugins/plugin.archive_analytics.js +0 -2
  168. package/BookReader/plugins/plugin.archive_analytics.js.map +0 -1
  169. package/BookReader/plugins/plugin.autoplay.js +0 -2
  170. package/BookReader/plugins/plugin.autoplay.js.map +0 -1
  171. package/BookReader/plugins/plugin.chapters.js +0 -23
  172. package/BookReader/plugins/plugin.chapters.js.LICENSE.txt +0 -1
  173. package/BookReader/plugins/plugin.chapters.js.map +0 -1
  174. package/BookReader/plugins/plugin.experiments.js +0 -3
  175. package/BookReader/plugins/plugin.experiments.js.LICENSE.txt +0 -1
  176. package/BookReader/plugins/plugin.experiments.js.map +0 -1
  177. package/BookReader/plugins/plugin.iframe.js +0 -2
  178. package/BookReader/plugins/plugin.iframe.js.map +0 -1
  179. package/BookReader/plugins/plugin.iiif.js +0 -2
  180. package/BookReader/plugins/plugin.iiif.js.map +0 -1
  181. package/BookReader/plugins/plugin.resume.js +0 -2
  182. package/BookReader/plugins/plugin.resume.js.map +0 -1
  183. package/BookReader/plugins/plugin.search.js +0 -3
  184. package/BookReader/plugins/plugin.search.js.LICENSE.txt +0 -1
  185. package/BookReader/plugins/plugin.search.js.map +0 -1
  186. package/BookReader/plugins/plugin.text_selection.js +0 -45
  187. package/BookReader/plugins/plugin.text_selection.js.LICENSE.txt +0 -1
  188. package/BookReader/plugins/plugin.text_selection.js.map +0 -1
  189. package/BookReader/plugins/plugin.translate.js +0 -179
  190. package/BookReader/plugins/plugin.translate.js.LICENSE.txt +0 -1
  191. package/BookReader/plugins/plugin.translate.js.map +0 -1
  192. package/BookReader/plugins/plugin.tts.js +0 -3
  193. package/BookReader/plugins/plugin.tts.js.LICENSE.txt +0 -29
  194. package/BookReader/plugins/plugin.tts.js.map +0 -1
  195. package/BookReader/plugins/plugin.url.js +0 -2
  196. package/BookReader/plugins/plugin.url.js.map +0 -1
  197. package/BookReader/plugins/plugin.vendor-fullscreen.js +0 -2
  198. package/BookReader/plugins/plugin.vendor-fullscreen.js.map +0 -1
  199. package/BookReader/plugins/translator-worker.js +0 -2
  200. package/BookReader/plugins/translator-worker.js.map +0 -1
  201. package/BookReader/silence.mp3 +0 -0
  202. package/BookReader/translator-worker.js +0 -475
  203. package/BookReader/webcomponents-bundle.js +0 -3
  204. package/BookReader/webcomponents-bundle.js.LICENSE.txt +0 -9
  205. package/BookReader/webcomponents-bundle.js.map +0 -1
package/README.md CHANGED
@@ -167,7 +167,9 @@ To version bump the repo and prepare a release, run `npm version major|minor|pat
167
167
  We release BookReader [in-repo as tags](https://github.com/internetarchive/bookreader/releases) & also as a node module [@internetarchive/bookreader](https://www.npmjs.com/package/@internetarchive/bookreader)
168
168
 
169
169
  ## Tests
170
- We would like to get to 100% test coverage and are tracking our progress in this project: [BookReader Fidelity](https://github.com/internetarchive/bookreader/projects/5)
170
+
171
+ When contributing code, please
172
+ include unit tests and/or update tests accordingly. [Current code coverage can be tracked here](https://app.codecov.io/gh/internetarchive/bookreader).
171
173
 
172
174
  ### End to end tests
173
175
  We also have end to end tests using [Testcafe](https://devexpress.github.io/testcafe/documentation/getting-started/). We write tests for the repo itself and also for our use on archive.org. You can read about them in [here](./tests/e2e/README.md). These are relatively easy to do, and a fantastic way of getting introduced to the wonders of BookReader. Check the project board for open tickets to work on. And if you don't see a test for something you spotted, feel free to make an issue.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@internetarchive/bookreader",
3
- "version": "5.0.0-116",
3
+ "version": "5.0.0-118-alpha1",
4
4
  "description": "The Internet Archive BookReader.",
5
5
  "type": "module",
6
6
  "files": [
@@ -32,22 +32,23 @@
32
32
  "private": false,
33
33
  "dependencies": {
34
34
  "@internetarchive/bergamot-translator": "^0.4.9-ia.1",
35
- "@internetarchive/ia-activity-indicator": "1.0.0",
36
- "@internetarchive/ia-item-navigator": "2.2.3",
37
- "@internetarchive/icon-bookmark": "1.4.1",
38
- "@internetarchive/icon-close": "1.4.1",
39
- "@internetarchive/icon-dl": "1.4.1",
40
- "@internetarchive/icon-edit-pencil": "1.4.1",
41
- "@internetarchive/icon-ia-logo": "1.4.1",
42
- "@internetarchive/icon-magnify-minus": "1.4.1",
43
- "@internetarchive/icon-magnify-plus": "1.4.1",
44
- "@internetarchive/icon-search": "1.4.1",
45
- "@internetarchive/icon-share": "1.4.1",
46
- "@internetarchive/icon-toc": "1.4.1",
47
- "@internetarchive/icon-visual-adjustment": "1.4.1",
48
- "@internetarchive/modal-manager": "2.0.6",
49
- "@internetarchive/shared-resize-observer": "0.2.0",
50
- "interactjs": "^1.10.18",
35
+ "@internetarchive/ia-activity-indicator": "^1.0.0",
36
+ "@internetarchive/ia-item-navigator": "^2.2.3",
37
+ "@internetarchive/icon-bookmark": "^1.4.1",
38
+ "@internetarchive/icon-close": "^1.4.1",
39
+ "@internetarchive/icon-dl": "^1.4.1",
40
+ "@internetarchive/icon-edit-pencil": "^1.4.1",
41
+ "@internetarchive/icon-ellipses": "^1.4.1",
42
+ "@internetarchive/icon-ia-logo": "^1.4.1",
43
+ "@internetarchive/icon-magnify-minus": "^1.4.1",
44
+ "@internetarchive/icon-magnify-plus": "^1.4.1",
45
+ "@internetarchive/icon-search": "^1.4.1",
46
+ "@internetarchive/icon-share": "^1.4.1",
47
+ "@internetarchive/icon-toc": "^1.4.1",
48
+ "@internetarchive/icon-visual-adjustment": "^1.4.1",
49
+ "@internetarchive/modal-manager": "^2.0.6",
50
+ "@internetarchive/shared-resize-observer": "^0.2.0",
51
+ "interactjs": "1.10.18",
51
52
  "iso-language-codes": "2.0.0",
52
53
  "jquery": "3.6.1",
53
54
  "jquery-colorbox": "1.6.4",
@@ -67,27 +68,29 @@
67
68
  "@iiif/presentation-3": "2.2.3",
68
69
  "@open-wc/testing-helpers": "3.0.1",
69
70
  "@types/jest": "30.0.0",
70
- "@webcomponents/webcomponentsjs": "^2.6.0",
71
+ "@webcomponents/webcomponentsjs": "2.6.0",
71
72
  "babel-loader": "10.1.1",
72
- "concurrently": "10.0.3",
73
- "core-js": "3.49.0",
73
+ "concurrently": "10.0.5",
74
+ "core-js": "3.50.0",
74
75
  "cpx2": "9.0.0",
76
+ "css-loader": "7.1.4",
75
77
  "eslint": "7.32.0",
76
- "eslint-plugin-no-jquery": "^2.7.0",
78
+ "eslint-plugin-no-jquery": "2.7.0",
77
79
  "eslint-plugin-testcafe": "0.2.1",
78
80
  "http-server": "14.1.1",
79
- "hypothesis": "^1.1627.0",
81
+ "hypothesis": "1.1766.0",
80
82
  "jest": "30.4.2",
81
83
  "jest-environment-jsdom": "30.4.1",
82
84
  "live-server": "1.2.2",
83
85
  "regenerator-runtime": "0.14.1",
84
- "sass": "1.100.0",
85
- "sinon": "22.0.0",
86
- "svgo": "4.0.1",
87
- "testcafe": "3.7.4",
86
+ "sass": "1.103.1",
87
+ "sass-loader": "17.0.0",
88
+ "sinon": "22.1.0",
89
+ "svgo": "4.1.0",
90
+ "testcafe": "3.7.6",
88
91
  "testcafe-browser-provider-browserstack": "1.15.2",
89
- "webpack": "5.107.2",
90
- "webpack-cli": "7.0.3"
92
+ "webpack": "5.109.2",
93
+ "webpack-cli": "7.2.2"
91
94
  },
92
95
  "jest": {
93
96
  "testEnvironment": "jsdom",
@@ -95,7 +98,8 @@
95
98
  "node_modules/(?!(sinon|lit-html|lit-element|lit|@lit|@lit-labs|@internetarchive|@open-wc)/)"
96
99
  ],
97
100
  "moduleNameMapper": {
98
- "^@/(.*)$": "<rootDir>/$1"
101
+ "@/(.*)$": "<rootDir>/$1",
102
+ "\\.scss$": "<rootDir>/tests/jest/styleMock.js"
99
103
  },
100
104
  "setupFiles": [
101
105
  "./src/jquery-wrapper.js",
@@ -135,7 +139,7 @@
135
139
  "update:test-deps": "npm i @babel/eslint-parser@latest @open-wc/testing-helpers@latest @types/jest@latest eslint@7 eslint-plugin-no-jquery@latest eslint-plugin-testcafe@latest jest@latest jest-environment-jsdom@latest sinon@latest testcafe@latest",
136
140
  "update:test-deps:test": "npm run lint && npm run test && npm run test:e2e",
137
141
  "DOCS:update:build-deps": "These can cause strange changes, so do an npm run build + check file size (git diff --stat), and check the site is as expected",
138
- "update:build-deps": "npm i @babel/core@latest @babel/preset-env@latest @babel/plugin-proposal-class-properties@latest @babel/plugin-proposal-decorators@latest babel-loader@latest core-js@latest regenerator-runtime@latest sass@latest svgo@latest webpack@latest webpack-cli@latest",
142
+ "update:build-deps": "npm i @babel/core@latest @babel/preset-env@latest @babel/plugin-proposal-class-properties@latest @babel/plugin-proposal-decorators@latest babel-loader@latest core-js@latest css-loader@latest regenerator-runtime@latest sass@latest sass-loader@latest svgo@latest webpack@latest webpack-cli@latest",
139
143
  "update:build-deps:test": "npm run build",
140
144
  "DOCS:update:dev-deps": "Packages used for development",
141
145
  "update:dev-deps": "npm i @iiif/presentation-2@latest @iiif/presentation-3@latest concurrently@latest cpx2@latest http-server@latest hypothesis@latest live-server@latest testcafe-browser-provider-browserstack@latest",
@@ -143,6 +147,6 @@
143
147
  "update:runtime-deps": "npm i @webcomponents/webcomponentsjs@latest interactjs@latest iso-language-codes@latest jquery@latest jquery-colorbox@latest jquery-ui@latest jquery-ui-touch-punch@latest jquery.browser@latest lit@latest soundmanager2@latest",
144
148
  "update:runtime-deps:test": "npm run build",
145
149
  "DOCS:update:ia-deps": "Packages by @internetarchive",
146
- "update:ia-deps": "npm i @internetarchive/bergamot-translator@latest @internetarchive/ia-activity-indicator@latest @internetarchive/ia-item-navigator@latest @internetarchive/icon-bookmark@latest @internetarchive/icon-close@latest @internetarchive/icon-dl@latest @internetarchive/icon-edit-pencil@latest @internetarchive/icon-ia-logo@latest @internetarchive/icon-magnify-minus@latest @internetarchive/icon-magnify-plus@latest @internetarchive/icon-search@latest @internetarchive/icon-share@latest @internetarchive/icon-toc@latest @internetarchive/icon-visual-adjustment@latest @internetarchive/modal-manager@latest @internetarchive/shared-resize-observer@latest"
150
+ "update:ia-deps": "npm i @internetarchive/bergamot-translator@latest @internetarchive/ia-activity-indicator@latest @internetarchive/ia-item-navigator@latest @internetarchive/icon-bookmark@latest @internetarchive/icon-close@latest @internetarchive/icon-dl@latest @internetarchive/icon-edit-pencil@latest @internetarchive/icon-ellipses@latest @internetarchive/icon-ia-logo@latest @internetarchive/icon-magnify-minus@latest @internetarchive/icon-magnify-plus@latest @internetarchive/icon-search@latest @internetarchive/icon-share@latest @internetarchive/icon-toc@latest @internetarchive/icon-visual-adjustment@latest @internetarchive/modal-manager@latest @internetarchive/shared-resize-observer@latest"
147
151
  }
148
152
  }
package/src/BookReader.js CHANGED
@@ -26,6 +26,7 @@ import 'jquery-ui-touch-punch';
26
26
 
27
27
  import PACKAGE_JSON from '../package.json';
28
28
  import * as utils from './BookReader/utils.js';
29
+ import { singleScrollIntoView } from './util/dom.js';
29
30
  import { exposeOverrideable } from './BookReader/utils/classes.js';
30
31
  import { Navbar } from './BookReader/Navbar/Navbar.js';
31
32
  import { DEFAULT_OPTIONS, OptionsParseError } from './BookReader/options.js';
@@ -111,6 +112,8 @@ BookReader.PLUGINS = {
111
112
  chapters: null,
112
113
  /** @type {typeof import('./plugins/plugin.experiments.js').ExperimentsPlugin | null}*/
113
114
  experiments: null,
115
+ /** @type {typeof import('./plugins/plugin.iframe.js').IframePlugin | null}*/
116
+ iframe: null,
114
117
  /** @type {typeof import('./plugins/plugin.resume.js').ResumePlugin | null}*/
115
118
  resume: null,
116
119
  /** @type {typeof import('./plugins/search/plugin.search.js').SearchPlugin | null}*/
@@ -181,6 +184,7 @@ BookReader.prototype.setup = function(options) {
181
184
  autoplay: BookReader.PLUGINS.autoplay ? new BookReader.PLUGINS.autoplay(this) : null,
182
185
  chapters: BookReader.PLUGINS.chapters ? new BookReader.PLUGINS.chapters(this) : null,
183
186
  experiments: BookReader.PLUGINS.experiments ? new BookReader.PLUGINS.experiments(this) : null,
187
+ iframe: BookReader.PLUGINS.iframe ? new BookReader.PLUGINS.iframe(this) : null,
184
188
  search: BookReader.PLUGINS.search ? new BookReader.PLUGINS.search(this) : null,
185
189
  resume: BookReader.PLUGINS.resume ? new BookReader.PLUGINS.resume(this) : null,
186
190
  textSelection: BookReader.PLUGINS.textSelection ? new BookReader.PLUGINS.textSelection(this) : null,
@@ -1031,6 +1035,18 @@ BookReader.prototype.resizeBRcontainer = function(animate) {
1031
1035
  }
1032
1036
  };
1033
1037
 
1038
+ /**
1039
+ * Scrolls the given element into view within the active mode's scroll container.
1040
+ * @param {Element} el
1041
+ * @param {object} [options]
1042
+ * @param {'auto' | 'smooth'} [options.behavior]
1043
+ * @param {'start' | 'center' | 'end' | 'nearest'} [options.block]
1044
+ * @param {'start' | 'center' | 'end' | 'nearest'} [options.inline]
1045
+ */
1046
+ BookReader.prototype.scrollIntoView = function(el, options) {
1047
+ singleScrollIntoView(el, { ...options, scrollContainer: this.activeMode.scrollContainer });
1048
+ };
1049
+
1034
1050
  BookReader.prototype.centerPageView = function() {
1035
1051
  const scrollWidth = this.refs.$brContainer.prop('scrollWidth');
1036
1052
  const clientWidth = this.refs.$brContainer.prop('clientWidth');
@@ -145,16 +145,29 @@
145
145
  display: none;
146
146
  }
147
147
 
148
+
149
+ $select-menu-radius: 25px;
150
+ $select-menu-extended-radius: 10px;
148
151
  .br-select-menu__root {
149
152
  display: none;
150
- border-radius: 20px;
151
- background-color: #333;
152
153
  color: white;
153
154
  color-scheme: dark;
154
155
  padding: 2px;
155
156
  overflow: hidden;
156
157
  opacity: 1;
157
- transition: border-radius 0.2s, opacity 0.2s;
158
+ transition: opacity 0.2s;
159
+ gap: 5px;
160
+
161
+ &[open] {
162
+ display: flex;
163
+ }
164
+
165
+ &[showextended] {
166
+ display: block;
167
+ gap: 0px;
168
+ background-color: #333;
169
+ border-radius: $select-menu-extended-radius;
170
+ }
158
171
 
159
172
  @starting-style {
160
173
  opacity: 0;
@@ -164,13 +177,6 @@
164
177
  opacity: 0;
165
178
  pointer-events: none;
166
179
  }
167
- .br-select-menu__root:hover {
168
- border-radius: 8px;
169
- }
170
-
171
- .br-select-menu__root:hover .br-select-menu__option {
172
- border-radius: 6px;
173
- }
174
180
 
175
181
  .br-select-menu__option {
176
182
  --iconWidth: 15px;
@@ -179,18 +185,40 @@
179
185
  background: transparent;
180
186
  display: flex;
181
187
  align-items: center;
182
- border-radius: 20px;
188
+ border-radius: $select-menu-radius;
183
189
  font-family: inherit;
184
190
  color: inherit;
185
191
  border: 0;
186
- transition: background-color 0.2s, border-radius 0.2s;
187
192
  cursor: pointer;
188
193
  text-wrap: nowrap;
189
- padding: 4px;
190
- }
194
+ background-color: #333;
195
+ position: relative;
191
196
 
192
- .br-select-menu__option:hover {
193
- background-color: rgba(255, 255, 255, 0.1);
197
+ @media (pointer: coarse) and (hover: none) {
198
+ padding: 4px 8px;
199
+ #br-select-more & {
200
+ padding: 4px;
201
+ }
202
+ }
203
+
204
+ &:hover:after {
205
+ position: absolute;
206
+ left: 2px;
207
+ right: 2px;
208
+ top: 2px;
209
+ bottom: 2px;
210
+ content: "";
211
+ pointer-events: none;
212
+ background-color: rgba(255, 255, 255, 0.1);
213
+ border-radius: calc($select-menu-radius - 2px);
214
+ }
215
+
216
+ .br-select-menu__root[showextended] & {
217
+ width:100%;
218
+ &:hover:after {
219
+ border-radius: calc($select-menu-extended-radius - 2px);
220
+ }
221
+ }
194
222
  }
195
223
 
196
224
  .br-select-menu__icon {
@@ -198,24 +226,29 @@
198
226
  flex-shrink: 0;
199
227
  width: 17px;
200
228
  height: 17px;
229
+ padding: 2px;
201
230
  }
202
231
 
203
232
  .br-select-menu__label {
204
233
  margin-left: 4px;
205
234
  font-size: 12px;
235
+ margin-right: 4px;
206
236
  }
207
237
 
208
238
  @media (hover: hover) {
239
+ .br-select-menu__option {
240
+ padding: 4px;
241
+ }
209
242
  .br-select-menu__label {
210
243
  width: 0px;
211
- margin-left: 0;
244
+ margin: 0;
212
245
  opacity: 0;
213
246
  interpolate-size: allow-keywords;
214
247
  transition: width 0.2s;
215
248
  }
216
249
  .br-select-menu__root:hover .br-select-menu__label {
217
250
  width: auto;
218
- margin-left: 4px;
251
+ margin: 0 4px;
219
252
  opacity: 1;
220
253
  }
221
254
  }
@@ -7,6 +7,7 @@ import '@internetarchive/icon-toc/icon-toc.js';
7
7
  import { BookReaderPlugin } from "../BookReaderPlugin.js";
8
8
  import { applyVariables } from "../util/strings.js";
9
9
  import { promisifyEvent } from "../BookReader/utils.js";
10
+ import { singleScrollIntoView } from "../util/dom.js";
10
11
  /** @typedef {import('@/src/BookReader/BookModel.js').PageIndex} PageIndex */
11
12
  /** @typedef {import('@/src/BookReader/BookModel.js').PageString} PageString */
12
13
  /** @typedef {import('@/src/BookReader/BookModel.js').LeafNum} LeafNum */
@@ -323,10 +324,13 @@ export class BRChaptersPanel extends LitElement {
323
324
 
324
325
  updated(changedProperties) {
325
326
  if (changedProperties.has('currentChapter')) {
326
- this.shadowRoot.querySelector('li.current')?.scrollIntoView({
327
- block: 'nearest',
328
- behavior: 'smooth',
329
- });
327
+ const currentEl = this.shadowRoot.querySelector('li.current');
328
+ if (currentEl) {
329
+ singleScrollIntoView(currentEl, {
330
+ block: 'nearest',
331
+ behavior: 'smooth',
332
+ });
333
+ }
330
334
  }
331
335
  }
332
336
 
@@ -1,48 +1,47 @@
1
- /* global BookReader */
2
- /**
3
- * Plugin for two-way communication between a BookReader in an IFrame and the
4
- * parent web page
5
- */
1
+ // @ts-check
2
+ import { EVENTS } from '../BookReader/events.js';
3
+ import { BookReaderPlugin } from '../BookReaderPlugin.js';
6
4
 
7
5
  const MESSAGE_TYPE_FRAGMENT_CHANGE = 'bookReaderFragmentChange';
8
6
 
9
- BookReader.prototype.init = (function (super_) {
10
- return function () {
11
- super_.call(this);
12
- _attachEventListeners(this);
13
- };
14
- })(BookReader.prototype.init);
15
-
16
7
  /**
17
- * @private
18
- * Using window.postMessage() and event listeners, the plugin notifies the
19
- * parent window when pages change, and the parent window can also
20
- * explicitly request a page change by sending its own message.
21
- *
22
- * @param {BookReader} br
23
- * @param {Window?} [parent]
8
+ * Plugin for two-way communication between a BookReader in an IFrame and the
9
+ * parent web page. Using window.postMessage() and event listeners, the
10
+ * plugin notifies the parent window when pages change, and the parent
11
+ * window can also explicitly request a page change by sending its own
12
+ * message.
24
13
  */
25
- export function _attachEventListeners(br, parent = window.parent) {
26
- // Not embedded, abort
27
- if (!parent) {
28
- return;
14
+ export class IframePlugin extends BookReaderPlugin {
15
+ options = {
16
+ enabled: true,
29
17
  }
30
18
 
31
- br.bind(BookReader.eventNames.fragmentChange, () => {
32
- const fragment = br.fragmentFromParams(br.paramsFromCurrent());
33
-
34
- parent.postMessage(
35
- { type: MESSAGE_TYPE_FRAGMENT_CHANGE, fragment },
36
- '*',
37
- );
38
- });
39
-
40
- window.addEventListener('message', event => {
41
- // Not a recognized message type, abort
42
- if (!event.data || event.data.type !== MESSAGE_TYPE_FRAGMENT_CHANGE) {
19
+ /** @override */
20
+ init() {
21
+ // Not enabled, or not embedded, abort
22
+ if (!this.options.enabled || !window.parent) {
43
23
  return;
44
24
  }
45
25
 
46
- br.updateFromParams(br.paramsFromFragment(event.data.fragment));
47
- });
26
+ this.br.bind(EVENTS.fragmentChange, () => {
27
+ const fragment = this.br.fragmentFromParams(this.br.paramsFromCurrent());
28
+
29
+ window.parent.postMessage(
30
+ { type: MESSAGE_TYPE_FRAGMENT_CHANGE, fragment },
31
+ '*',
32
+ );
33
+ });
34
+
35
+ window.addEventListener('message', event => {
36
+ // Not a recognized message type, abort
37
+ if (!event.data || event.data.type !== MESSAGE_TYPE_FRAGMENT_CHANGE) {
38
+ return;
39
+ }
40
+
41
+ this.br.updateFromParams(this.br.paramsFromFragment(event.data.fragment));
42
+ });
43
+ }
48
44
  }
45
+
46
+ const BookReader = /** @type {typeof import('../BookReader').default} */(window.BookReader);
47
+ BookReader?.registerPlugin('iframe', IframePlugin);
@@ -6,6 +6,7 @@ import { Cache } from '../util/cache.js';
6
6
  import { toISO6391 } from './tts/utils.js';
7
7
  import { BookReaderTextFragment, renderHighlight, TextSelectionManager } from '../util/TextSelectionManager.js';
8
8
  import { genMap, lookAroundWindow, zip } from '../util/generators.js';
9
+ import textSelectionCss from '../css/_TextSelection.scss';
9
10
  /** @typedef {import('../util/strings.js').StringWithVars} StringWithVars */
10
11
  /** @typedef {import('../BookReader/PageContainer.js').PageContainer} PageContainer */
11
12
 
@@ -39,6 +40,13 @@ export class TextSelectionPlugin extends BookReaderPlugin {
39
40
 
40
41
  _jumpedToHighlight = false;
41
42
 
43
+ /**
44
+ * Isolated document/layout used to performantly measure OCR text-layer
45
+ * elements.
46
+ * @type {Document}
47
+ */
48
+ _measurementDocument;
49
+
42
50
  /**
43
51
  * @param {import('../BookReader.js').default} br
44
52
  */
@@ -56,6 +64,19 @@ export class TextSelectionPlugin extends BookReaderPlugin {
56
64
  init() {
57
65
  if (!this.options.enabled) return;
58
66
 
67
+ // Setup measurement iframe for OCR
68
+ const measurementIframe = document.createElement('iframe');
69
+ measurementIframe.setAttribute('aria-hidden', 'true');
70
+ measurementIframe.tabIndex = -1;
71
+ measurementIframe.style.cssText = 'position:fixed; top:-99999px; left:-99999px; width:2000px; height:4000px; border:0; visibility:hidden;';
72
+ document.body.appendChild(measurementIframe);
73
+ this._measurementDocument = measurementIframe.contentDocument;
74
+ // Injects _TextSelection.scss so measurements match the real
75
+ // rendering
76
+ const style = this._measurementDocument.createElement('style');
77
+ style.textContent = textSelectionCss;
78
+ this._measurementDocument.head.appendChild(style);
79
+
59
80
  this.br.on('pageVisible', (_, {pageContainerEl}) => {
60
81
  const textLayer = pageContainerEl.querySelector('.BRtextLayer');
61
82
  if (textLayer) {
@@ -78,7 +99,7 @@ export class TextSelectionPlugin extends BookReaderPlugin {
78
99
  const markEls = renderHighlight(textLayer, targetTextFragment, 'BRhighlight--target-text');
79
100
  // Only jump once; presumably on first page load.
80
101
  if (!this._jumpedToHighlight) {
81
- markEls[0].scrollIntoView({behavior: 'smooth', block: 'center'});
102
+ this.br.scrollIntoView(markEls[0], {behavior: 'smooth', block: 'center'});
82
103
  this._jumpedToHighlight = true;
83
104
  }
84
105
  }
@@ -94,7 +115,7 @@ export class TextSelectionPlugin extends BookReaderPlugin {
94
115
  _configurePageContainer(pageContainer) {
95
116
  // Disable if thumb mode; it's too janky
96
117
  // .page can be null for "pre-cover" region
97
- if (this.br.mode !== this.br.constModeThumb && pageContainer.page?.isViewable) {
118
+ if (this.options.enabled && this.br.mode !== this.br.constModeThumb && pageContainer.page?.isViewable) {
98
119
  this.createTextLayer(pageContainer);
99
120
  }
100
121
  return pageContainer;
@@ -204,7 +225,7 @@ export class TextSelectionPlugin extends BookReaderPlugin {
204
225
  });
205
226
 
206
227
  // Fix up paragraph positions
207
- const paragraphRects = determineRealRects(textLayer, '.BRparagraphElement');
228
+ const paragraphRects = determineRealRects(textLayer, '.BRparagraphElement', this._measurementDocument);
208
229
  let yAdded = 0;
209
230
  for (const [ocrParagraph, paragEl] of zip(ocrParagraphs, paragEls)) {
210
231
  const ocrParagBounds = $(ocrParagraph).attr("coords").split(",").map(parseFloat);
@@ -312,7 +333,7 @@ export class TextSelectionPlugin extends BookReaderPlugin {
312
333
  paragEl.style.fontSize = `${paragWordHeight}px`;
313
334
 
314
335
  // Fix up sizes - stretch/crush words as necessary using letter spacing
315
- let wordRects = determineRealRects(paragEl, '.BRwordElement');
336
+ let wordRects = determineRealRects(paragEl, '.BRwordElement', this._measurementDocument);
316
337
  const ocrWords = $(ocrParagraph).find("WORD").toArray();
317
338
  const wordEls = paragEl.querySelectorAll('.BRwordElement');
318
339
  for (const [ocrWord, wordEl] of zip(ocrWords, wordEls)) {
@@ -333,8 +354,8 @@ export class TextSelectionPlugin extends BookReaderPlugin {
333
354
 
334
355
  // Stretch/crush lines as necessary using line spacing
335
356
  // Recompute rects after letter spacing
336
- wordRects = determineRealRects(paragEl, '.BRwordElement');
337
- const spaceRects = determineRealRects(paragEl, '.BRspace');
357
+ wordRects = determineRealRects(paragEl, '.BRwordElement', this._measurementDocument);
358
+ const spaceRects = determineRealRects(paragEl, '.BRspace', this._measurementDocument);
338
359
 
339
360
  const ocrLines = $(ocrParagraph).find("LINE[coords]").toArray();
340
361
  const lineEls = Array.from(paragEl.querySelectorAll('.BRlineElement'));
@@ -384,9 +405,11 @@ BookReader?.registerPlugin('textSelection', TextSelectionPlugin);
384
405
  /**
385
406
  * @param {HTMLElement} parentEl
386
407
  * @param {string} selector
408
+ * @param {Document} measurementDocument Isolated document to measure within
409
+ * (see TextSelectionPlugin#_measurementDocument for why).
387
410
  * @returns {Map<Element, Rect>}
388
411
  */
389
- function determineRealRects(parentEl, selector) {
412
+ function determineRealRects(parentEl, selector, measurementDocument) {
390
413
  const initals = {
391
414
  position: parentEl.style.position,
392
415
  visibility: parentEl.style.visibility,
@@ -399,21 +422,23 @@ function determineRealRects(parentEl, selector) {
399
422
  parentEl.style.top = '0';
400
423
  parentEl.style.left = '0';
401
424
  parentEl.style.transform = 'none';
402
- document.body.appendChild(parentEl);
425
+ measurementDocument.body.appendChild(parentEl);
403
426
  const rects = new Map(
404
427
  Array.from(parentEl.querySelectorAll(selector))
405
428
  .map(wordEl => {
406
429
  const origRect = wordEl.getBoundingClientRect();
407
430
  return [wordEl, new Rect(
408
- origRect.left + window.scrollX,
409
- origRect.top + window.scrollY,
431
+ origRect.left + measurementDocument.defaultView.scrollX,
432
+ origRect.top + measurementDocument.defaultView.scrollY,
410
433
  origRect.width,
411
434
  origRect.height,
412
435
  )];
413
436
  }),
414
437
  );
415
- document.body.removeChild(parentEl);
438
+ measurementDocument.body.removeChild(parentEl);
416
439
  Object.assign(parentEl.style, initals);
440
+ // Need to restore the document to the main window document
441
+ document.adoptNode(parentEl);
417
442
  return rects;
418
443
  }
419
444
 
@@ -383,14 +383,8 @@ export class SearchPlugin extends BookReaderPlugin {
383
383
  const $boxes = await poll(() => $(`rect.match-index-${match.matchIndex}`), { until: result => result.length > 0 });
384
384
  if ($boxes.length) {
385
385
  $boxes.css('animation', 'none');
386
- $boxes[0].scrollIntoView({
387
- // Only vertically center the highlight if we're in 1up or in full screen. In
388
- // 2up, if we're not fullscreen, the whole body gets scrolled around to try to
389
- // center the highlight 🙄 See:
390
- // https://stackoverflow.com/questions/11039885/scrollintoview-causing-the-whole-page-to-move/11041376
391
- // Note: nearest doesn't quite work great, because the ReadAloud toolbar is now
392
- // full-width, and covers up the last line of the highlight.
393
- block: this.br.constMode1up == this.br.mode || this.br.isFullscreenActive ? 'center' : 'nearest',
386
+ this.br.scrollIntoView($boxes[0], {
387
+ block: 'center',
394
388
  inline: 'center',
395
389
  behavior: onNearbyPage ? 'smooth' : 'auto',
396
390
  });
@@ -5,6 +5,7 @@ import WebTTSEngine from './WebTTSEngine.js';
5
5
  import { toISO6391 } from './utils.js';
6
6
  import { en as tooltips } from './tooltip_dict.js';
7
7
  import { renderBoxesInPageContainerLayer } from '../../BookReader/PageContainer.js';
8
+ import { throttle } from '../../BookReader/utils.js';
8
9
  import { BookReaderPlugin } from '../../BookReaderPlugin.js';
9
10
  import { applyVariables, countWords } from '../../util/strings.js';
10
11
  /** @typedef {import('./PageChunk.js').default} PageChunk */
@@ -72,6 +73,10 @@ export class TtsPlugin extends BookReaderPlugin {
72
73
  festivalUrl: applyVariables(this.options.remoteTtsUrl, this.br.options.vars),
73
74
  } : {}),
74
75
  });
76
+
77
+ // Resuming picks up inside the current chunk, so it would otherwise wait for the
78
+ // next one to register as activity.
79
+ this.ttsEngine.events.on('resume', this.signalUserIsActive);
75
80
  }
76
81
  }
77
82
 
@@ -277,11 +282,30 @@ export class TtsPlugin extends BookReaderPlugin {
277
282
  this.br.removeProgressPopup();
278
283
  }
279
284
 
285
+ /**
286
+ * Tell the lending code the patron is still here.
287
+ *
288
+ * `userAction` is how ia-book-actions decides a browse loan is still in use, but it
289
+ * is otherwise only triggered by an index change (see BookReader.prototype
290
+ * .updateFirstIndex) or a navbar click. Read aloud holds someone's attention without
291
+ * either: in 2up the engine reads both pages before it flips, so a spread can easily
292
+ * outlast the window the loan renewal allows, and a listener would have their loan
293
+ * auto-returned mid-playback. Driving the signal off chunk playback instead ties it
294
+ * to actual progress through the book.
295
+ *
296
+ * Throttled because chunks are paragraphs -- short ones would otherwise signal every
297
+ * few seconds, and the renewal only cares about minutes.
298
+ */
299
+ signalUserIsActive = throttle(() => {
300
+ this.br.trigger(BookReader.eventNames.userAction);
301
+ }, 60000, false);
302
+
280
303
  /**
281
304
  * @param {PageChunk} chunk
282
305
  * Returns once the flip is done
283
306
  */
284
307
  async beforeChunkPlay(chunk) {
308
+ this.signalUserIsActive();
285
309
  await this.maybeFlipToIndex(chunk.leafIndex);
286
310
  this.highlightChunk(chunk);
287
311
  this.scrollToChunk(chunk);
@@ -350,14 +374,9 @@ export class TtsPlugin extends BookReaderPlugin {
350
374
  // It behaves weird if used in thumb mode
351
375
  if (this.br.constModeThumb == this.br.mode) return;
352
376
 
353
- $(`.pagediv${chunk.leafIndex} .ttsHiliteLayer rect`).last()?.[0]?.scrollIntoView({
354
- // Only vertically center the highlight if we're in 1up or in full screen. In
355
- // 2up, if we're not fullscreen, the whole body gets scrolled around to try to
356
- // center the highlight 🙄 See:
357
- // https://stackoverflow.com/questions/11039885/scrollintoview-causing-the-whole-page-to-move/11041376
358
- // Note: nearest doesn't quite work great, because the ReadAloud toolbar is now
359
- // full-width, and covers up the last line of the highlight.
360
- block: this.br.constMode1up == this.br.mode || this.br.isFullscreenActive ? 'center' : 'nearest',
377
+ const highlightRect = $(`.pagediv${chunk.leafIndex} .ttsHiliteLayer rect`).last()?.[0];
378
+ this.br.scrollIntoView(highlightRect, {
379
+ block: 'center',
361
380
  inline: 'center',
362
381
  behavior: 'smooth',
363
382
  });