@internetarchive/bookreader 5.0.0-95 → 5.0.0-97

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 (330) hide show
  1. package/BookReader/474.js +2 -0
  2. package/BookReader/474.js.map +1 -0
  3. package/BookReader/BookReader.css +2257 -0
  4. package/BookReader/BookReader.js +3 -0
  5. package/BookReader/BookReader.js.LICENSE.txt +72 -0
  6. package/BookReader/BookReader.js.map +1 -0
  7. package/BookReader/bergamot-translator-worker.js +2966 -0
  8. package/BookReader/bergamot-translator-worker.wasm +0 -0
  9. package/BookReader/hypothesis/LICENSE +50 -0
  10. package/BookReader/hypothesis/README.md +55 -0
  11. package/BookReader/hypothesis/build/boot.js +1 -0
  12. package/BookReader/hypothesis/build/manifest.json +20 -0
  13. package/BookReader/hypothesis/build/scripts/annotator.bundle.js +184 -0
  14. package/BookReader/hypothesis/build/scripts/annotator.bundle.js.map +1 -0
  15. package/BookReader/hypothesis/build/scripts/sidebar.bundle.js +798 -0
  16. package/BookReader/hypothesis/build/scripts/sidebar.bundle.js.map +1 -0
  17. package/BookReader/hypothesis/build/scripts/ui-playground.bundle.js +711 -0
  18. package/BookReader/hypothesis/build/scripts/ui-playground.bundle.js.map +1 -0
  19. package/BookReader/hypothesis/build/styles/annotator.css +2235 -0
  20. package/BookReader/hypothesis/build/styles/annotator.css.map +1 -0
  21. package/BookReader/hypothesis/build/styles/fonts/KaTeX_AMS-Regular.woff2 +0 -0
  22. package/BookReader/hypothesis/build/styles/fonts/KaTeX_Caligraphic-Bold.woff2 +0 -0
  23. package/BookReader/hypothesis/build/styles/fonts/KaTeX_Caligraphic-Regular.woff2 +0 -0
  24. package/BookReader/hypothesis/build/styles/fonts/KaTeX_Fraktur-Bold.woff2 +0 -0
  25. package/BookReader/hypothesis/build/styles/fonts/KaTeX_Fraktur-Regular.woff2 +0 -0
  26. package/BookReader/hypothesis/build/styles/fonts/KaTeX_Main-Bold.woff2 +0 -0
  27. package/BookReader/hypothesis/build/styles/fonts/KaTeX_Main-BoldItalic.woff2 +0 -0
  28. package/BookReader/hypothesis/build/styles/fonts/KaTeX_Main-Italic.woff2 +0 -0
  29. package/BookReader/hypothesis/build/styles/fonts/KaTeX_Main-Regular.woff2 +0 -0
  30. package/BookReader/hypothesis/build/styles/fonts/KaTeX_Math-BoldItalic.woff2 +0 -0
  31. package/BookReader/hypothesis/build/styles/fonts/KaTeX_Math-Italic.woff2 +0 -0
  32. package/BookReader/hypothesis/build/styles/fonts/KaTeX_SansSerif-Bold.woff2 +0 -0
  33. package/BookReader/hypothesis/build/styles/fonts/KaTeX_SansSerif-Italic.woff2 +0 -0
  34. package/BookReader/hypothesis/build/styles/fonts/KaTeX_SansSerif-Regular.woff2 +0 -0
  35. package/BookReader/hypothesis/build/styles/fonts/KaTeX_Script-Regular.woff2 +0 -0
  36. package/BookReader/hypothesis/build/styles/fonts/KaTeX_Size1-Regular.woff2 +0 -0
  37. package/BookReader/hypothesis/build/styles/fonts/KaTeX_Size2-Regular.woff2 +0 -0
  38. package/BookReader/hypothesis/build/styles/fonts/KaTeX_Size3-Regular.woff2 +0 -0
  39. package/BookReader/hypothesis/build/styles/fonts/KaTeX_Size4-Regular.woff2 +0 -0
  40. package/BookReader/hypothesis/build/styles/fonts/KaTeX_Typewriter-Regular.woff2 +0 -0
  41. package/BookReader/hypothesis/build/styles/highlights.css +2 -0
  42. package/BookReader/hypothesis/build/styles/highlights.css.map +1 -0
  43. package/BookReader/hypothesis/build/styles/katex.min.css +2 -0
  44. package/BookReader/hypothesis/build/styles/katex.min.css.map +1 -0
  45. package/BookReader/hypothesis/build/styles/pdfjs-overrides.css +2 -0
  46. package/BookReader/hypothesis/build/styles/pdfjs-overrides.css.map +1 -0
  47. package/BookReader/hypothesis/build/styles/sidebar.css +2731 -0
  48. package/BookReader/hypothesis/build/styles/sidebar.css.map +1 -0
  49. package/BookReader/hypothesis/build/styles/ui-playground.css +2659 -0
  50. package/BookReader/hypothesis/build/styles/ui-playground.css.map +1 -0
  51. package/BookReader/hypothesis/package.json +126 -0
  52. package/BookReader/ia-bookreader-bundle.js +1782 -0
  53. package/BookReader/ia-bookreader-bundle.js.LICENSE.txt +7 -0
  54. package/BookReader/ia-bookreader-bundle.js.map +1 -0
  55. package/BookReader/icons/1up.svg +1 -0
  56. package/BookReader/icons/2up.svg +1 -0
  57. package/BookReader/icons/advance.svg +3 -0
  58. package/BookReader/icons/chevron-right.svg +1 -0
  59. package/BookReader/icons/close-circle-dark.svg +1 -0
  60. package/BookReader/icons/close-circle.svg +1 -0
  61. package/BookReader/icons/fullscreen.svg +1 -0
  62. package/BookReader/icons/fullscreen_exit.svg +1 -0
  63. package/BookReader/icons/hamburger.svg +1 -0
  64. package/BookReader/icons/left-arrow.svg +1 -0
  65. package/BookReader/icons/magnify-minus.svg +1 -0
  66. package/BookReader/icons/magnify-plus.svg +1 -0
  67. package/BookReader/icons/magnify.svg +1 -0
  68. package/BookReader/icons/pause.svg +1 -0
  69. package/BookReader/icons/play.svg +1 -0
  70. package/BookReader/icons/playback-speed.svg +1 -0
  71. package/BookReader/icons/read-aloud.svg +1 -0
  72. package/BookReader/icons/review.svg +3 -0
  73. package/BookReader/icons/thumbnails.svg +1 -0
  74. package/BookReader/icons/voice.svg +1 -0
  75. package/BookReader/icons/volume-full.svg +1 -0
  76. package/BookReader/images/BRicons.png +0 -0
  77. package/BookReader/images/BRicons.svg +5 -0
  78. package/BookReader/images/BRicons_ia.png +0 -0
  79. package/BookReader/images/back_pages.png +0 -0
  80. package/BookReader/images/book_bottom_icon.png +0 -0
  81. package/BookReader/images/book_down_icon.png +0 -0
  82. package/BookReader/images/book_left_icon.png +0 -0
  83. package/BookReader/images/book_leftmost_icon.png +0 -0
  84. package/BookReader/images/book_right_icon.png +0 -0
  85. package/BookReader/images/book_rightmost_icon.png +0 -0
  86. package/BookReader/images/book_top_icon.png +0 -0
  87. package/BookReader/images/book_up_icon.png +0 -0
  88. package/BookReader/images/books_graphic.svg +1 -0
  89. package/BookReader/images/booksplit.png +0 -0
  90. package/BookReader/images/control_pause_icon.png +0 -0
  91. package/BookReader/images/control_play_icon.png +0 -0
  92. package/BookReader/images/embed_icon.png +0 -0
  93. package/BookReader/images/hypothesis.ico +0 -0
  94. package/BookReader/images/icon-home-ia.png +0 -0
  95. package/BookReader/images/icon_OL-logo-xs.png +0 -0
  96. package/BookReader/images/icon_alert-xs.png +0 -0
  97. package/BookReader/images/icon_book.svg +1 -0
  98. package/BookReader/images/icon_bookmark.svg +1 -0
  99. package/BookReader/images/icon_close-pop.png +0 -0
  100. package/BookReader/images/icon_download.png +0 -0
  101. package/BookReader/images/icon_experiment.svg +1 -0
  102. package/BookReader/images/icon_gear.svg +1 -0
  103. package/BookReader/images/icon_hamburger.svg +1 -0
  104. package/BookReader/images/icon_home.png +0 -0
  105. package/BookReader/images/icon_home.svg +1 -0
  106. package/BookReader/images/icon_home_ia.png +0 -0
  107. package/BookReader/images/icon_indicator.png +0 -0
  108. package/BookReader/images/icon_info.svg +1 -0
  109. package/BookReader/images/icon_one_page.svg +1 -0
  110. package/BookReader/images/icon_pause.svg +1 -0
  111. package/BookReader/images/icon_play.svg +1 -0
  112. package/BookReader/images/icon_playback-rate.svg +1 -0
  113. package/BookReader/images/icon_return.png +0 -0
  114. package/BookReader/images/icon_search_button.svg +1 -0
  115. package/BookReader/images/icon_share.svg +1 -0
  116. package/BookReader/images/icon_skip-ahead.svg +1 -0
  117. package/BookReader/images/icon_skip-back.svg +2 -0
  118. package/BookReader/images/icon_speaker.svg +1 -0
  119. package/BookReader/images/icon_speaker_open.svg +1 -0
  120. package/BookReader/images/icon_thumbnails.svg +1 -0
  121. package/BookReader/images/icon_toc.svg +1 -0
  122. package/BookReader/images/icon_two_pages.svg +1 -0
  123. package/BookReader/images/icon_zoomer.png +0 -0
  124. package/BookReader/images/loading.gif +0 -0
  125. package/BookReader/images/logo_icon.png +0 -0
  126. package/BookReader/images/marker_chap-off.png +0 -0
  127. package/BookReader/images/marker_chap-off.svg +1 -0
  128. package/BookReader/images/marker_chap-off_ia.png +0 -0
  129. package/BookReader/images/marker_chap-on.png +0 -0
  130. package/BookReader/images/marker_chap-on.svg +1 -0
  131. package/BookReader/images/marker_srch-on.svg +1 -0
  132. package/BookReader/images/marker_srchchap-off.png +0 -0
  133. package/BookReader/images/marker_srchchap-on.png +0 -0
  134. package/BookReader/images/nav_control-dn.png +0 -0
  135. package/BookReader/images/nav_control-dn_ia.png +0 -0
  136. package/BookReader/images/nav_control-up.png +0 -0
  137. package/BookReader/images/nav_control-up_ia.png +0 -0
  138. package/BookReader/images/nav_control.png +0 -0
  139. package/BookReader/images/one_page_mode_icon.png +0 -0
  140. package/BookReader/images/paper-badge.png +0 -0
  141. package/BookReader/images/print_icon.png +0 -0
  142. package/BookReader/images/progressbar.gif +0 -0
  143. package/BookReader/images/right_edges.png +0 -0
  144. package/BookReader/images/slider.png +0 -0
  145. package/BookReader/images/slider_ia.png +0 -0
  146. package/BookReader/images/thumbnail_mode_icon.png +0 -0
  147. package/BookReader/images/translate.svg +1 -0
  148. package/BookReader/images/transparent.png +0 -0
  149. package/BookReader/images/two_page_mode_icon.png +0 -0
  150. package/BookReader/images/unviewable_page.png +0 -0
  151. package/BookReader/images/zoom_in_icon.png +0 -0
  152. package/BookReader/images/zoom_out_icon.png +0 -0
  153. package/BookReader/jquery-3.js +2 -0
  154. package/BookReader/jquery-3.js.LICENSE.txt +24 -0
  155. package/BookReader/plugins/plugin.archive_analytics.js +2 -0
  156. package/BookReader/plugins/plugin.archive_analytics.js.map +1 -0
  157. package/BookReader/plugins/plugin.autoplay.js +2 -0
  158. package/BookReader/plugins/plugin.autoplay.js.map +1 -0
  159. package/BookReader/plugins/plugin.chapters.js +26 -0
  160. package/BookReader/plugins/plugin.chapters.js.LICENSE.txt +1 -0
  161. package/BookReader/plugins/plugin.chapters.js.map +1 -0
  162. package/BookReader/plugins/plugin.experiments.js +3 -0
  163. package/BookReader/plugins/plugin.experiments.js.LICENSE.txt +1 -0
  164. package/BookReader/plugins/plugin.experiments.js.map +1 -0
  165. package/BookReader/plugins/plugin.iframe.js +2 -0
  166. package/BookReader/plugins/plugin.iframe.js.map +1 -0
  167. package/BookReader/plugins/plugin.iiif.js +2 -0
  168. package/BookReader/plugins/plugin.iiif.js.map +1 -0
  169. package/BookReader/plugins/plugin.resume.js +2 -0
  170. package/BookReader/plugins/plugin.resume.js.map +1 -0
  171. package/BookReader/plugins/plugin.search.js +3 -0
  172. package/BookReader/plugins/plugin.search.js.LICENSE.txt +1 -0
  173. package/BookReader/plugins/plugin.search.js.map +1 -0
  174. package/BookReader/plugins/plugin.text_selection.js +3 -0
  175. package/BookReader/plugins/plugin.text_selection.js.LICENSE.txt +1 -0
  176. package/BookReader/plugins/plugin.text_selection.js.map +1 -0
  177. package/BookReader/plugins/plugin.translate.js +3 -0
  178. package/BookReader/plugins/plugin.translate.js.LICENSE.txt +1 -0
  179. package/BookReader/plugins/plugin.translate.js.map +1 -0
  180. package/BookReader/plugins/plugin.tts.js +3 -0
  181. package/BookReader/plugins/plugin.tts.js.LICENSE.txt +29 -0
  182. package/BookReader/plugins/plugin.tts.js.map +1 -0
  183. package/BookReader/plugins/plugin.url.js +2 -0
  184. package/BookReader/plugins/plugin.url.js.map +1 -0
  185. package/BookReader/plugins/plugin.vendor-fullscreen.js +2 -0
  186. package/BookReader/plugins/plugin.vendor-fullscreen.js.map +1 -0
  187. package/BookReader/plugins/translator-worker.js +2 -0
  188. package/BookReader/plugins/translator-worker.js.map +1 -0
  189. package/BookReader/translator-worker.js +475 -0
  190. package/BookReader/webcomponents-bundle.js +3 -0
  191. package/BookReader/webcomponents-bundle.js.LICENSE.txt +9 -0
  192. package/BookReader/webcomponents-bundle.js.map +1 -0
  193. package/package.json +11 -3
  194. package/src/BookNavigator/book-navigator.js +1 -0
  195. package/src/BookReader/BookModel.js +564 -0
  196. package/src/BookReader/DragScrollable.js +233 -0
  197. package/src/BookReader/ImageCache.js +149 -0
  198. package/src/BookReader/Mode1Up.js +110 -0
  199. package/src/BookReader/Mode1UpLit.js +393 -0
  200. package/src/BookReader/Mode2Up.js +107 -0
  201. package/src/BookReader/Mode2UpLit.js +787 -0
  202. package/src/BookReader/ModeCoordinateSpace.js +29 -0
  203. package/src/BookReader/ModeSmoothZoom.js +312 -0
  204. package/src/BookReader/ModeThumb.js +344 -0
  205. package/src/BookReader/Navbar/Navbar.js +416 -0
  206. package/src/BookReader/PageContainer.js +172 -0
  207. package/src/BookReader/ReduceSet.js +26 -0
  208. package/src/BookReader/Toolbar/Toolbar.js +362 -0
  209. package/src/BookReader/events.js +19 -0
  210. package/src/BookReader/options.js +387 -0
  211. package/src/BookReader/utils/HTMLDimensionsCacher.js +44 -0
  212. package/src/BookReader/utils/ScrollClassAdder.js +31 -0
  213. package/src/BookReader/utils/SelectionObserver.js +45 -0
  214. package/src/BookReader/utils/classes.js +36 -0
  215. package/src/BookReader/utils.js +313 -0
  216. package/src/BookReader.js +22 -139
  217. package/src/assets/images/icon_experiment.svg +1 -0
  218. package/src/assets/images/translate.svg +1 -0
  219. package/src/css/_BRnav.scss +0 -24
  220. package/src/css/_BRsearch.scss +0 -5
  221. package/src/css/_TextSelection.scss +32 -1
  222. package/src/plugins/plugin.experiments.js +34 -9
  223. package/src/plugins/plugin.text_selection.js +8 -20
  224. package/src/plugins/translate/TranslationManager.js +167 -0
  225. package/src/plugins/translate/plugin.translate.js +414 -0
  226. package/src/plugins/tts/utils.js +9 -20
  227. package/src/util/cache.js +20 -0
  228. package/.eslintrc.cjs +0 -51
  229. package/.gitattributes +0 -2
  230. package/.github/ISSUE_TEMPLATE/bug.md +0 -32
  231. package/.github/ISSUE_TEMPLATE/feature-request.md +0 -30
  232. package/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md +0 -15
  233. package/.github/workflows/node.js.yml +0 -102
  234. package/.github/workflows/npm-publish.yml +0 -23
  235. package/.testcaferc.cjs +0 -10
  236. package/BookReaderDemo/BookReaderDemo.css +0 -40
  237. package/BookReaderDemo/BookReaderJSAdvanced.js +0 -112
  238. package/BookReaderDemo/BookReaderJSSimple.js +0 -56
  239. package/BookReaderDemo/IADemoBr.js +0 -149
  240. package/BookReaderDemo/assets/v5/Bookreader-logo-cool-grad.svg +0 -1
  241. package/BookReaderDemo/assets/v5/Bookreader-logo-flat.svg +0 -1
  242. package/BookReaderDemo/assets/v5/Bookreader-logo-hex-cool-grad.png +0 -0
  243. package/BookReaderDemo/assets/v5/Bookreader-logo-hex-flat.png +0 -0
  244. package/BookReaderDemo/assets/v5/Bookreader-logo-lines.png +0 -0
  245. package/BookReaderDemo/assets/v5/Bookreader-logo-lines.svg +0 -1
  246. package/BookReaderDemo/assets/v5/Bookreader-logo-warm.svg +0 -1
  247. package/BookReaderDemo/assets/v5/bookreader-logo-renders@1x.png +0 -0
  248. package/BookReaderDemo/assets/v5/bookreader-logo-renders@2x.png +0 -0
  249. package/BookReaderDemo/assets/v5/bookreader-v5-screenshot.png +0 -0
  250. package/BookReaderDemo/demo-advanced.html +0 -33
  251. package/BookReaderDemo/demo-embed-iframe-src.html +0 -85
  252. package/BookReaderDemo/demo-embed.html +0 -26
  253. package/BookReaderDemo/demo-fullscreen-mobile.html +0 -34
  254. package/BookReaderDemo/demo-fullscreen.html +0 -31
  255. package/BookReaderDemo/demo-iiif.html +0 -121
  256. package/BookReaderDemo/demo-internetarchive.html +0 -271
  257. package/BookReaderDemo/demo-multiple.html +0 -44
  258. package/BookReaderDemo/demo-preview-pages.html +0 -1093
  259. package/BookReaderDemo/demo-simple.html +0 -35
  260. package/BookReaderDemo/demo-vendor-fullscreen.html +0 -34
  261. package/BookReaderDemo/ia-multiple-volumes-manifest.js +0 -169
  262. package/BookReaderDemo/immersion-1up.html +0 -64
  263. package/BookReaderDemo/immersion-mode.html +0 -33
  264. package/BookReaderDemo/toggle_controls.html +0 -54
  265. package/BookReaderDemo/view_mode.html +0 -40
  266. package/BookReaderDemo/viewmode-cycle.html +0 -40
  267. package/CHANGELOG.md +0 -1087
  268. package/CONTRIBUTING.md +0 -7
  269. package/babel.config.cjs +0 -20
  270. package/codecov.yml +0 -23
  271. package/index.html +0 -34
  272. package/netlify.toml +0 -9
  273. package/renovate.json +0 -52
  274. package/screenshot.png +0 -0
  275. package/scripts/postversion.js +0 -11
  276. package/scripts/preversion.js +0 -15
  277. package/scripts/version.js +0 -24
  278. package/tests/e2e/README.md +0 -112
  279. package/tests/e2e/autoplay.test.js +0 -16
  280. package/tests/e2e/base.test.js +0 -27
  281. package/tests/e2e/helpers/base.js +0 -263
  282. package/tests/e2e/helpers/debug.js +0 -13
  283. package/tests/e2e/helpers/mockSearch.js +0 -90
  284. package/tests/e2e/helpers/params.js +0 -17
  285. package/tests/e2e/helpers/rightToLeft.js +0 -23
  286. package/tests/e2e/helpers/search.js +0 -73
  287. package/tests/e2e/models/BookReader.js +0 -11
  288. package/tests/e2e/models/Navigation.js +0 -39
  289. package/tests/e2e/rightToLeft.test.js +0 -19
  290. package/tests/e2e/viewmode.test.js +0 -44
  291. package/tests/jest/BookNavigator/book-navigator.test.js +0 -653
  292. package/tests/jest/BookNavigator/bookmarks/bookmark-button.test.js +0 -43
  293. package/tests/jest/BookNavigator/bookmarks/bookmark-edit.test.js +0 -132
  294. package/tests/jest/BookNavigator/bookmarks/bookmarks-list.test.js +0 -221
  295. package/tests/jest/BookNavigator/bookmarks/ia-bookmarks.test.js +0 -45
  296. package/tests/jest/BookNavigator/downloads/downloads-provider.test.js +0 -67
  297. package/tests/jest/BookNavigator/downloads/downloads.test.js +0 -53
  298. package/tests/jest/BookNavigator/search/search-provider.test.js +0 -179
  299. package/tests/jest/BookNavigator/search/search-results.test.js +0 -289
  300. package/tests/jest/BookNavigator/sharing/sharing-provider.test.js +0 -49
  301. package/tests/jest/BookNavigator/viewable-files/viewable-files-provider.test.js +0 -80
  302. package/tests/jest/BookNavigator/visual-adjustments.test.js +0 -200
  303. package/tests/jest/BookReader.keyboard.test.js +0 -190
  304. package/tests/jest/BookReader.options.test.js +0 -47
  305. package/tests/jest/BookReader.test.js +0 -316
  306. package/tests/jest/plugins/plugin.archive_analytics.test.js +0 -20
  307. package/tests/jest/plugins/plugin.autoplay.test.js +0 -35
  308. package/tests/jest/plugins/plugin.chapters.test.js +0 -193
  309. package/tests/jest/plugins/plugin.iframe.test.js +0 -42
  310. package/tests/jest/plugins/plugin.resume.test.js +0 -85
  311. package/tests/jest/plugins/plugin.text_selection.test.js +0 -447
  312. package/tests/jest/plugins/plugin.vendor-fullscreen.test.js +0 -65
  313. package/tests/jest/plugins/search/plugin.search.test.js +0 -120
  314. package/tests/jest/plugins/search/plugin.search.view.test.js +0 -131
  315. package/tests/jest/plugins/search/utils.js +0 -25
  316. package/tests/jest/plugins/search/utils.test.js +0 -29
  317. package/tests/jest/plugins/tts/AbstractTTSEngine.test.js +0 -173
  318. package/tests/jest/plugins/tts/FestivalTTSEngine.test.js +0 -59
  319. package/tests/jest/plugins/tts/PageChunk.test.js +0 -57
  320. package/tests/jest/plugins/tts/PageChunkIterator.test.js +0 -179
  321. package/tests/jest/plugins/tts/WebTTSEngine.test.js +0 -178
  322. package/tests/jest/plugins/tts/utils.test.js +0 -74
  323. package/tests/jest/plugins/url/UrlPlugin.test.js +0 -198
  324. package/tests/jest/plugins/url/plugin.url.test.js +0 -168
  325. package/tests/jest/setup.js +0 -3
  326. package/tests/jest/util/browserSniffing.test.js +0 -62
  327. package/tests/jest/util/docCookies.test.js +0 -24
  328. package/tests/jest/util/strings.test.js +0 -63
  329. package/tests/jest/utils.js +0 -83
  330. package/webpack.config.js +0 -97
