@internetarchive/bookreader 5.0.0-11 → 5.0.0-110

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 (380) hide show
  1. package/BookReader/474.js +2 -0
  2. package/BookReader/474.js.map +1 -0
  3. package/BookReader/BookReader.css +604 -1239
  4. package/BookReader/BookReader.js +1 -1
  5. package/BookReader/BookReader.js.LICENSE.txt +20 -20
  6. package/BookReader/BookReader.js.map +1 -1
  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 +1907 -0
  53. package/BookReader/ia-bookreader-bundle.js.LICENSE.txt +19 -0
  54. package/BookReader/ia-bookreader-bundle.js.map +1 -0
  55. package/BookReader/icons/1up.svg +1 -1
  56. package/BookReader/icons/2up.svg +1 -1
  57. package/BookReader/icons/advance.svg +1 -1
  58. package/BookReader/icons/chevron-right.svg +1 -1
  59. package/BookReader/icons/close-circle-dark.svg +1 -1
  60. package/BookReader/icons/close-circle.svg +1 -1
  61. package/BookReader/icons/fullscreen.svg +1 -1
  62. package/BookReader/icons/fullscreen_exit.svg +1 -1
  63. package/BookReader/icons/hamburger.svg +1 -1
  64. package/BookReader/icons/left-arrow.svg +1 -1
  65. package/BookReader/icons/magnify-minus.svg +1 -1
  66. package/BookReader/icons/magnify-plus.svg +1 -1
  67. package/BookReader/icons/magnify.svg +1 -1
  68. package/BookReader/icons/pause.svg +1 -1
  69. package/BookReader/icons/play.svg +1 -1
  70. package/BookReader/icons/playback-speed.svg +1 -1
  71. package/BookReader/icons/read-aloud.svg +1 -1
  72. package/BookReader/icons/review.svg +1 -1
  73. package/BookReader/icons/slider-toggle.svg +1 -0
  74. package/BookReader/icons/thumbnails.svg +1 -1
  75. package/BookReader/icons/voice.svg +1 -0
  76. package/BookReader/icons/volume-full.svg +1 -1
  77. package/BookReader/images/BRicons.svg +3 -3
  78. package/BookReader/images/books_graphic.svg +1 -1
  79. package/BookReader/images/hypothesis.ico +0 -0
  80. package/BookReader/images/icon_book.svg +1 -1
  81. package/BookReader/images/icon_bookmark.svg +1 -1
  82. package/BookReader/images/icon_experiment.svg +1 -0
  83. package/BookReader/images/icon_gear.svg +1 -1
  84. package/BookReader/images/icon_hamburger.svg +1 -1
  85. package/BookReader/images/icon_home.svg +1 -1
  86. package/BookReader/images/icon_info.svg +1 -1
  87. package/BookReader/images/icon_one_page.svg +1 -1
  88. package/BookReader/images/icon_pause.svg +1 -1
  89. package/BookReader/images/icon_play.svg +1 -1
  90. package/BookReader/images/icon_playback-rate.svg +1 -1
  91. package/BookReader/images/icon_search_button.svg +1 -1
  92. package/BookReader/images/icon_share.svg +1 -1
  93. package/BookReader/images/icon_skip-ahead.svg +1 -1
  94. package/BookReader/images/icon_skip-back.svg +1 -1
  95. package/BookReader/images/icon_speaker.svg +1 -1
  96. package/BookReader/images/icon_speaker_open.svg +1 -1
  97. package/BookReader/images/icon_thumbnails.svg +1 -1
  98. package/BookReader/images/icon_toc.svg +1 -1
  99. package/BookReader/images/icon_two_pages.svg +1 -1
  100. package/BookReader/images/marker_chap-off.svg +1 -1
  101. package/BookReader/images/marker_chap-on.svg +1 -1
  102. package/BookReader/images/marker_srch-on.svg +1 -1
  103. package/BookReader/images/translate.svg +1 -0
  104. package/BookReader/images/unviewable_page.png +0 -0
  105. package/BookReader/jquery-3.js +2 -0
  106. package/BookReader/jquery-3.js.LICENSE.txt +24 -0
  107. package/BookReader/plugins/plugin.archive_analytics.js +1 -1
  108. package/BookReader/plugins/plugin.archive_analytics.js.map +1 -1
  109. package/BookReader/plugins/plugin.autoplay.js +1 -1
  110. package/BookReader/plugins/plugin.autoplay.js.map +1 -1
  111. package/BookReader/plugins/plugin.chapters.js +22 -1
  112. package/BookReader/plugins/plugin.chapters.js.LICENSE.txt +1 -0
  113. package/BookReader/plugins/plugin.chapters.js.map +1 -1
  114. package/BookReader/plugins/plugin.experiments.js +3 -0
  115. package/BookReader/plugins/plugin.experiments.js.LICENSE.txt +1 -0
  116. package/BookReader/plugins/plugin.experiments.js.map +1 -0
  117. package/BookReader/plugins/plugin.iframe.js +1 -1
  118. package/BookReader/plugins/plugin.iframe.js.map +1 -1
  119. package/BookReader/plugins/plugin.iiif.js +2 -0
  120. package/BookReader/plugins/plugin.iiif.js.map +1 -0
  121. package/BookReader/plugins/plugin.resume.js +1 -1
  122. package/BookReader/plugins/plugin.resume.js.map +1 -1
  123. package/BookReader/plugins/plugin.search.js +2 -1
  124. package/BookReader/plugins/plugin.search.js.LICENSE.txt +1 -0
  125. package/BookReader/plugins/plugin.search.js.map +1 -1
  126. package/BookReader/plugins/plugin.text_selection.js +2 -1
  127. package/BookReader/plugins/plugin.text_selection.js.LICENSE.txt +1 -0
  128. package/BookReader/plugins/plugin.text_selection.js.map +1 -1
  129. package/BookReader/plugins/plugin.translate.js +137 -0
  130. package/BookReader/plugins/plugin.translate.js.LICENSE.txt +1 -0
  131. package/BookReader/plugins/plugin.translate.js.map +1 -0
  132. package/BookReader/plugins/plugin.tts.js +1 -1
  133. package/BookReader/plugins/plugin.tts.js.LICENSE.txt +2 -0
  134. package/BookReader/plugins/plugin.tts.js.map +1 -1
  135. package/BookReader/plugins/plugin.url.js +1 -1
  136. package/BookReader/plugins/plugin.url.js.map +1 -1
  137. package/BookReader/plugins/plugin.vendor-fullscreen.js +1 -1
  138. package/BookReader/plugins/plugin.vendor-fullscreen.js.map +1 -1
  139. package/BookReader/plugins/translator-worker.js +2 -0
  140. package/BookReader/plugins/translator-worker.js.map +1 -0
  141. package/BookReader/silence.mp3 +0 -0
  142. package/BookReader/translator-worker.js +475 -0
  143. package/BookReader/webcomponents-bundle.js +3 -0
  144. package/BookReader/webcomponents-bundle.js.LICENSE.txt +9 -0
  145. package/BookReader/webcomponents-bundle.js.map +1 -0
  146. package/README.md +14 -3
  147. package/jsconfig.json +19 -0
  148. package/package.json +92 -70
  149. package/src/BookReader/BookModel.js +92 -46
  150. package/src/BookReader/DragScrollable.js +233 -0
  151. package/src/BookReader/ImageCache.js +49 -16
  152. package/src/BookReader/Mode1Up.js +66 -365
  153. package/src/BookReader/Mode1UpLit.js +392 -0
  154. package/src/BookReader/Mode2Up.js +87 -1315
  155. package/src/BookReader/Mode2UpLit.js +788 -0
  156. package/src/BookReader/ModeAbstract.js +43 -0
  157. package/src/BookReader/ModeCoordinateSpace.js +29 -0
  158. package/src/BookReader/ModeSmoothZoom.js +312 -0
  159. package/src/BookReader/ModeThumb.js +29 -15
  160. package/src/BookReader/Navbar/Navbar.js +201 -76
  161. package/src/BookReader/PageContainer.js +120 -23
  162. package/src/BookReader/ReduceSet.js +2 -2
  163. package/src/BookReader/Toolbar/Toolbar.js +18 -40
  164. package/src/BookReader/events.js +3 -3
  165. package/src/BookReader/options.js +94 -17
  166. package/src/BookReader/utils/HTMLDimensionsCacher.js +44 -0
  167. package/src/BookReader/utils/ScrollClassAdder.js +31 -0
  168. package/src/BookReader/utils/SelectionObserver.js +45 -0
  169. package/src/BookReader/utils/classes.js +1 -1
  170. package/src/BookReader/utils.js +136 -12
  171. package/src/BookReader.js +678 -1226
  172. package/src/BookReaderPlugin.js +52 -0
  173. package/src/assets/icons/magnify-minus.svg +3 -7
  174. package/src/assets/icons/magnify-plus.svg +3 -7
  175. package/src/assets/icons/slider-toggle.svg +1 -0
  176. package/src/assets/icons/voice.svg +1 -0
  177. package/src/assets/images/hypothesis.ico +0 -0
  178. package/src/assets/images/icon_experiment.svg +1 -0
  179. package/src/assets/images/translate.svg +1 -0
  180. package/src/assets/images/unviewable_page.png +0 -0
  181. package/src/assets/silence.mp3 +0 -0
  182. package/src/css/BookReader.scss +1 -5
  183. package/src/css/_BRBookmarks.scss +1 -1
  184. package/src/css/_BRComponent.scss +1 -1
  185. package/src/css/_BRicon.scss +8 -2
  186. package/src/css/_BRmain.scss +16 -3
  187. package/src/css/_BRnav.scss +74 -70
  188. package/src/css/_BRpages.scss +171 -42
  189. package/src/css/_BRsearch.scss +69 -30
  190. package/src/css/_BRtoolbar.scss +5 -5
  191. package/src/css/_TextSelection.scss +129 -24
  192. package/src/css/_colorbox.scss +2 -2
  193. package/src/css/_controls.scss +24 -7
  194. package/src/css/_icons.scss +8 -1
  195. package/src/{BookNavigator/assets → css}/button-base.js +2 -2
  196. package/src/css/icon_checkmark.js +9 -0
  197. package/src/css/sharedStyles.js +15 -0
  198. package/src/ia-bookreader/downloads/downloads-provider.js +81 -0
  199. package/src/{BookNavigator → ia-bookreader}/downloads/downloads.js +25 -5
  200. package/src/ia-bookreader/ia-bookreader.js +666 -0
  201. package/src/ia-bookreader/sharing.js +27 -0
  202. package/src/ia-bookreader/viewable-files.js +98 -0
  203. package/src/{BookNavigator → ia-bookreader}/visual-adjustments/visual-adjustments-provider.js +17 -17
  204. package/src/{BookNavigator → ia-bookreader}/visual-adjustments/visual-adjustments.js +75 -67
  205. package/src/{BookNavigator → plugins}/bookmarks/bookmark-button.js +4 -3
  206. package/src/{BookNavigator/assets → plugins/bookmarks}/bookmark-colors.js +1 -1
  207. package/src/{BookNavigator → plugins}/bookmarks/bookmark-edit.js +43 -31
  208. package/src/{BookNavigator → plugins}/bookmarks/bookmarks-list.js +48 -49
  209. package/src/{BookNavigator → plugins}/bookmarks/bookmarks-loginCTA.js +3 -3
  210. package/src/plugins/bookmarks/bookmarks-provider.js +63 -0
  211. package/src/{BookNavigator → plugins/bookmarks}/delete-modal-actions.js +1 -1
  212. package/src/{BookNavigator → plugins}/bookmarks/ia-bookmarks.js +117 -68
  213. package/src/plugins/plugin.archive_analytics.js +84 -78
  214. package/src/plugins/plugin.autoplay.js +99 -104
  215. package/src/plugins/plugin.chapters.js +314 -205
  216. package/src/plugins/plugin.experiments.js +321 -0
  217. package/src/plugins/plugin.iframe.js +1 -1
  218. package/src/plugins/plugin.iiif.js +141 -0
  219. package/src/plugins/plugin.resume.js +54 -51
  220. package/src/plugins/plugin.text_selection.js +522 -219
  221. package/src/plugins/plugin.vendor-fullscreen.js +5 -5
  222. package/src/plugins/search/plugin.search.js +374 -392
  223. package/src/{BookNavigator → plugins}/search/search-provider.js +59 -27
  224. package/src/{BookNavigator → plugins}/search/search-results.js +105 -76
  225. package/src/plugins/search/utils.js +50 -0
  226. package/src/plugins/search/view.js +50 -68
  227. package/src/plugins/translate/TranslationManager.js +164 -0
  228. package/src/plugins/translate/plugin.translate.js +512 -0
  229. package/src/plugins/tts/AbstractTTSEngine.js +78 -49
  230. package/src/plugins/tts/FestivalTTSEngine.js +20 -30
  231. package/src/plugins/tts/PageChunk.js +33 -21
  232. package/src/plugins/tts/PageChunkIterator.js +11 -17
  233. package/src/plugins/tts/WebTTSEngine.js +131 -91
  234. package/src/plugins/tts/plugin.tts.js +345 -350
  235. package/src/plugins/tts/utils.js +77 -49
  236. package/src/plugins/url/UrlPlugin.js +191 -0
  237. package/src/plugins/{plugin.url.js → url/plugin.url.js} +44 -15
  238. package/src/util/TextSelectionManager.js +282 -0
  239. package/src/util/browserSniffing.js +33 -1
  240. package/src/util/cache.js +20 -0
  241. package/src/util/docCookies.js +21 -2
  242. package/src/util/lit.js +15 -0
  243. package/src/util/strings.js +1 -0
  244. package/.babelrc +0 -12
  245. package/.dependabot/config.yml +0 -6
  246. package/.eslintrc.js +0 -50
  247. package/.gitattributes +0 -2
  248. package/.github/ISSUE_TEMPLATE/bug.md +0 -32
  249. package/.github/ISSUE_TEMPLATE/feature-request.md +0 -30
  250. package/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md +0 -15
  251. package/.github/workflows/node.js.yml +0 -37
  252. package/.github/workflows/npm-publish.yml +0 -47
  253. package/.testcaferc.json +0 -5
  254. package/BookReader/bookreader-component-bundle.js +0 -1450
  255. package/BookReader/bookreader-component-bundle.js.LICENSE.txt +0 -38
  256. package/BookReader/bookreader-component-bundle.js.map +0 -1
  257. package/BookReader/jquery-1.10.1.js +0 -2
  258. package/BookReader/jquery-1.10.1.js.LICENSE.txt +0 -24
  259. package/BookReader/plugins/plugin.menu_toggle.js +0 -2
  260. package/BookReader/plugins/plugin.menu_toggle.js.map +0 -1
  261. package/BookReader/plugins/plugin.mobile_nav.js +0 -2
  262. package/BookReader/plugins/plugin.mobile_nav.js.map +0 -1
  263. package/BookReaderDemo/BookReaderDemo.css +0 -41
  264. package/BookReaderDemo/BookReaderJSAdvanced.js +0 -115
  265. package/BookReaderDemo/BookReaderJSAutoplay.js +0 -56
  266. package/BookReaderDemo/BookReaderJSSimple.js +0 -55
  267. package/BookReaderDemo/IIIFBookReader.js +0 -207
  268. package/BookReaderDemo/assets/v5/Bookreader-logo-cool-grad.svg +0 -1
  269. package/BookReaderDemo/assets/v5/Bookreader-logo-flat.svg +0 -1
  270. package/BookReaderDemo/assets/v5/Bookreader-logo-hex-cool-grad.png +0 -0
  271. package/BookReaderDemo/assets/v5/Bookreader-logo-hex-flat.png +0 -0
  272. package/BookReaderDemo/assets/v5/Bookreader-logo-lines.png +0 -0
  273. package/BookReaderDemo/assets/v5/Bookreader-logo-lines.svg +0 -1
  274. package/BookReaderDemo/assets/v5/Bookreader-logo-warm.svg +0 -1
  275. package/BookReaderDemo/assets/v5/bookreader-logo-renders@1x.png +0 -0
  276. package/BookReaderDemo/assets/v5/bookreader-logo-renders@2x.png +0 -0
  277. package/BookReaderDemo/assets/v5/bookreader-v5-screenshot.png +0 -0
  278. package/BookReaderDemo/bookreader-template-bundle.js +0 -7178
  279. package/BookReaderDemo/demo-advanced.html +0 -33
  280. package/BookReaderDemo/demo-autoplay.html +0 -38
  281. package/BookReaderDemo/demo-embed-iframe-src.html +0 -84
  282. package/BookReaderDemo/demo-embed.html +0 -26
  283. package/BookReaderDemo/demo-fullscreen-mobile.html +0 -36
  284. package/BookReaderDemo/demo-fullscreen.html +0 -33
  285. package/BookReaderDemo/demo-iiif.html +0 -34
  286. package/BookReaderDemo/demo-iiif.js +0 -26
  287. package/BookReaderDemo/demo-internetarchive.html +0 -74
  288. package/BookReaderDemo/demo-multiple.html +0 -43
  289. package/BookReaderDemo/demo-plugin-menu-toggle.html +0 -34
  290. package/BookReaderDemo/demo-preview-pages.html +0 -1092
  291. package/BookReaderDemo/demo-simple.html +0 -34
  292. package/BookReaderDemo/demo-vendor-fullscreen.html +0 -36
  293. package/BookReaderDemo/immersion-1up.html +0 -64
  294. package/BookReaderDemo/immersion-mode.html +0 -35
  295. package/BookReaderDemo/toggle_controls.html +0 -53
  296. package/BookReaderDemo/view_mode.html +0 -39
  297. package/BookReaderDemo/viewmode-cycle.html +0 -41
  298. package/CHANGELOG.md +0 -495
  299. package/CONTRIBUTING.md +0 -7
  300. package/codecov.yml +0 -17
  301. package/index.html +0 -31
  302. package/karma.conf.js +0 -23
  303. package/screenshot.png +0 -0
  304. package/scripts/postversion.js +0 -10
  305. package/scripts/preversion.js +0 -14
  306. package/scripts/version.js +0 -26
  307. package/src/BookNavigator/BookModel.js +0 -14
  308. package/src/BookNavigator/BookNavigator.js +0 -446
  309. package/src/BookNavigator/assets/book-loader.js +0 -27
  310. package/src/BookNavigator/assets/icon_checkmark.js +0 -6
  311. package/src/BookNavigator/assets/icon_close.js +0 -3
  312. package/src/BookNavigator/bookmarks/bookmarks-provider.js +0 -53
  313. package/src/BookNavigator/br-fullscreen-mgr.js +0 -83
  314. package/src/BookNavigator/downloads/downloads-provider.js +0 -66
  315. package/src/BookNavigator/search/a-search-result.js +0 -55
  316. package/src/BookReader/DebugConsole.js +0 -54
  317. package/src/BookReaderComponent/BookReaderComponent.js +0 -112
  318. package/src/ItemNavigator/ItemNavigator.js +0 -376
  319. package/src/ItemNavigator/providers/sharing.js +0 -29
  320. package/src/css/_MobileNav.scss +0 -194
  321. package/src/dragscrollable-br.js +0 -261
  322. package/src/plugins/menu_toggle/plugin.menu_toggle.js +0 -324
  323. package/src/plugins/plugin.mobile_nav.js +0 -287
  324. package/tests/BookReader/BookModel.test.js +0 -312
  325. package/tests/BookReader/BookReaderPublicFunctions.test.js +0 -171
  326. package/tests/BookReader/DebugConsole.test.js +0 -25
  327. package/tests/BookReader/ImageCache.test.js +0 -150
  328. package/tests/BookReader/Mode1Up.test.js +0 -164
  329. package/tests/BookReader/Mode2Up.test.js +0 -247
  330. package/tests/BookReader/Navbar/Navbar.test.js +0 -169
  331. package/tests/BookReader/PageContainer.test.js +0 -115
  332. package/tests/BookReader/ReduceSet.test.js +0 -38
  333. package/tests/BookReader/Toolbar/Toolbar.test.js +0 -26
  334. package/tests/BookReader/utils/classes.test.js +0 -88
  335. package/tests/BookReader/utils.test.js +0 -109
  336. package/tests/BookReader.options.test.js +0 -39
  337. package/tests/BookReader.test.js +0 -301
  338. package/tests/e2e/README.md +0 -75
  339. package/tests/e2e/autoplay.test.js +0 -13
  340. package/tests/e2e/base.test.js +0 -35
  341. package/tests/e2e/helpers/base.js +0 -263
  342. package/tests/e2e/helpers/debug.js +0 -13
  343. package/tests/e2e/helpers/desktopSearch.js +0 -72
  344. package/tests/e2e/helpers/mobileSearch.js +0 -85
  345. package/tests/e2e/helpers/mockSearch.js +0 -93
  346. package/tests/e2e/helpers/rightToLeft.js +0 -29
  347. package/tests/e2e/ia-production/ia-prod-base.js +0 -17
  348. package/tests/e2e/models/BookReader.js +0 -11
  349. package/tests/e2e/models/Navigation.js +0 -56
  350. package/tests/e2e/rightToLeft.test.js +0 -20
  351. package/tests/e2e/viewmode.test.js +0 -37
  352. package/tests/karma/BookNavigator/book-navigator.test.js +0 -132
  353. package/tests/karma/BookNavigator/bookmarks/bookmark-edit.test.js +0 -133
  354. package/tests/karma/BookNavigator/bookmarks/bookmarks-list.test.js +0 -222
  355. package/tests/karma/BookNavigator/search/search-provider.test.js +0 -23
  356. package/tests/karma/BookNavigator/search/search-results.test.js +0 -240
  357. package/tests/karma/BookNavigator/visual-adjustments.test.js +0 -201
  358. package/tests/plugins/menu_toggle/plugin.menu_toggle.test.js +0 -68
  359. package/tests/plugins/plugin.archive_analytics.test.js +0 -23
  360. package/tests/plugins/plugin.autoplay.test.js +0 -52
  361. package/tests/plugins/plugin.chapters.test.js +0 -130
  362. package/tests/plugins/plugin.iframe.test.js +0 -42
  363. package/tests/plugins/plugin.mobile_nav.test.js +0 -66
  364. package/tests/plugins/plugin.resume.test.js +0 -98
  365. package/tests/plugins/plugin.text_selection.test.js +0 -203
  366. package/tests/plugins/plugin.url.test.js +0 -129
  367. package/tests/plugins/plugin.vendor-fullscreen.test.js +0 -65
  368. package/tests/plugins/search/plugin.search.test.js +0 -173
  369. package/tests/plugins/search/plugin.search.view.test.js +0 -106
  370. package/tests/plugins/tts/AbstractTTSEngine.test.js +0 -153
  371. package/tests/plugins/tts/FestivalTTSEngine.test.js +0 -59
  372. package/tests/plugins/tts/PageChunk.test.js +0 -57
  373. package/tests/plugins/tts/PageChunkIterator.test.js +0 -179
  374. package/tests/plugins/tts/WebTTSEngine.test.js +0 -126
  375. package/tests/plugins/tts/utils.test.js +0 -133
  376. package/tests/util/browserSniffing.test.js +0 -56
  377. package/tests/util/docCookies.test.js +0 -15
  378. package/tests/util/strings.test.js +0 -63
  379. package/tests/utils.js +0 -42
  380. package/webpack.config.js +0 -86
