@internetarchive/bookreader 5.0.0-11 → 5.0.0-111

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 (381) hide show
  1. package/BookReader/474.js +2 -0
  2. package/BookReader/474.js.map +1 -0
  3. package/BookReader/BookReader.css +649 -1225
  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 +1904 -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 +24 -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 +159 -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 +2 -1
  136. package/BookReader/plugins/plugin.url.js.LICENSE.txt +1 -0
  137. package/BookReader/plugins/plugin.url.js.map +1 -1
  138. package/BookReader/plugins/plugin.vendor-fullscreen.js +1 -1
  139. package/BookReader/plugins/plugin.vendor-fullscreen.js.map +1 -1
  140. package/BookReader/plugins/translator-worker.js +2 -0
  141. package/BookReader/plugins/translator-worker.js.map +1 -0
  142. package/BookReader/silence.mp3 +0 -0
  143. package/BookReader/translator-worker.js +475 -0
  144. package/BookReader/webcomponents-bundle.js +3 -0
  145. package/BookReader/webcomponents-bundle.js.LICENSE.txt +9 -0
  146. package/BookReader/webcomponents-bundle.js.map +1 -0
  147. package/README.md +14 -3
  148. package/jsconfig.json +19 -0
  149. package/package.json +93 -70
  150. package/src/BookReader/BookModel.js +92 -46
  151. package/src/BookReader/DragScrollable.js +233 -0
  152. package/src/BookReader/ImageCache.js +49 -16
  153. package/src/BookReader/Mode1Up.js +66 -365
  154. package/src/BookReader/Mode1UpLit.js +392 -0
  155. package/src/BookReader/Mode2Up.js +87 -1315
  156. package/src/BookReader/Mode2UpLit.js +786 -0
  157. package/src/BookReader/ModeAbstract.js +43 -0
  158. package/src/BookReader/ModeCoordinateSpace.js +29 -0
  159. package/src/BookReader/ModeSmoothZoom.js +312 -0
  160. package/src/BookReader/ModeThumb.js +29 -15
  161. package/src/BookReader/Navbar/Navbar.js +201 -76
  162. package/src/BookReader/PageContainer.js +120 -23
  163. package/src/BookReader/ReduceSet.js +2 -2
  164. package/src/BookReader/Toolbar/Toolbar.js +18 -40
  165. package/src/BookReader/events.js +3 -3
  166. package/src/BookReader/options.js +94 -17
  167. package/src/BookReader/utils/HTMLDimensionsCacher.js +44 -0
  168. package/src/BookReader/utils/ScrollClassAdder.js +31 -0
  169. package/src/BookReader/utils/SelectionObserver.js +53 -0
  170. package/src/BookReader/utils/classes.js +1 -1
  171. package/src/BookReader/utils.js +136 -12
  172. package/src/BookReader.js +695 -1228
  173. package/src/BookReaderPlugin.js +52 -0
  174. package/src/assets/icons/magnify-minus.svg +3 -7
  175. package/src/assets/icons/magnify-plus.svg +3 -7
  176. package/src/assets/icons/slider-toggle.svg +1 -0
  177. package/src/assets/icons/voice.svg +1 -0
  178. package/src/assets/images/hypothesis.ico +0 -0
  179. package/src/assets/images/icon_experiment.svg +1 -0
  180. package/src/assets/images/translate.svg +1 -0
  181. package/src/assets/images/unviewable_page.png +0 -0
  182. package/src/assets/silence.mp3 +0 -0
  183. package/src/css/BookReader.scss +1 -5
  184. package/src/css/_BRBookmarks.scss +1 -1
  185. package/src/css/_BRComponent.scss +1 -1
  186. package/src/css/_BRicon.scss +8 -2
  187. package/src/css/_BRmain.scss +16 -3
  188. package/src/css/_BRnav.scss +74 -70
  189. package/src/css/_BRpages.scss +171 -42
  190. package/src/css/_BRsearch.scss +69 -30
  191. package/src/css/_BRtoolbar.scss +5 -5
  192. package/src/css/_TextSelection.scss +188 -24
  193. package/src/css/_colorbox.scss +2 -2
  194. package/src/css/_controls.scss +24 -7
  195. package/src/css/_icons.scss +8 -1
  196. package/src/{BookNavigator/assets → css}/button-base.js +2 -2
  197. package/src/css/icon_checkmark.js +9 -0
  198. package/src/css/sharedStyles.js +15 -0
  199. package/src/ia-bookreader/downloads/downloads-provider.js +81 -0
  200. package/src/{BookNavigator → ia-bookreader}/downloads/downloads.js +25 -5
  201. package/src/ia-bookreader/ia-bookreader.js +666 -0
  202. package/src/ia-bookreader/sharing.js +27 -0
  203. package/src/ia-bookreader/viewable-files.js +98 -0
  204. package/src/{BookNavigator → ia-bookreader}/visual-adjustments/visual-adjustments-provider.js +17 -17
  205. package/src/{BookNavigator → ia-bookreader}/visual-adjustments/visual-adjustments.js +75 -67
  206. package/src/{BookNavigator → plugins}/bookmarks/bookmark-button.js +4 -3
  207. package/src/{BookNavigator/assets → plugins/bookmarks}/bookmark-colors.js +1 -1
  208. package/src/{BookNavigator → plugins}/bookmarks/bookmark-edit.js +43 -31
  209. package/src/{BookNavigator → plugins}/bookmarks/bookmarks-list.js +48 -49
  210. package/src/{BookNavigator → plugins}/bookmarks/bookmarks-loginCTA.js +3 -3
  211. package/src/plugins/bookmarks/bookmarks-provider.js +63 -0
  212. package/src/{BookNavigator → plugins/bookmarks}/delete-modal-actions.js +1 -1
  213. package/src/{BookNavigator → plugins}/bookmarks/ia-bookmarks.js +117 -68
  214. package/src/plugins/plugin.archive_analytics.js +84 -78
  215. package/src/plugins/plugin.autoplay.js +99 -104
  216. package/src/plugins/plugin.chapters.js +319 -205
  217. package/src/plugins/plugin.experiments.js +339 -0
  218. package/src/plugins/plugin.iframe.js +1 -1
  219. package/src/plugins/plugin.iiif.js +141 -0
  220. package/src/plugins/plugin.resume.js +54 -51
  221. package/src/plugins/plugin.text_selection.js +539 -219
  222. package/src/plugins/plugin.vendor-fullscreen.js +5 -5
  223. package/src/plugins/search/plugin.search.js +374 -392
  224. package/src/{BookNavigator → plugins}/search/search-provider.js +59 -27
  225. package/src/{BookNavigator → plugins}/search/search-results.js +105 -76
  226. package/src/plugins/search/utils.js +50 -0
  227. package/src/plugins/search/view.js +50 -68
  228. package/src/plugins/translate/TranslationManager.js +164 -0
  229. package/src/plugins/translate/plugin.translate.js +512 -0
  230. package/src/plugins/tts/AbstractTTSEngine.js +78 -49
  231. package/src/plugins/tts/FestivalTTSEngine.js +20 -30
  232. package/src/plugins/tts/PageChunk.js +33 -21
  233. package/src/plugins/tts/PageChunkIterator.js +11 -17
  234. package/src/plugins/tts/WebTTSEngine.js +131 -91
  235. package/src/plugins/tts/plugin.tts.js +345 -350
  236. package/src/plugins/tts/utils.js +77 -49
  237. package/src/plugins/url/UrlPlugin.js +211 -0
  238. package/src/plugins/{plugin.url.js → url/plugin.url.js} +105 -20
  239. package/src/util/TextSelectionManager.js +532 -0
  240. package/src/util/browserSniffing.js +33 -1
  241. package/src/util/cache.js +20 -0
  242. package/src/util/docCookies.js +21 -2
  243. package/src/util/lit.js +15 -0
  244. package/src/util/strings.js +1 -0
  245. package/.babelrc +0 -12
  246. package/.dependabot/config.yml +0 -6
  247. package/.eslintrc.js +0 -50
  248. package/.gitattributes +0 -2
  249. package/.github/ISSUE_TEMPLATE/bug.md +0 -32
  250. package/.github/ISSUE_TEMPLATE/feature-request.md +0 -30
  251. package/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md +0 -15
  252. package/.github/workflows/node.js.yml +0 -37
  253. package/.github/workflows/npm-publish.yml +0 -47
  254. package/.testcaferc.json +0 -5
  255. package/BookReader/bookreader-component-bundle.js +0 -1450
  256. package/BookReader/bookreader-component-bundle.js.LICENSE.txt +0 -38
  257. package/BookReader/bookreader-component-bundle.js.map +0 -1
  258. package/BookReader/jquery-1.10.1.js +0 -2
  259. package/BookReader/jquery-1.10.1.js.LICENSE.txt +0 -24
  260. package/BookReader/plugins/plugin.menu_toggle.js +0 -2
  261. package/BookReader/plugins/plugin.menu_toggle.js.map +0 -1
  262. package/BookReader/plugins/plugin.mobile_nav.js +0 -2
  263. package/BookReader/plugins/plugin.mobile_nav.js.map +0 -1
  264. package/BookReaderDemo/BookReaderDemo.css +0 -41
  265. package/BookReaderDemo/BookReaderJSAdvanced.js +0 -115
  266. package/BookReaderDemo/BookReaderJSAutoplay.js +0 -56
  267. package/BookReaderDemo/BookReaderJSSimple.js +0 -55
  268. package/BookReaderDemo/IIIFBookReader.js +0 -207
  269. package/BookReaderDemo/assets/v5/Bookreader-logo-cool-grad.svg +0 -1
  270. package/BookReaderDemo/assets/v5/Bookreader-logo-flat.svg +0 -1
  271. package/BookReaderDemo/assets/v5/Bookreader-logo-hex-cool-grad.png +0 -0
  272. package/BookReaderDemo/assets/v5/Bookreader-logo-hex-flat.png +0 -0
  273. package/BookReaderDemo/assets/v5/Bookreader-logo-lines.png +0 -0
  274. package/BookReaderDemo/assets/v5/Bookreader-logo-lines.svg +0 -1
  275. package/BookReaderDemo/assets/v5/Bookreader-logo-warm.svg +0 -1
  276. package/BookReaderDemo/assets/v5/bookreader-logo-renders@1x.png +0 -0
  277. package/BookReaderDemo/assets/v5/bookreader-logo-renders@2x.png +0 -0
  278. package/BookReaderDemo/assets/v5/bookreader-v5-screenshot.png +0 -0
  279. package/BookReaderDemo/bookreader-template-bundle.js +0 -7178
  280. package/BookReaderDemo/demo-advanced.html +0 -33
  281. package/BookReaderDemo/demo-autoplay.html +0 -38
  282. package/BookReaderDemo/demo-embed-iframe-src.html +0 -84
  283. package/BookReaderDemo/demo-embed.html +0 -26
  284. package/BookReaderDemo/demo-fullscreen-mobile.html +0 -36
  285. package/BookReaderDemo/demo-fullscreen.html +0 -33
  286. package/BookReaderDemo/demo-iiif.html +0 -34
  287. package/BookReaderDemo/demo-iiif.js +0 -26
  288. package/BookReaderDemo/demo-internetarchive.html +0 -74
  289. package/BookReaderDemo/demo-multiple.html +0 -43
  290. package/BookReaderDemo/demo-plugin-menu-toggle.html +0 -34
  291. package/BookReaderDemo/demo-preview-pages.html +0 -1092
  292. package/BookReaderDemo/demo-simple.html +0 -34
  293. package/BookReaderDemo/demo-vendor-fullscreen.html +0 -36
  294. package/BookReaderDemo/immersion-1up.html +0 -64
  295. package/BookReaderDemo/immersion-mode.html +0 -35
  296. package/BookReaderDemo/toggle_controls.html +0 -53
  297. package/BookReaderDemo/view_mode.html +0 -39
  298. package/BookReaderDemo/viewmode-cycle.html +0 -41
  299. package/CHANGELOG.md +0 -495
  300. package/CONTRIBUTING.md +0 -7
  301. package/codecov.yml +0 -17
  302. package/index.html +0 -31
  303. package/karma.conf.js +0 -23
  304. package/screenshot.png +0 -0
  305. package/scripts/postversion.js +0 -10
  306. package/scripts/preversion.js +0 -14
  307. package/scripts/version.js +0 -26
  308. package/src/BookNavigator/BookModel.js +0 -14
  309. package/src/BookNavigator/BookNavigator.js +0 -446
  310. package/src/BookNavigator/assets/book-loader.js +0 -27
  311. package/src/BookNavigator/assets/icon_checkmark.js +0 -6
  312. package/src/BookNavigator/assets/icon_close.js +0 -3
  313. package/src/BookNavigator/bookmarks/bookmarks-provider.js +0 -53
  314. package/src/BookNavigator/br-fullscreen-mgr.js +0 -83
  315. package/src/BookNavigator/downloads/downloads-provider.js +0 -66
  316. package/src/BookNavigator/search/a-search-result.js +0 -55
  317. package/src/BookReader/DebugConsole.js +0 -54
  318. package/src/BookReaderComponent/BookReaderComponent.js +0 -112
  319. package/src/ItemNavigator/ItemNavigator.js +0 -376
  320. package/src/ItemNavigator/providers/sharing.js +0 -29
  321. package/src/css/_MobileNav.scss +0 -194
  322. package/src/dragscrollable-br.js +0 -261
  323. package/src/plugins/menu_toggle/plugin.menu_toggle.js +0 -324
  324. package/src/plugins/plugin.mobile_nav.js +0 -287
  325. package/tests/BookReader/BookModel.test.js +0 -312
  326. package/tests/BookReader/BookReaderPublicFunctions.test.js +0 -171
  327. package/tests/BookReader/DebugConsole.test.js +0 -25
  328. package/tests/BookReader/ImageCache.test.js +0 -150
  329. package/tests/BookReader/Mode1Up.test.js +0 -164
  330. package/tests/BookReader/Mode2Up.test.js +0 -247
  331. package/tests/BookReader/Navbar/Navbar.test.js +0 -169
  332. package/tests/BookReader/PageContainer.test.js +0 -115
  333. package/tests/BookReader/ReduceSet.test.js +0 -38
  334. package/tests/BookReader/Toolbar/Toolbar.test.js +0 -26
  335. package/tests/BookReader/utils/classes.test.js +0 -88
  336. package/tests/BookReader/utils.test.js +0 -109
  337. package/tests/BookReader.options.test.js +0 -39
  338. package/tests/BookReader.test.js +0 -301
  339. package/tests/e2e/README.md +0 -75
  340. package/tests/e2e/autoplay.test.js +0 -13
  341. package/tests/e2e/base.test.js +0 -35
  342. package/tests/e2e/helpers/base.js +0 -263
  343. package/tests/e2e/helpers/debug.js +0 -13
  344. package/tests/e2e/helpers/desktopSearch.js +0 -72
  345. package/tests/e2e/helpers/mobileSearch.js +0 -85
  346. package/tests/e2e/helpers/mockSearch.js +0 -93
  347. package/tests/e2e/helpers/rightToLeft.js +0 -29
  348. package/tests/e2e/ia-production/ia-prod-base.js +0 -17
  349. package/tests/e2e/models/BookReader.js +0 -11
  350. package/tests/e2e/models/Navigation.js +0 -56
  351. package/tests/e2e/rightToLeft.test.js +0 -20
  352. package/tests/e2e/viewmode.test.js +0 -37
  353. package/tests/karma/BookNavigator/book-navigator.test.js +0 -132
  354. package/tests/karma/BookNavigator/bookmarks/bookmark-edit.test.js +0 -133
  355. package/tests/karma/BookNavigator/bookmarks/bookmarks-list.test.js +0 -222
  356. package/tests/karma/BookNavigator/search/search-provider.test.js +0 -23
  357. package/tests/karma/BookNavigator/search/search-results.test.js +0 -240
  358. package/tests/karma/BookNavigator/visual-adjustments.test.js +0 -201
  359. package/tests/plugins/menu_toggle/plugin.menu_toggle.test.js +0 -68
  360. package/tests/plugins/plugin.archive_analytics.test.js +0 -23
  361. package/tests/plugins/plugin.autoplay.test.js +0 -52
  362. package/tests/plugins/plugin.chapters.test.js +0 -130
  363. package/tests/plugins/plugin.iframe.test.js +0 -42
  364. package/tests/plugins/plugin.mobile_nav.test.js +0 -66
  365. package/tests/plugins/plugin.resume.test.js +0 -98
  366. package/tests/plugins/plugin.text_selection.test.js +0 -203
  367. package/tests/plugins/plugin.url.test.js +0 -129
  368. package/tests/plugins/plugin.vendor-fullscreen.test.js +0 -65
  369. package/tests/plugins/search/plugin.search.test.js +0 -173
  370. package/tests/plugins/search/plugin.search.view.test.js +0 -106
  371. package/tests/plugins/tts/AbstractTTSEngine.test.js +0 -153
  372. package/tests/plugins/tts/FestivalTTSEngine.test.js +0 -59
  373. package/tests/plugins/tts/PageChunk.test.js +0 -57
  374. package/tests/plugins/tts/PageChunkIterator.test.js +0 -179
  375. package/tests/plugins/tts/WebTTSEngine.test.js +0 -126
  376. package/tests/plugins/tts/utils.test.js +0 -133
  377. package/tests/util/browserSniffing.test.js +0 -56
  378. package/tests/util/docCookies.test.js +0 -15
  379. package/tests/util/strings.test.js +0 -63
  380. package/tests/utils.js +0 -42
  381. 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
+ }