@@ -0,0 +1,414 @@
1
+ // @ts-check
2
+ import { html, LitElement } from 'lit';
3
+ import { BookReaderPlugin } from '../../BookReaderPlugin.js';
4
+ import { customElement, property } from 'lit/decorators.js';
5
+ import { langs, TranslationManager } from "./TranslationManager.js";
6
+
7
+ // @ts-ignore
8
+ const BookReader = /** @type {typeof import('@/src/BookReader.js').default} */(window.BookReader);
9
+
10
+ export class TranslatePlugin extends BookReaderPlugin {
11
+
12
+ options = {
13
+ enabled: true,
14
+ panelDisclaimerText: "Translations are in alpha",
15
+ }
16
+
17
+ /** @type {TranslationManager} */
18
+ translationManager = new TranslationManager();
19
+
20
+ /** @type {Worker}*/
21
+ worker;
22
+
23
+ /**
24
+ * Contains the list of languages available to translate to
25
+ * @type {string[]}
26
+ */
27
+ toLanguages = [];
28
+
29
+ /**
30
+ * Current language code that is being translated From
31
+ * @type {!string}
32
+ */
33
+ langFromCode = "en";
34
+
35
+ /**
36
+ * Current language code that is being translated To
37
+ * @type {!string}
38
+ */
39
+ langToCode;
40
+ /**
41
+ * @type {BrTranslatePanel} _panel - Represents a panel used in the plugin.
42
+ * The specific type and purpose of this panel should be defined based on its usage.
43
+ */
44
+ _panel;
45
+
46
+ async init() {
47
+ if (!this.options.enabled) {
48
+ return;
49
+ }
50
+
51
+ this.translationManager.publicPath = this.br.options.imagesBaseURL.replace(/\/+$/, '') + '/..';
52
+
53
+ /**
54
+ * @param {*} ev
55
+ * @param {object} eventProps
56
+ */
57
+ this.br.on('textLayerRendered', async (_, {pageIndex, pageContainer}) => {
58
+ // Stops invalid models from running, also prevents translation on page load
59
+ // TODO check if model has finished loading or if it exists
60
+ if (!this.translationManager) {
61
+ return;
62
+ }
63
+ if (this.translationManager.active) {
64
+ const pageElement = pageContainer.$container[0];
65
+ this.translateRenderedLayer(pageElement);
66
+ }
67
+ });
68
+
69
+ /**
70
+ * @param {*} ev
71
+ * @param {object} eventProps
72
+ */
73
+ this.br.on('pageVisible', (_, {pageContainerEl}) => {
74
+ if (!this.translationManager.active) {
75
+ return;
76
+ }
77
+ for (const paragraphEl of pageContainerEl.querySelectorAll('.BRtranslateLayer > .BRparagraphElement')) {
78
+ if (paragraphEl.textContent) {
79
+ this.fitVisiblePage(paragraphEl);
80
+ }
81
+ }
82
+ });
83
+
84
+ await this.translationManager.initWorker();
85
+ // Note await above lets _render function properly, since it gives the browser
86
+ // time to render the rest of bookreader, which _render depends on
87
+ this._render();
88
+
89
+ this.langToCode = this.translationManager.toLanguages[0].code;
90
+
91
+ }
92
+
93
+ /** @param {HTMLElement} page*/
94
+ getParagraphsOnPage = (page) => {
95
+ return page ? Array.from(page.querySelectorAll(".BRtextLayer > .BRparagraphElement")) : [];
96
+ }
97
+
98
+ translateActivePageContainerElements() {
99
+ const currentlyActiveContainers = this.br.getActivePageContainerElements();
100
+ const visiblePageContainers = currentlyActiveContainers.filter((element) => {
101
+ return element.classList.contains('BRpage-visible');
102
+ });
103
+ const hiddenPageContainers = currentlyActiveContainers.filter((element) => {
104
+ return !element.classList.contains('BRpage-visible');
105
+ });
106
+
107
+ for (const page of visiblePageContainers) {
108
+ this.translateRenderedLayer(page, 0);
109
+ }
110
+ for (const loadingPage of hiddenPageContainers) {
111
+ this.translateRenderedLayer(loadingPage, 1000);
112
+ }
113
+ }
114
+
115
+ /** @param {HTMLElement} page */
116
+ async translateRenderedLayer(page, priority) {
117
+ if (this.br.mode == this.br.constModeThumb) {
118
+ return;
119
+ }
120
+
121
+ const pageIndex = page.dataset.index;
122
+
123
+ let pageTranslationLayer;
124
+ if (!page.querySelector('.BRPageLayer.BRtranslateLayer')) {
125
+ pageTranslationLayer = document.createElement('div');
126
+ pageTranslationLayer.classList.add('BRPageLayer', 'BRtranslateLayer');
127
+ pageTranslationLayer.setAttribute('lang', `${this.langToCode}`);
128
+ page.prepend(pageTranslationLayer);
129
+ } else {
130
+ pageTranslationLayer = page.querySelector('.BRPageLayer.BRtranslateLayer');
131
+ }
132
+
133
+ const textLayerElement = page.querySelector('.BRtextLayer');
134
+ textLayerElement.classList.add('showingTranslation');
135
+ $(pageTranslationLayer).css({
136
+ "width": $(textLayerElement).css("width"),
137
+ "height": $(textLayerElement).css("height"),
138
+ "transform": $(textLayerElement).css("transform"),
139
+ "pointer-events": $(textLayerElement).css("pointer-events"),
140
+ "z-index": 3,
141
+ });
142
+ const paragraphs = this.getParagraphsOnPage(page);
143
+
144
+ paragraphs.forEach(async (paragraph, pidx) => {
145
+ let translatedParagraph = page.querySelector(`[data-translate-index='${pageIndex}-${pidx}']`);
146
+ if (!translatedParagraph) {
147
+ translatedParagraph = document.createElement('p');
148
+ // set data-translate-index on the placeholder
149
+ translatedParagraph.setAttribute('data-translate-index', `${pageIndex}-${pidx}`);
150
+ translatedParagraph.className = 'BRparagraphElement';
151
+ const originalParagraphStyle = paragraphs[pidx];
152
+ const fontSize = `${parseInt($(originalParagraphStyle).css("font-size"))}px`;
153
+
154
+ $(translatedParagraph).css({
155
+ "margin-left": $(originalParagraphStyle).css("margin-left"),
156
+ "margin-top": $(originalParagraphStyle).css("margin-top"),
157
+ "top": $(originalParagraphStyle).css("top"),
158
+ "height": $(originalParagraphStyle).css("height"),
159
+ "width": $(originalParagraphStyle).css("width"),
160
+ "font-size": fontSize,
161
+ });
162
+
163
+ // Note: We'll likely want to switch to using the same logic as
164
+ // TextSelectionPlugin's selection, which allows for e.g. click-to-flip
165
+ // to work simultaneously with text selection.
166
+ translatedParagraph.addEventListener('mousedown', (e) => {
167
+ e.stopPropagation();
168
+ e.stopImmediatePropagation();
169
+ });
170
+
171
+ translatedParagraph.addEventListener('mouseup', (e) => {
172
+ e.stopPropagation();
173
+ e.stopImmediatePropagation();
174
+ });
175
+
176
+ translatedParagraph.addEventListener('dragstart', (e) =>{
177
+ e.preventDefault();
178
+ });
179
+ pageTranslationLayer.append(translatedParagraph);
180
+ }
181
+
182
+ if (paragraph.textContent.length !== 0) {
183
+ const pagePriority = parseFloat(pageIndex) + priority + pidx;
184
+ const translatedText = await this.translationManager.getTranslation(this.langFromCode, this.langToCode, pageIndex, pidx, paragraph.textContent, pagePriority);
185
+ // prevent duplicate spans from appearing if exists
186
+ translatedParagraph.firstElementChild?.remove();
187
+
188
+ const firstWordSpacing = paragraphs[pidx]?.firstChild?.firstChild;
189
+ const createSpan = document.createElement('span');
190
+ createSpan.className = 'BRlineElement';
191
+ createSpan.textContent = translatedText;
192
+ translatedParagraph.appendChild(createSpan);
193
+
194
+ $(createSpan).css({
195
+ "text-indent": $(firstWordSpacing).css('padding-left'),
196
+ });
197
+ if (page.classList.contains('BRpage-visible')) {
198
+ this.fitVisiblePage(translatedParagraph);
199
+ }
200
+ }
201
+ });
202
+ }
203
+
204
+ clearAllTranslations() {
205
+ document.querySelectorAll('.BRtranslateLayer').forEach(el => el.remove());
206
+ }
207
+
208
+ /**
209
+ * @param {Element} paragEl
210
+ */
211
+ fitVisiblePage(paragEl) {
212
+ // For some reason, Chrome does not detect the transform property for the translation + text layers
213
+ // Could not get it to fetch the transform value using $().css method
214
+ // Oddly enough the value is retrieved if using .style.transform instead?
215
+ const translateLayerEl = paragEl.parentElement;
216
+ if ($(translateLayerEl).css('transform') == 'none') {
217
+ const pageNumber = paragEl.getAttribute('data-translate-index').split('-')[0];
218
+ /** @type {HTMLElement} selectionTransform */
219
+ const textLayerEl = document.querySelector(`[data-index='${pageNumber}'] .BRtextLayer`);
220
+ $(translateLayerEl).css({'transform': textLayerEl.style.transform});
221
+ }
222
+
223
+ const originalFontSize = parseInt($(paragEl).css("font-size"));
224
+ let adjustedFontSize = originalFontSize;
225
+ while (paragEl.clientHeight < paragEl.scrollHeight && adjustedFontSize > 0) {
226
+ adjustedFontSize--;
227
+ $(paragEl).css({ "font-size": `${adjustedFontSize}px` });
228
+ }
229
+
230
+ const textHeight = paragEl.firstElementChild.clientHeight;
231
+ const scrollHeight = paragEl.scrollHeight;
232
+ const fits = textHeight < scrollHeight;
233
+ if (fits) {
234
+ const lines = textHeight / adjustedFontSize;
235
+ // Line heights for smaller paragraphs occasionally need a minor adjustment
236
+ const newLineHeight = scrollHeight / lines;
237
+ $(paragEl).css({
238
+ "line-height" : `${newLineHeight}px`,
239
+ "overflow": "visible",
240
+ });
241
+ }
242
+ }
243
+
244
+ handleFromLangChange = async (e) => {
245
+ this.clearAllTranslations();
246
+ const selectedLangFrom = e.detail.value;
247
+
248
+ // Update the from language
249
+ this.langFromCode = selectedLangFrom;
250
+
251
+ // Add 'From' language to 'To' list if not already present
252
+ if (!this.translationManager.toLanguages.some(lang => lang.code === selectedLangFrom)) {
253
+ this.translationManager.toLanguages.push({ code: selectedLangFrom, name: langs[selectedLangFrom] });
254
+ }
255
+
256
+ // Update the 'To' languages list and set the correct 'To' language
257
+ this._panel.toLanguages = this.translationManager.toLanguages;
258
+
259
+ console.log(this.langFromCode, this.langToCode);
260
+ if (this.langFromCode !== this.langToCode) {
261
+ this.translateActivePageContainerElements();
262
+ }
263
+ }
264
+
265
+ handleToLangChange = async (e) => {
266
+ this.clearAllTranslations();
267
+ this.langToCode = e.detail.value;
268
+ this.translateActivePageContainerElements();
269
+ }
270
+
271
+
272
+ /**
273
+ * Update the table of contents based on array of TOC entries.
274
+ */
275
+ _render() {
276
+ this.br.shell.menuProviders['translate'] = {
277
+ id: 'translate',
278
+ icon: html`<img src='${this.br.options.imagesBaseURL}/translate.svg' width="26"/>`,
279
+ label: 'Translate',
280
+ component: html`<br-translate-panel
281
+ @connected="${e => {
282
+ this._panel = e.target;
283
+ this._panel.fromLanguages = this.translationManager.fromLanguages;
284
+ this._panel.toLanguages = this.translationManager.toLanguages;
285
+ }
286
+ }"
287
+ @langFromChanged="${this.handleFromLangChange}"
288
+ @langToChanged="${this.handleToLangChange}"
289
+ .fromLanguages="${this.translationManager.fromLanguages}"
290
+ .toLanguages="${this.translationManager.toLanguages}"
291
+ .disclaimerMessage="${this.options.panelDisclaimerText}"
292
+ class="translate-panel"
293
+ />`,
294
+ };
295
+ this.br.shell.updateMenuContents();
296
+ }
297
+ }
298
+ BookReader?.registerPlugin('translate', TranslatePlugin);
299
+
300
+ @customElement('br-translate-panel')
301
+ export class BrTranslatePanel extends LitElement {
302
+ @property({ type: Array }) fromLanguages = []; // List of obj {code, name}
303
+ @property({ type: Array }) toLanguages = []; // List of obj {code, name}
304
+ @property({ type: String }) prevSelectedLang = ''; // Tracks the previous selected language for the "To" dropdown
305
+ @property({ type: String }) disclaimerMessage = '';
306
+
307
+ /** @override */
308
+ createRenderRoot() {
309
+ // Disable shadow DOM; that would require a huge rejiggering of CSS
310
+ return this;
311
+ }
312
+
313
+ connectedCallback() {
314
+ super.connectedCallback();
315
+ this.dispatchEvent(new CustomEvent('connected'));
316
+ }
317
+
318
+ render() {
319
+ const showPrevLangButton =
320
+ this.prevSelectedLang &&
321
+ (this.prevSelectedLang !== this._getSelectedLang('to') || this._getSelectedLang('from') === this._getSelectedLang('to'));
322
+
323
+ return html`<div class="app">
324
+ <div class="panel panel--from">
325
+ <label>
326
+ From
327
+ <select id="lang-from" name="from" class="lang-select" @change="${this._onLangFromChange}">
328
+ ${this.fromLanguages.map(
329
+ lang => html`<option value="${lang.code}">${lang.name}</option>`,
330
+ )}
331
+ </select>
332
+ </label>
333
+ </div>
334
+ <div class="panel panel--to">
335
+ <label>
336
+ To
337
+ <select id="lang-to" name="to" class="lang-select" @change="${this._onLangToChange}">
338
+ ${this.toLanguages.map(
339
+ lang => html`<option value="${lang.code}">${lang.name}</option>`,
340
+ )}
341
+ </select>
342
+ </label>
343
+ ${showPrevLangButton
344
+ ? html`<button class="prev-lang-btn" @click="${this._onPrevLangClick}">
345
+ ${this._getLangName(this.prevSelectedLang)}
346
+ </button>`
347
+ : ''}
348
+ </div>
349
+ <div class="footer" id="status"></div>
350
+ <br/>
351
+ <div class="disclaimer" id="disclaimerMessage"> ${this.disclaimerMessage} </div>
352
+ </div>`;
353
+ }
354
+
355
+ _onLangFromChange(event) {
356
+ const langFromChangedEvent = new CustomEvent('langFromChanged', {
357
+ detail: { value: event.target.value },
358
+ bubbles: true,
359
+ composed: true,
360
+ });
361
+ this.dispatchEvent(langFromChangedEvent);
362
+
363
+ // Update the prevSelectedLang if "To" is different from "From"
364
+ if (this._getSelectedLang('to') !== this._getSelectedLang('from')) {
365
+ this.prevSelectedLang = this._getSelectedLang('from');
366
+ }
367
+ }
368
+
369
+ _onLangToChange(event) {
370
+ const langToChangedEvent = new CustomEvent('langToChanged', {
371
+ detail: { value: event.target.value },
372
+ bubbles: true,
373
+ composed: true,
374
+ });
375
+ this.dispatchEvent(langToChangedEvent);
376
+
377
+ // Update the prevSelectedLang if "To" is different from "From"
378
+ if (this._getSelectedLang('from') !== event.target.value) {
379
+ this.prevSelectedLang = this._getSelectedLang('from');
380
+ }
381
+ }
382
+
383
+ _onPrevLangClick() {
384
+ const prevLang = this.prevSelectedLang;
385
+ if (prevLang == this._getSelectedLang('from')) {
386
+ console.log("_onPrevLangClick: will not change since prevLang is the same as the current 'To' language code");
387
+ return;
388
+ }
389
+ this.prevSelectedLang = this._getSelectedLang('to'); // Update prevSelectedLang to current "To" value
390
+ const langToChangedEvent = new CustomEvent('langToChanged', {
391
+ detail: { value: prevLang },
392
+ bubbles: true,
393
+ composed: true,
394
+ });
395
+ this.dispatchEvent(langToChangedEvent);
396
+
397
+ // Update the "To" dropdown to the previous language
398
+ const toDropdown = this.querySelector('#lang-to');
399
+ if (toDropdown) {
400
+ toDropdown.value = prevLang;
401
+ }
402
+ }
403
+
404
+ _getSelectedLang(type) {
405
+ const dropdown = this.querySelector(`#lang-${type}`);
406
+ return dropdown ? dropdown.value : '';
407
+ }
408
+
409
+ _getLangName(code) {
410
+ const lang = [...this.fromLanguages, ...this.toLanguages].find(lang => lang.code === code);
411
+ return lang ? lang.name : '';
412
+ }
413
+ }
414
+
@@ -1,4 +1,4 @@
1
- import langs from 'iso-language-codes/js/data.js';
1
+ import langs from 'iso-language-codes';
2
2
 