@@ -0,0 +1,512 @@
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 { TranslationManager } from "./TranslationManager.js";
6
+ import { toISO6391 } from '../tts/utils.js';
7
+ import { sortBy } from '../../../src/BookReader/utils.js';
8
+ import { TextSelectionManager } from '../../../src/util/TextSelectionManager.js';
9
+ import '@internetarchive/ia-activity-indicator';
10
+
11
+ // @ts-ignore
12
+ const BookReader = /** @type {typeof import('@/src/BookReader.js').default} */(window.BookReader);
13
+
14
+ export class TranslatePlugin extends BookReaderPlugin {
15
+
16
+ options = {
17
+ enabled: true,
18
+
19
+ /** @type {string | import('lit').TemplateResult} */
20
+ panelDisclaimerText: "Translations are in alpha",
21
+ }
22
+
23
+ /** @type {TranslationManager} */
24
+ translationManager = new TranslationManager();
25
+
26
+ /** @type {Worker}*/
27
+ worker;
28
+
29
+ /**
30
+ * Contains the list of languages available to translate to
31
+ * @type {string[]}
32
+ */
33
+ toLanguages = [];
34
+
35
+ /**
36
+ * Current language code that is being translated From. Defaults to EN currently
37
+ * @type {!string}
38
+ */
39
+ langFromCode;
40
+
41
+ /**
42
+ * Current language code that is being translated To
43
+ * @type {!string}
44
+ */
45
+ langToCode;
46
+ /**
47
+ * @type {BrTranslatePanel} _panel - Represents a panel used in the plugin.
48
+ * The specific type and purpose of this panel should be defined based on its usage.
49
+ */
50
+ _panel;
51
+
52
+ /**
53
+ * @type {boolean} userToggleTranslate - Checks if user has initiated translation
54
+ * Should synchronize with the state of TranslationManager's active state
55
+ */
56
+ userToggleTranslate;
57
+
58
+ /**
59
+ * @type {boolean} loadingModel - Shows loading animation while downloading lang model
60
+ */
61
+ loadingModel = true;
62
+
63
+ textSelectionManager = new TextSelectionManager('.BRtranslateLayer', this.br, {selectionElement: [".BRlineElement"]}, 1);
64
+
65
+ async init() {
66
+ const currentLanguage = toISO6391(this.br.options.bookLanguage.replace(/[.,/#!$%^&*;:{}=\-_`~()]/g, ""));
67
+ this.langFromCode = currentLanguage ?? "en";
68
+ this.textSelectionManager.init();
69
+
70
+ if (!this.options.enabled) {
71
+ return;
72
+ }
73
+
74
+ this.translationManager.publicPath = this.br.options.imagesBaseURL.replace(/\/+$/, '') + '/..';
75
+
76
+ /**
77
+ * @param {*} ev
78
+ * @param {object} eventProps
79
+ */
80
+ this.br.on('textLayerRendered', async (_, {pageIndex, pageContainer}) => {
81
+ // Stops invalid models from running, also prevents translation on page load
82
+ // TODO check if model has finished loading or if it exists
83
+ if (!this.translationManager) {
84
+ return;
85
+ }
86
+ if (this.translationManager.active) {
87
+ const pageElement = pageContainer.$container[0];
88
+ this.translateRenderedLayer(pageElement);
89
+ }
90
+ });
91
+
92
+ /**
93
+ * @param {*} ev
94
+ * @param {object} eventProps
95
+ */
96
+ this.br.on('pageVisible', (_, {pageContainerEl}) => {
97
+ if (!this.translationManager.active) {
98
+ return;
99
+ }
100
+ for (const paragraphEl of pageContainerEl.querySelectorAll('.BRtranslateLayer > .BRparagraphElement')) {
101
+ if (paragraphEl.textContent) {
102
+ this.fitVisiblePage(paragraphEl);
103
+ }
104
+ }
105
+ });
106
+
107
+ await this.translationManager.initWorker();
108
+ // Note await above lets _render function properly, since it gives the browser
109
+ // time to render the rest of bookreader, which _render depends on
110
+ this.langToCode = this.translationManager.toLanguages[0].code;
111
+ this._render();
112
+ }
113
+
114
+ /** @param {HTMLElement} page*/
115
+ getParagraphsOnPage = (page) => {
116
+ return page ? Array.from(page.querySelectorAll(".BRtextLayer > .BRparagraphElement")) : [];
117
+ }
118
+
119
+ translateActivePageContainerElements() {
120
+ const currentlyActiveContainers = this.br.getActivePageContainerElements();
121
+ const visiblePageContainers = currentlyActiveContainers.filter((element) => {
122
+ return element.classList.contains('BRpage-visible');
123
+ });
124
+ const hiddenPageContainers = currentlyActiveContainers.filter((element) => {
125
+ return !element.classList.contains('BRpage-visible');
126
+ });
127
+
128
+ for (const page of visiblePageContainers) {
129
+ this.translateRenderedLayer(page, 0);
130
+ }
131
+ for (const loadingPage of hiddenPageContainers) {
132
+ this.translateRenderedLayer(loadingPage, 1000);
133
+ }
134
+ }
135
+
136
+ /** @param {HTMLElement} page */
137
+ async translateRenderedLayer(page, priority) {
138
+ // Do not run translation if in thumbnail mode or if user did not initiate transations
139
+ if (this.br.mode == this.br.constModeThumb || !this.userToggleTranslate || this.langFromCode == this.langToCode) {
140
+ return;
141
+ }
142
+
143
+ const pageIndex = page.dataset.index;
144
+ let pageTranslationLayer;
145
+ if (!page.querySelector('.BRPageLayer.BRtranslateLayer')) {
146
+ pageTranslationLayer = document.createElement('div');
147
+ pageTranslationLayer.classList.add('BRPageLayer', 'BRtranslateLayer', 'BRtranslateLayerLoading');
148
+ pageTranslationLayer.setAttribute('lang', `${this.langToCode}`);
149
+ page.prepend(pageTranslationLayer);
150
+ } else {
151
+ pageTranslationLayer = page.querySelector('.BRPageLayer.BRtranslateLayer');
152
+ }
153
+ /** @type {HTMLElement} textLayerElement */
154
+ const textLayerElement = page.querySelector('.BRtextLayer');
155
+ // Should use native DOM element.style method instead of $().css method, specific issue with rendering / style calculation in Chrome
156
+ $(pageTranslationLayer).css({
157
+ "width": textLayerElement.style.width,
158
+ "height": textLayerElement.style.height,
159
+ "transform": textLayerElement.style.transform,
160
+ "pointer-events": textLayerElement.style.pointerEvents,
161
+ "z-index": 3,
162
+ });
163
+ textLayerElement.classList.add('showingTranslation');
164
+ const paragraphs = this.getParagraphsOnPage(page);
165
+
166
+ const paragraphTranslationPromises = paragraphs.map(async (paragraph, pidx) => {
167
+ let translatedParagraph = page.querySelector(`[data-translate-index='${pageIndex}-${pidx}']`);
168
+ if (!translatedParagraph) {
169
+ translatedParagraph = document.createElement('p');
170
+ // set data-translate-index on the placeholder
171
+ translatedParagraph.setAttribute('data-translate-index', `${pageIndex}-${pidx}`);
172
+ translatedParagraph.className = 'BRparagraphElement';
173
+ const originalParagraphStyle = paragraphs[pidx];
174
+ // check text selection paragraphs for header/footer roles
175
+ if (paragraph.classList.contains('ocr-role-header-footer')) {
176
+ translatedParagraph.ariaHidden = "true";
177
+ translatedParagraph.classList.add('ocr-role-header-footer');
178
+ }
179
+ const fontSize = `${parseInt($(originalParagraphStyle).css("font-size"))}px`;
180
+
181
+ $(translatedParagraph).css({
182
+ "margin-left": $(originalParagraphStyle).css("margin-left"),
183
+ "margin-top": $(originalParagraphStyle).css("margin-top"),
184
+ "top": $(originalParagraphStyle).css("top"),
185
+ "height": $(originalParagraphStyle).css("height"),
186
+ "width": $(originalParagraphStyle).css("width"),
187
+ "font-size": fontSize,
188
+ });
189
+ pageTranslationLayer.append(translatedParagraph);
190
+ }
191
+
192
+ if (paragraph.textContent.length !== 0) {
193
+ const pagePriority = parseFloat(pageIndex) + priority + pidx;
194
+ this.translationManager.getTranslationModel(this.langFromCode, this.langToCode).then(() => {
195
+ this._panel.loadingModel = false;
196
+ this.loadingModel = false;
197
+ });
198
+ const translatedText = await this.translationManager.getTranslation(this.langFromCode, this.langToCode, pageIndex, pidx, paragraph.textContent, pagePriority);
199
+ // prevent duplicate spans from appearing if exists
200
+ translatedParagraph.firstElementChild?.remove();
201
+
202
+ const firstWordSpacing = paragraphs[pidx]?.firstChild?.firstChild;
203
+ const createSpan = document.createElement('span');
204
+ createSpan.className = 'BRlineElement';
205
+ createSpan.textContent = translatedText;
206
+ translatedParagraph.appendChild(createSpan);
207
+
208
+ $(createSpan).css({
209
+ "text-indent": $(firstWordSpacing).css('padding-left'),
210
+ });
211
+ if (page.classList.contains('BRpage-visible')) {
212
+ this.fitVisiblePage(translatedParagraph);
213
+ }
214
+ }
215
+ });
216
+
217
+ this.textSelectionManager?.stopPageFlip(this.br.refs.$brContainer);
218
+ await Promise.all(paragraphTranslationPromises);
219
+ this.br.trigger('translateLayerRendered', {
220
+ leafIndex: pageIndex,
221
+ translateLayer: pageTranslationLayer,
222
+ });
223
+ }
224
+
225
+ /**
226
+ * Get the translation layers for a specific leaf index.
227
+ * @param {number} leafIndex
228
+ * @returns {Promise<HTMLElement[]>}
229
+ */
230
+ async getTranslateLayers(leafIndex) {
231
+ const pageContainerElements = this.br.getActivePageContainerElementsForIndex(leafIndex);
232
+ const translateLayer = $(pageContainerElements).filter(`[data-index='${leafIndex}']`).find('.BRtranslateLayer');
233
+ if (translateLayer.length) return translateLayer.toArray();
234
+
235
+ return new Promise((res, rej) => {
236
+ const handler = async (_, extraParams) => {
237
+ if (extraParams.leafIndex == leafIndex) {
238
+ this.br.off('translateLayerRendered', handler); // remember to detach translateLayer
239
+ res([extraParams.translateLayer]);
240
+ }
241
+ };
242
+ this.br.on('translateLayerRendered', handler);
243
+ });
244
+ }
245
+
246
+ clearAllTranslations() {
247
+ document.querySelectorAll('.BRtranslateLayer').forEach(el => el.remove());
248
+ document.querySelectorAll('.showingTranslation').forEach(el => el.classList.remove('showingTranslation'));
249
+ }
250
+
251
+ /**
252
+ * @param {Element} paragEl
253
+ */
254
+ fitVisiblePage(paragEl) {
255
+ const originalFontSize = parseInt($(paragEl).css("font-size"));
256
+ let adjustedFontSize = originalFontSize;
257
+ while (paragEl.clientHeight < paragEl.scrollHeight && adjustedFontSize > 0) {
258
+ adjustedFontSize--;
259
+ $(paragEl).css({ "font-size": `${adjustedFontSize}px` });
260
+ }
261
+
262
+ const textHeight = paragEl.firstElementChild.clientHeight;
263
+ const scrollHeight = paragEl.scrollHeight;
264
+ const fits = textHeight < scrollHeight;
265
+ if (fits) {
266
+ const lines = textHeight / adjustedFontSize;
267
+ // Line heights for smaller paragraphs occasionally need a minor adjustment
268
+ const newLineHeight = scrollHeight / lines;
269
+ $(paragEl).css({
270
+ "line-height" : `${newLineHeight}px`,
271
+ "overflow": "visible",
272
+ });
273
+ }
274
+ }
275
+
276
+ handleFromLangChange = async (e) => {
277
+ this.clearAllTranslations();
278
+ const selectedLangFrom = e.detail.value;
279
+
280
+ // Update the from language
281
+ this.langFromCode = selectedLangFrom;
282
+ this._panel.requestUpdate();
283
+
284
+ // Add 'From' language to 'To' list if not already present
285
+ if (!this.translationManager.toLanguages.some(lang => lang.code === selectedLangFrom)) {
286
+ this.translationManager.toLanguages.push({
287
+ code: selectedLangFrom,
288
+ name: this.translationManager.fromLanguages.find((entry) => entry.code == selectedLangFrom).name,
289
+ });
290
+ }
291
+
292
+ // Update the 'To' languages list and set the correct 'To' language
293
+ this._panel.toLanguages = this.translationManager.toLanguages;
294
+
295
+ console.log(this.langFromCode, this.langToCode);
296
+ this._render();
297
+ if (this.langFromCode !== this.langToCode) {
298
+ this.translateActivePageContainerElements();
299
+ }
300
+ }
301
+
302
+ handleToLangChange = async (e) => {
303
+ this.clearAllTranslations();
304
+ this.langToCode = e.detail.value;
305
+ this._render();
306
+ this.translateActivePageContainerElements();
307
+ }
308
+
309
+ handleToggleTranslation = async () => {
310
+ this.userToggleTranslate = !this.userToggleTranslate;
311
+ this.translationManager.active = this.userToggleTranslate;
312
+
313
+ this._render();
314
+ if (!this.userToggleTranslate) {
315
+ this.clearAllTranslations();
316
+ this.br.trigger('translationDisabled', { });
317
+ this.textSelectionManager.detach();
318
+ } else {
319
+ this.br.trigger('translationEnabled', { });
320
+ this.translateActivePageContainerElements();
321
+ this.textSelectionManager.attach();
322
+ }
323
+ }
324
+
325
+ /**
326
+ * Update translation side menu
327
+ */
328
+ _render() {
329
+ this.br.shell.menuProviders['translate'] = {
330
+ id: 'translate',
331
+ icon: html`<img src='${this.br.options.imagesBaseURL}/translate.svg' width="26"/>`,
332
+ label: 'Translate',
333
+ component: html`<br-translate-panel
334
+ @connected="${e => {
335
+ this._panel = e.target;
336
+ this._panel.fromLanguages = this.translationManager.fromLanguages;
337
+ this._panel.toLanguages = this.translationManager.toLanguages;
338
+ this._panel.userTranslationActive = this.userToggleTranslate;
339
+ this._panel.detectedToLang = this.langToCode;
340
+ this._panel.detectedFromLang = this.langFromCode;
341
+ this._panel.loadingModel = this.loadingModel;
342
+ }
343
+ }"
344
+ @langFromChanged="${this.handleFromLangChange}"
345
+ @langToChanged="${this.handleToLangChange}"
346
+ @toggleTranslation="${this.handleToggleTranslation}"
347
+ .fromLanguages="${this.translationManager.fromLanguages}"
348
+ .toLanguages="${this.translationManager.toLanguages}"
349
+ .disclaimerMessage="${this.options.panelDisclaimerText}"
350
+ .userTranslationActive=${this.userToggleTranslate}
351
+ .detectedFromLang=${this.langFromCode}
352
+ .detectedToLang=${this.langToCode}
353
+ .loadingModel=${this.loadingModel}
354
+ class="translate-panel"
355
+ />`,
356
+ };
357
+ this.br.shell.updateMenuContents();
358
+ }
359
+ }
360
+ BookReader?.registerPlugin('translate', TranslatePlugin);
361
+
362
+ @customElement('br-translate-panel')
363
+ export class BrTranslatePanel extends LitElement {
364
+ @property({ type: Array }) fromLanguages = []; // List of obj {code, name}
365
+ @property({ type: Array }) toLanguages = []; // List of obj {code, name}
366
+ @property({ type: String }) prevSelectedLang = ''; // Tracks the previous selected language for the "To" dropdown
367
+ @property({ type: String }) disclaimerMessage = '';
368
+ @property({ type: Boolean }) userTranslationActive = false;
369
+ @property({ type: String }) detectedFromLang = '';
370
+ @property({ type: String }) detectedToLang = '';
371
+ @property({ type: Boolean }) loadingModel;
372
+
373
+ /** @override */
374
+ createRenderRoot() {
375
+ // Disable shadow DOM; that would require a huge rejiggering of CSS
376
+ return this;
377
+ }
378
+
379
+ connectedCallback() {
380
+ super.connectedCallback();
381
+ this.dispatchEvent(new CustomEvent('connected'));
382
+ }
383
+
384
+ render() {
385
+ return html`<div class="app" style="margin-top: 5%;padding-right: 5px;">
386
+ <div
387
+ class="disclaimer"
388
+ id="disclaimerMessage"
389
+ style="background-color: rgba(255,255,255,0.1);padding: 10px;border-radius: 8px;font-size: 12px;margin-bottom: 10px;color: rgba(255,255,255, 0.9);"
390
+ >${this.disclaimerMessage}</div>
391
+
392
+ <div class="panel panel--to" style="padding: 0 10px;">
393
+ <label>
394
+ <span style="font-size: 12px;color: #ccc;">Translate To</span>
395
+ <select id="lang-to" name="to" class="lang-select" style="display:block; width:100%;" @change="${this._onLangToChange}">
396
+ ${sortBy(this.toLanguages, ((lang) => lang.name.toLowerCase()
397
+ )).map((lang) => {
398
+ return html`<option value="${lang.code}"
399
+ ?selected=${lang.code == this.detectedToLang}
400
+ > ${lang.name ? lang.name : lang.code} </option>`;
401
+ })
402
+ }
403
+ </select>
404
+ </label>
405
+ </div>
406
+
407
+ <div class="panel panel--start" style="text-align: right;padding: 0 10px;/*! font-size: 18px; */margin-top: 10px;">
408
+ <button class="start-translation-brn" @click="${this._toggleTranslation}">
409
+ ${this.userTranslationActive ? "Stop Translating" : "Translate"}
410
+ </button>
411
+ </div>
412
+
413
+ <div class="panel panel--from" style="font-size: 12px;color: #ccc;text-align: center;padding: 8px 10px;">
414
+ <details style="display: contents">
415
+ <summary style="text-decoration: underline white; cursor:pointer; display:inline-block">
416
+ <i>
417
+ Source: ${this._getLangName(this.detectedFromLang)} ${this.prevSelectedLang ? "" : "(detected)"}
418
+ </i> Change
419
+ </summary>
420
+ <select id="lang-from" name="from" class="lang-select" value=${this.detectedFromLang} @change="${this._onLangFromChange}" style="width:65%; margin-top: 3%; margin-bottom: 3%">
421
+ ${sortBy(this.fromLanguages, ((lang) => lang.name.toLowerCase()
422
+ )).map((lang) => {
423
+ return html`<option value="${lang.code}"
424
+ ?selected=${lang.code == this.detectedFromLang}
425
+ >${lang.name ? lang.name : lang.code} </option>`;
426
+ })
427
+ }
428
+ </select>
429
+ </details>
430
+ <div class="footer" id="status" style="margin-top:5%">
431
+ ${this._statusWarning()}
432
+ </div>
433
+
434
+ <div class="lang-models-loading">
435
+ ${this._languageModelStatus()}
436
+ </div>
437
+ </div>`;
438
+ }
439
+ _onLangFromChange(event) {
440
+ const langFromChangedEvent = new CustomEvent('langFromChanged', {
441
+ detail: { value: event.target.value },
442
+ bubbles: true,
443
+ composed: true,
444
+ });
445
+ this.dispatchEvent(langFromChangedEvent);
446
+
447
+ // Update the prevSelectedLang if "To" is different from "From"
448
+ if (this._getSelectedLang('to') !== this._getSelectedLang('from')) {
449
+ this.prevSelectedLang = this._getSelectedLang('from');
450
+ }
451
+ this.loadingModel = true;
452
+ this.detectedFromLang = event.target.value;
453
+ }
454
+
455
+ _onLangToChange(event) {
456
+ const langToChangedEvent = new CustomEvent('langToChanged', {
457
+ detail: { value: event.target.value },
458
+ bubbles: true,
459
+ composed: true,
460
+ });
461
+ this.dispatchEvent(langToChangedEvent);
462
+
463
+ // Update the prevSelectedLang if "To" is different from "From"
464
+ if (this._getSelectedLang('from') !== event.target.value) {
465
+ this.prevSelectedLang = this._getSelectedLang('from');
466
+ }
467
+ this.loadingModel = true;
468
+ this.detectedToLang = event.target.value;
469
+ }
470
+
471
+ _getSelectedLang(type) {
472
+ /** @type {HTMLSelectElement} */
473
+ const dropdown = this.querySelector(`#lang-${type}`);
474
+ return dropdown ? dropdown.value : '';
475
+ }
476
+
477
+ _getLangName(code) {
478
+ const lang = [...this.fromLanguages, ...this.toLanguages].find(lang => lang.code === code);
479
+ return lang ? lang.name : '';
480
+ }
481
+
482
+ _toggleTranslation(event) {
483
+ const toggleTranslateEvent = new CustomEvent('toggleTranslation', {
484
+ detail: {value: event.target.value},
485
+ bubbles: true,
486
+ composed:true,
487
+ });
488
+ this.userTranslationActive = !this.userTranslationActive;
489
+ this.dispatchEvent(toggleTranslateEvent);
490
+ }
491
+
492
+ // TODO: Hardcoded warning message for now but should add more statuses
493
+ _statusWarning() {
494
+ if (this.detectedFromLang == this.detectedToLang) {
495
+ return "Translate To language is the same as the Source language";
496
+ }
497
+ return "";
498
+ }
499
+
500
+ _languageModelStatus() {
501
+ if (this.userTranslationActive) {
502
+ if (this.loadingModel) {
503
+ return html`
504
+ <ia-activity-indicator mode="processing" style="display:block; width: 40px; height: 40px; margin: 0 auto;"></ia-activity-indicator>
505
+ <p>Downloading language model</p>
506
+ `;
507
+ }
508
+ return html`<p>Language model loaded</p>`;
509
+ }
510
+ return "";
511
+ }
512
+ }