3
3
  /**
4
4
  * Use regex to approximate word count in a string
@@ -24,15 +24,6 @@ export function isAndroid(userAgent = navigator.userAgent) {
24
24
  * Language code in ISO 639-1 format. e.g. en, fr, zh
25
25
  **/
26
26
 
27
- /** Each lang is an array, with each index mapping to a different property */
28
- const COLUMN_TO_LANG_INDEX = {
29
- 'Name': 0,
30
- 'Endonym': 1,
31
- 'ISO 639-1': 2,
32
- 'ISO 639-2/T': 3,
33
- 'ISO 639-2/B': 4,
34
- };
35
-
36
27
  /**
37
28
  * @param {string} language in some format
38
29
  * @return {ISO6391?}
@@ -41,24 +32,22 @@ export function toISO6391(language) {
41
32
  if (!language) return null;
42
33
  language = language.toLowerCase();
43
34
 
44
- return searchForISO6391(language, ['ISO 639-1']) ||
45
- searchForISO6391(language, ['ISO 639-2/B']) ||
46
- searchForISO6391(language, ['ISO 639-2/T', 'Endonym', 'Name']);
35
+ return searchForISO6391(language, ['iso639_1']) ||
36
+ searchForISO6391(language, ['iso639_2T']) ||
37
+ searchForISO6391(language, ['iso639_2B', 'nativeName', 'name']);
47
38
  }
48
39
 
49
40
  /**
50
41
  * Searches for the given long in the given columns.
51
42
  * @param {string} language
52
- * @param {Array<keyof COLUMN_TO_LANG_INDEX>} columnsToSearch
43
+ * @param {Array<keyof import('iso-language-codes').Code>} columnsToSearch
53
44
  * @return {ISO6391?}
54
45
  */
55
46
  function searchForISO6391(language, columnsToSearch) {
56
- for (let i = 0; i < langs.length; i++) {
57
- for (let colI = 0; colI < columnsToSearch.length; colI++) {
58
- const column = columnsToSearch[colI];
59
- const columnValue = langs[i][COLUMN_TO_LANG_INDEX[column]];
60
- if (columnValue.split(', ').map(x => x.toLowerCase()).indexOf(language) != -1) {
61
- return langs[i][COLUMN_TO_LANG_INDEX['ISO 639-1']];
47
+ for (const lang of langs) {
48
+ for (const colName of columnsToSearch) {
49
+ if (lang[colName].split(', ').map(x => x.toLowerCase()).indexOf(language) != -1) {
50
+ return lang.iso639_1;
62
51
  }
63
52
  }
64
53
  }
@@ -0,0 +1,20 @@
1
+ /**
2
+ * @template T
3
+ */
4
+ export class Cache {
5
+ constructor(maxSize = 10) {
6
+ this.maxSize = maxSize;
7
+ /** @type {T[]} */
8
+ this.entries = [];
9
+ }
10
+
11
+ /**
12
+ * @param {T} entry
13
+ */
14
+ add(entry) {
15
+ if (this.entries.length >= this.maxSize) {
16
+ this.entries.shift();
17
+ }
18
+ this.entries.push(entry);
19
+ }
20
+ }
package/.eslintrc.cjs DELETED
@@ -1,51 +0,0 @@
1
- module.exports = {
2
- "parser": "@babel/eslint-parser",
3
- "env": {
4
- "browser": true,
5
- "jquery": true,
6
- "es6": true,
7
- "node": true,
8
- "jest": true,
9
- },
10
- "plugins": [
11
- "testcafe",
12
- "no-jquery",
13
- ],
14
- "extends": [
15
- "eslint:recommended",
16
- "plugin:testcafe/recommended",
17
- "plugin:no-jquery/deprecated",
18
- ],
19
- "globals": {
20
- // Browser API
21
- "MediaMetadata": "readonly",
22
- },
23
- "parserOptions": {
24
- "ecmaVersion": 2020,
25
- "ecmaFeatures": { "legacyDecorators": true },
26
- "sourceType": "module",
27
- },
28
- "rules": {
29
- "comma-dangle": ["error", "always-multiline", {"functions": "only-multiline"}],
30
- "semi": ["error", "always"],
31
- "space-before-blocks": ["error"],
32
- "keyword-spacing": [2, {"before": true, "after": true}],
33
- "indent": ["error", 2, {
34
- // This for some reason causing errors after switch to parser: babel-eslint.
35
- // See https://github.com/babel/babel-eslint/issues/681
36
- "ignoredNodes": ["TemplateLiteral"],
37
- }],
38
- "no-console": "off", // Used too often behind `debug` options; not dealing with this now
39
- "no-empty": ["error", { "allowEmptyCatch": true }],
40
- "no-jquery/no-bind": ["error"],
41
- "no-jquery/no-event-shorthand": ["error"],
42
- "no-jquery/no-sizzle": ["error"],
43
- "no-jquery/no-trim": ["error"],
44
- "no-trailing-spaces": ["error"],
45
- "no-unused-vars": ["error", { "vars": "all", "args": "none", "ignoreRestSiblings": false }], // set args:none; this is generally more annoying than useful
46
- "no-var": ["error"],
47
- "prefer-const": ["error"],
48
- "space-infix-ops": ["error", { "int32Hint": false }],
49
- "eol-last": ["error", "always"],
50
- },
51
- };
package/.gitattributes DELETED
@@ -1,2 +0,0 @@
1
- # Build files
2
- BookReader/**/* binary
@@ -1,32 +0,0 @@
1
- ---
2
- name: Bug
3
- about: A general problem with website functionality
4
- title: ''
5
- labels: Bug
6
- assignees: ''
7
-
8
- ---
9
-
10
- **Description**
11
-
12
- > What problem are we solving? What does the experience look like today? What are the symptoms? How can one reproduce the problem?
13
-
14
- **Evidence / Screenshot (if possible)**
15
-
16
- > Include evidence of the problem or provide a screenshot.
17
-
18
- **Expectation**
19
-
20
- > What should be happening? What will it look like / how will it behave when fixed?
21
-
22
- **Context**
23
-
24
- > What operating system? What browser type and version?
25
-
26
- **Proposal & Constraints**
27
-
28
- > What is the proposed solution / implementation? Is there a precedent of this approach succeeding elsewhere?
29
-
30
- **Stakeholders**
31
-
32
- > @-tag any stakeholders of this bug
@@ -1,30 +0,0 @@
1
- ---
2
- name: Feature Request
3
- about: A request for an entirely new feature
4
- title: ''
5
- labels: Feature Request
6
- assignees: ''
7
-
8
- ---
9
-
10
- **Context**
11
-
12
- > Is your feature request related to a problem? What is the motivation for implementing this feature?
13
-
14
- **Proposal & Constraints**
15
-
16
- > What is the proposed solution / implementation? Is there a precedent for this approach succeeding elsewhere?
17
-
18
- > Which suggestions or requirements should be considered for how this feature needs to appear or be implemented?
19
-
20
- **Additional Resources**
21
-
22
- > Add any other screenshots or assets related to the feature request.
23
-
24
- **Success Metrics**
25
-
26
- > How will you know if this change is successful? What specific metrics are relevant and how do you expect them to change?
27
-
28
- **Stakeholders**
29
-
30
- > @-tag stakeholders of this feature
@@ -1,15 +0,0 @@
1
- **Description**
2
-
3
- > What does this PR achieve? Is it a feature/bugfix/refactor? Does it close an Issue? If so, use `Closes #<issue number>`.
4
-
5
- **Technical**
6
-
7
- > What should be noted about the implementation?
8
-
9
- **Testing**
10
-
11
- > What steps should the reviewer take to verify this PR resolves the issue?
12
-
13
- **Screenshots/Videos**
14
-
15
- > Add a screenshot or video/GIF if the fix can be seen visually. This is helpful for reviewers to get context for the fix.