@internetarchive/bookreader 5.0.0-18

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 (428) hide show
  1. package/.eslintrc.js +58 -0
  2. package/.gitattributes +2 -0
  3. package/.github/ISSUE_TEMPLATE/bug.md +32 -0
  4. package/.github/ISSUE_TEMPLATE/feature-request.md +30 -0
  5. package/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md +15 -0
  6. package/.github/dependabot.yml +8 -0
  7. package/.github/workflows/node.js.yml +37 -0
  8. package/.github/workflows/npm-publish.yml +47 -0
  9. package/.testcaferc.json +5 -0
  10. package/BookReader/BookReader.css +2983 -0
  11. package/BookReader/BookReader.js +3 -0
  12. package/BookReader/BookReader.js.LICENSE.txt +117 -0
  13. package/BookReader/BookReader.js.map +1 -0
  14. package/BookReader/bookreader-component-bundle.js +1436 -0
  15. package/BookReader/bookreader-component-bundle.js.LICENSE.txt +27 -0
  16. package/BookReader/bookreader-component-bundle.js.map +1 -0
  17. package/BookReader/icons/1up.svg +1 -0
  18. package/BookReader/icons/2up.svg +1 -0
  19. package/BookReader/icons/advance.svg +3 -0
  20. package/BookReader/icons/chevron-right.svg +1 -0
  21. package/BookReader/icons/close-circle-dark.svg +1 -0
  22. package/BookReader/icons/close-circle.svg +1 -0
  23. package/BookReader/icons/fullscreen.svg +1 -0
  24. package/BookReader/icons/fullscreen_exit.svg +1 -0
  25. package/BookReader/icons/hamburger.svg +1 -0
  26. package/BookReader/icons/left-arrow.svg +1 -0
  27. package/BookReader/icons/magnify-minus.svg +1 -0
  28. package/BookReader/icons/magnify-plus.svg +1 -0
  29. package/BookReader/icons/magnify.svg +1 -0
  30. package/BookReader/icons/pause.svg +1 -0
  31. package/BookReader/icons/play.svg +1 -0
  32. package/BookReader/icons/playback-speed.svg +1 -0
  33. package/BookReader/icons/read-aloud.svg +1 -0
  34. package/BookReader/icons/review.svg +3 -0
  35. package/BookReader/icons/thumbnails.svg +1 -0
  36. package/BookReader/icons/volume-full.svg +1 -0
  37. package/BookReader/images/BRicons.png +0 -0
  38. package/BookReader/images/BRicons.svg +5 -0
  39. package/BookReader/images/BRicons_ia.png +0 -0
  40. package/BookReader/images/back_pages.png +0 -0
  41. package/BookReader/images/book_bottom_icon.png +0 -0
  42. package/BookReader/images/book_down_icon.png +0 -0
  43. package/BookReader/images/book_left_icon.png +0 -0
  44. package/BookReader/images/book_leftmost_icon.png +0 -0
  45. package/BookReader/images/book_right_icon.png +0 -0
  46. package/BookReader/images/book_rightmost_icon.png +0 -0
  47. package/BookReader/images/book_top_icon.png +0 -0
  48. package/BookReader/images/book_up_icon.png +0 -0
  49. package/BookReader/images/books_graphic.svg +1 -0
  50. package/BookReader/images/booksplit.png +0 -0
  51. package/BookReader/images/control_pause_icon.png +0 -0
  52. package/BookReader/images/control_play_icon.png +0 -0
  53. package/BookReader/images/embed_icon.png +0 -0
  54. package/BookReader/images/icon-home-ia.png +0 -0
  55. package/BookReader/images/icon_OL-logo-xs.png +0 -0
  56. package/BookReader/images/icon_alert-xs.png +0 -0
  57. package/BookReader/images/icon_book.svg +1 -0
  58. package/BookReader/images/icon_bookmark.svg +1 -0
  59. package/BookReader/images/icon_close-pop.png +0 -0
  60. package/BookReader/images/icon_download.png +0 -0
  61. package/BookReader/images/icon_gear.svg +1 -0
  62. package/BookReader/images/icon_hamburger.svg +1 -0
  63. package/BookReader/images/icon_home.png +0 -0
  64. package/BookReader/images/icon_home.svg +1 -0
  65. package/BookReader/images/icon_home_ia.png +0 -0
  66. package/BookReader/images/icon_indicator.png +0 -0
  67. package/BookReader/images/icon_info.svg +1 -0
  68. package/BookReader/images/icon_one_page.svg +1 -0
  69. package/BookReader/images/icon_pause.svg +1 -0
  70. package/BookReader/images/icon_play.svg +1 -0
  71. package/BookReader/images/icon_playback-rate.svg +1 -0
  72. package/BookReader/images/icon_return.png +0 -0
  73. package/BookReader/images/icon_search_button.svg +1 -0
  74. package/BookReader/images/icon_share.svg +1 -0
  75. package/BookReader/images/icon_skip-ahead.svg +1 -0
  76. package/BookReader/images/icon_skip-back.svg +2 -0
  77. package/BookReader/images/icon_speaker.svg +1 -0
  78. package/BookReader/images/icon_speaker_open.svg +1 -0
  79. package/BookReader/images/icon_thumbnails.svg +1 -0
  80. package/BookReader/images/icon_toc.svg +1 -0
  81. package/BookReader/images/icon_two_pages.svg +1 -0
  82. package/BookReader/images/icon_zoomer.png +0 -0
  83. package/BookReader/images/loading.gif +0 -0
  84. package/BookReader/images/logo_icon.png +0 -0
  85. package/BookReader/images/marker_chap-off.png +0 -0
  86. package/BookReader/images/marker_chap-off.svg +1 -0
  87. package/BookReader/images/marker_chap-off_ia.png +0 -0
  88. package/BookReader/images/marker_chap-on.png +0 -0
  89. package/BookReader/images/marker_chap-on.svg +1 -0
  90. package/BookReader/images/marker_srch-on.svg +1 -0
  91. package/BookReader/images/marker_srchchap-off.png +0 -0
  92. package/BookReader/images/marker_srchchap-on.png +0 -0
  93. package/BookReader/images/nav_control-dn.png +0 -0
  94. package/BookReader/images/nav_control-dn_ia.png +0 -0
  95. package/BookReader/images/nav_control-up.png +0 -0
  96. package/BookReader/images/nav_control-up_ia.png +0 -0
  97. package/BookReader/images/nav_control.png +0 -0
  98. package/BookReader/images/one_page_mode_icon.png +0 -0
  99. package/BookReader/images/paper-badge.png +0 -0
  100. package/BookReader/images/print_icon.png +0 -0
  101. package/BookReader/images/progressbar.gif +0 -0
  102. package/BookReader/images/right_edges.png +0 -0
  103. package/BookReader/images/slider.png +0 -0
  104. package/BookReader/images/slider_ia.png +0 -0
  105. package/BookReader/images/thumbnail_mode_icon.png +0 -0
  106. package/BookReader/images/transparent.png +0 -0
  107. package/BookReader/images/two_page_mode_icon.png +0 -0
  108. package/BookReader/images/zoom_in_icon.png +0 -0
  109. package/BookReader/images/zoom_out_icon.png +0 -0
  110. package/BookReader/jquery-1.10.1.js +2 -0
  111. package/BookReader/jquery-1.10.1.js.LICENSE.txt +24 -0
  112. package/BookReader/plugins/plugin.archive_analytics.js +2 -0
  113. package/BookReader/plugins/plugin.archive_analytics.js.map +1 -0
  114. package/BookReader/plugins/plugin.autoplay.js +2 -0
  115. package/BookReader/plugins/plugin.autoplay.js.map +1 -0
  116. package/BookReader/plugins/plugin.chapters.js +2 -0
  117. package/BookReader/plugins/plugin.chapters.js.map +1 -0
  118. package/BookReader/plugins/plugin.iframe.js +2 -0
  119. package/BookReader/plugins/plugin.iframe.js.map +1 -0
  120. package/BookReader/plugins/plugin.mobile_nav.js +2 -0
  121. package/BookReader/plugins/plugin.mobile_nav.js.map +1 -0
  122. package/BookReader/plugins/plugin.resume.js +2 -0
  123. package/BookReader/plugins/plugin.resume.js.map +1 -0
  124. package/BookReader/plugins/plugin.search.js +2 -0
  125. package/BookReader/plugins/plugin.search.js.map +1 -0
  126. package/BookReader/plugins/plugin.text_selection.js +2 -0
  127. package/BookReader/plugins/plugin.text_selection.js.map +1 -0
  128. package/BookReader/plugins/plugin.tts.js +3 -0
  129. package/BookReader/plugins/plugin.tts.js.LICENSE.txt +27 -0
  130. package/BookReader/plugins/plugin.tts.js.map +1 -0
  131. package/BookReader/plugins/plugin.url.js +2 -0
  132. package/BookReader/plugins/plugin.url.js.map +1 -0
  133. package/BookReader/plugins/plugin.vendor-fullscreen.js +2 -0
  134. package/BookReader/plugins/plugin.vendor-fullscreen.js.map +1 -0
  135. package/BookReaderDemo/BookReaderDemo.css +41 -0
  136. package/BookReaderDemo/BookReaderJSAdvanced.js +115 -0
  137. package/BookReaderDemo/BookReaderJSAutoplay.js +56 -0
  138. package/BookReaderDemo/BookReaderJSSimple.js +55 -0
  139. package/BookReaderDemo/IIIFBookReader.js +207 -0
  140. package/BookReaderDemo/assets/v5/Bookreader-logo-cool-grad.svg +1 -0
  141. package/BookReaderDemo/assets/v5/Bookreader-logo-flat.svg +1 -0
  142. package/BookReaderDemo/assets/v5/Bookreader-logo-hex-cool-grad.png +0 -0
  143. package/BookReaderDemo/assets/v5/Bookreader-logo-hex-flat.png +0 -0
  144. package/BookReaderDemo/assets/v5/Bookreader-logo-lines.png +0 -0
  145. package/BookReaderDemo/assets/v5/Bookreader-logo-lines.svg +1 -0
  146. package/BookReaderDemo/assets/v5/Bookreader-logo-warm.svg +1 -0
  147. package/BookReaderDemo/assets/v5/bookreader-logo-renders@1x.png +0 -0
  148. package/BookReaderDemo/assets/v5/bookreader-logo-renders@2x.png +0 -0
  149. package/BookReaderDemo/assets/v5/bookreader-v5-screenshot.png +0 -0
  150. package/BookReaderDemo/bookreader-template-bundle.js +7178 -0
  151. package/BookReaderDemo/demo-advanced.html +32 -0
  152. package/BookReaderDemo/demo-autoplay.html +38 -0
  153. package/BookReaderDemo/demo-embed-iframe-src.html +84 -0
  154. package/BookReaderDemo/demo-embed.html +26 -0
  155. package/BookReaderDemo/demo-fullscreen-mobile.html +36 -0
  156. package/BookReaderDemo/demo-fullscreen.html +33 -0
  157. package/BookReaderDemo/demo-iiif.html +34 -0
  158. package/BookReaderDemo/demo-iiif.js +26 -0
  159. package/BookReaderDemo/demo-internetarchive.html +74 -0
  160. package/BookReaderDemo/demo-multiple.html +43 -0
  161. package/BookReaderDemo/demo-preview-pages.html +1092 -0
  162. package/BookReaderDemo/demo-simple.html +34 -0
  163. package/BookReaderDemo/demo-vendor-fullscreen.html +36 -0
  164. package/BookReaderDemo/immersion-1up.html +64 -0
  165. package/BookReaderDemo/immersion-mode.html +35 -0
  166. package/BookReaderDemo/toggle_controls.html +53 -0
  167. package/BookReaderDemo/view_mode.html +39 -0
  168. package/BookReaderDemo/viewmode-cycle.html +41 -0
  169. package/CHANGELOG.md +540 -0
  170. package/CONTRIBUTING.md +7 -0
  171. package/LICENSE +661 -0
  172. package/README.md +205 -0
  173. package/babel.config.js +18 -0
  174. package/codecov.yml +17 -0
  175. package/index.html +31 -0
  176. package/jsconfig.json +14 -0
  177. package/karma.conf.js +23 -0
  178. package/package.json +129 -0
  179. package/screenshot.png +0 -0
  180. package/scripts/postversion.js +10 -0
  181. package/scripts/preversion.js +14 -0
  182. package/scripts/version.js +26 -0
  183. package/src/BookNavigator/BookModel.js +14 -0
  184. package/src/BookNavigator/BookNavigator.js +468 -0
  185. package/src/BookNavigator/assets/book-loader.js +27 -0
  186. package/src/BookNavigator/assets/bookmark-colors.js +15 -0
  187. package/src/BookNavigator/assets/button-base.js +61 -0
  188. package/src/BookNavigator/assets/icon_checkmark.js +6 -0
  189. package/src/BookNavigator/assets/icon_close.js +3 -0
  190. package/src/BookNavigator/assets/icon_sort_asc.js +5 -0
  191. package/src/BookNavigator/assets/icon_sort_desc.js +5 -0
  192. package/src/BookNavigator/assets/icon_sort_neutral.js +5 -0
  193. package/src/BookNavigator/assets/icon_volumes.js +11 -0
  194. package/src/BookNavigator/bookmarks/bookmark-button.js +64 -0
  195. package/src/BookNavigator/bookmarks/bookmark-edit.js +215 -0
  196. package/src/BookNavigator/bookmarks/bookmarks-list.js +285 -0
  197. package/src/BookNavigator/bookmarks/bookmarks-loginCTA.js +28 -0
  198. package/src/BookNavigator/bookmarks/bookmarks-provider.js +53 -0
  199. package/src/BookNavigator/bookmarks/ia-bookmarks.js +500 -0
  200. package/src/BookNavigator/br-fullscreen-mgr.js +83 -0
  201. package/src/BookNavigator/delete-modal-actions.js +49 -0
  202. package/src/BookNavigator/downloads/downloads-provider.js +76 -0
  203. package/src/BookNavigator/downloads/downloads.js +138 -0
  204. package/src/BookNavigator/search/a-search-result.js +55 -0
  205. package/src/BookNavigator/search/search-provider.js +180 -0
  206. package/src/BookNavigator/search/search-results.js +360 -0
  207. package/src/BookNavigator/visual-adjustments/visual-adjustments-provider.js +93 -0
  208. package/src/BookNavigator/visual-adjustments/visual-adjustments.js +280 -0
  209. package/src/BookNavigator/volumes/volumes-provider.js +83 -0
  210. package/src/BookNavigator/volumes/volumes.js +178 -0
  211. package/src/BookReader/BookModel.js +518 -0
  212. package/src/BookReader/DebugConsole.js +54 -0
  213. package/src/BookReader/ImageCache.js +116 -0
  214. package/src/BookReader/Mode1Up.js +90 -0
  215. package/src/BookReader/Mode1UpLit.js +434 -0
  216. package/src/BookReader/Mode2Up.js +1372 -0
  217. package/src/BookReader/ModeSmoothZoom.js +177 -0
  218. package/src/BookReader/ModeThumb.js +336 -0
  219. package/src/BookReader/Navbar/Navbar.js +339 -0
  220. package/src/BookReader/PageContainer.js +120 -0
  221. package/src/BookReader/ReduceSet.js +26 -0
  222. package/src/BookReader/Toolbar/Toolbar.js +384 -0
  223. package/src/BookReader/events.js +20 -0
  224. package/src/BookReader/options.js +320 -0
  225. package/src/BookReader/utils/HTMLDimensionsCacher.js +44 -0
  226. package/src/BookReader/utils/classes.js +36 -0
  227. package/src/BookReader/utils.js +240 -0
  228. package/src/BookReader.js +2546 -0
  229. package/src/BookReaderComponent/BookReaderComponent.js +112 -0
  230. package/src/ItemNavigator/ItemNavigator.js +376 -0
  231. package/src/ItemNavigator/providers/sharing.js +33 -0
  232. package/src/assets/icons/1up.svg +12 -0
  233. package/src/assets/icons/2up.svg +15 -0
  234. package/src/assets/icons/advance.svg +26 -0
  235. package/src/assets/icons/chevron-right.svg +1 -0
  236. package/src/assets/icons/close-circle-dark.svg +1 -0
  237. package/src/assets/icons/close-circle.svg +1 -0
  238. package/src/assets/icons/fullscreen.svg +17 -0
  239. package/src/assets/icons/fullscreen_exit.svg +17 -0
  240. package/src/assets/icons/hamburger.svg +15 -0
  241. package/src/assets/icons/left-arrow.svg +12 -0
  242. package/src/assets/icons/magnify-minus.svg +16 -0
  243. package/src/assets/icons/magnify-plus.svg +17 -0
  244. package/src/assets/icons/magnify.svg +15 -0
  245. package/src/assets/icons/pause.svg +23 -0
  246. package/src/assets/icons/play.svg +22 -0
  247. package/src/assets/icons/playback-speed.svg +34 -0
  248. package/src/assets/icons/read-aloud.svg +22 -0
  249. package/src/assets/icons/review.svg +22 -0
  250. package/src/assets/icons/thumbnails.svg +17 -0
  251. package/src/assets/icons/volume-full.svg +22 -0
  252. package/src/assets/images/BRicons.png +0 -0
  253. package/src/assets/images/BRicons.svg +94 -0
  254. package/src/assets/images/BRicons_ia.png +0 -0
  255. package/src/assets/images/back_pages.png +0 -0
  256. package/src/assets/images/book_bottom_icon.png +0 -0
  257. package/src/assets/images/book_down_icon.png +0 -0
  258. package/src/assets/images/book_left_icon.png +0 -0
  259. package/src/assets/images/book_leftmost_icon.png +0 -0
  260. package/src/assets/images/book_right_icon.png +0 -0
  261. package/src/assets/images/book_rightmost_icon.png +0 -0
  262. package/src/assets/images/book_top_icon.png +0 -0
  263. package/src/assets/images/book_up_icon.png +0 -0
  264. package/src/assets/images/books_graphic.svg +177 -0
  265. package/src/assets/images/booksplit.png +0 -0
  266. package/src/assets/images/control_pause_icon.png +0 -0
  267. package/src/assets/images/control_play_icon.png +0 -0
  268. package/src/assets/images/embed_icon.png +0 -0
  269. package/src/assets/images/icon-home-ia.png +0 -0
  270. package/src/assets/images/icon_OL-logo-xs.png +0 -0
  271. package/src/assets/images/icon_alert-xs.png +0 -0
  272. package/src/assets/images/icon_book.svg +12 -0
  273. package/src/assets/images/icon_bookmark.svg +12 -0
  274. package/src/assets/images/icon_close-pop.png +0 -0
  275. package/src/assets/images/icon_download.png +0 -0
  276. package/src/assets/images/icon_gear.svg +14 -0
  277. package/src/assets/images/icon_hamburger.svg +20 -0
  278. package/src/assets/images/icon_home.png +0 -0
  279. package/src/assets/images/icon_home.svg +21 -0
  280. package/src/assets/images/icon_home_ia.png +0 -0
  281. package/src/assets/images/icon_indicator.png +0 -0
  282. package/src/assets/images/icon_info.svg +11 -0
  283. package/src/assets/images/icon_one_page.svg +8 -0
  284. package/src/assets/images/icon_pause.svg +1 -0
  285. package/src/assets/images/icon_play.svg +1 -0
  286. package/src/assets/images/icon_playback-rate.svg +15 -0
  287. package/src/assets/images/icon_return.png +0 -0
  288. package/src/assets/images/icon_search_button.svg +8 -0
  289. package/src/assets/images/icon_share.svg +9 -0
  290. package/src/assets/images/icon_skip-ahead.svg +6 -0
  291. package/src/assets/images/icon_skip-back.svg +13 -0
  292. package/src/assets/images/icon_speaker.svg +18 -0
  293. package/src/assets/images/icon_speaker_open.svg +10 -0
  294. package/src/assets/images/icon_thumbnails.svg +12 -0
  295. package/src/assets/images/icon_toc.svg +5 -0
  296. package/src/assets/images/icon_two_pages.svg +9 -0
  297. package/src/assets/images/icon_zoomer.png +0 -0
  298. package/src/assets/images/loading.gif +0 -0
  299. package/src/assets/images/logo_icon.png +0 -0
  300. package/src/assets/images/marker_chap-off.png +0 -0
  301. package/src/assets/images/marker_chap-off.svg +11 -0
  302. package/src/assets/images/marker_chap-off_ia.png +0 -0
  303. package/src/assets/images/marker_chap-on.png +0 -0
  304. package/src/assets/images/marker_chap-on.svg +11 -0
  305. package/src/assets/images/marker_srch-on.svg +11 -0
  306. package/src/assets/images/marker_srchchap-off.png +0 -0
  307. package/src/assets/images/marker_srchchap-on.png +0 -0
  308. package/src/assets/images/nav_control-dn.png +0 -0
  309. package/src/assets/images/nav_control-dn_ia.png +0 -0
  310. package/src/assets/images/nav_control-up.png +0 -0
  311. package/src/assets/images/nav_control-up_ia.png +0 -0
  312. package/src/assets/images/nav_control.png +0 -0
  313. package/src/assets/images/one_page_mode_icon.png +0 -0
  314. package/src/assets/images/paper-badge.png +0 -0
  315. package/src/assets/images/print_icon.png +0 -0
  316. package/src/assets/images/progressbar.gif +0 -0
  317. package/src/assets/images/right_edges.png +0 -0
  318. package/src/assets/images/slider.png +0 -0
  319. package/src/assets/images/slider_ia.png +0 -0
  320. package/src/assets/images/thumbnail_mode_icon.png +0 -0
  321. package/src/assets/images/transparent.png +0 -0
  322. package/src/assets/images/two_page_mode_icon.png +0 -0
  323. package/src/assets/images/zoom_in_icon.png +0 -0
  324. package/src/assets/images/zoom_out_icon.png +0 -0
  325. package/src/css/BookReader.scss +89 -0
  326. package/src/css/_BRBookmarks.scss +29 -0
  327. package/src/css/_BRComponent.scss +13 -0
  328. package/src/css/_BRfloat.scss +197 -0
  329. package/src/css/_BRicon.scss +48 -0
  330. package/src/css/_BRmain.scss +251 -0
  331. package/src/css/_BRnav.scss +382 -0
  332. package/src/css/_BRpages.scss +139 -0
  333. package/src/css/_BRsearch.scss +226 -0
  334. package/src/css/_BRtoolbar.scss +84 -0
  335. package/src/css/_BRvendor.scss +5 -0
  336. package/src/css/_MobileNav.scss +194 -0
  337. package/src/css/_TextSelection.scss +32 -0
  338. package/src/css/_colorbox.scss +52 -0
  339. package/src/css/_controls.scss +244 -0
  340. package/src/css/_icons.scss +121 -0
  341. package/src/dragscrollable-br.js +261 -0
  342. package/src/jquery-wrapper.js +4 -0
  343. package/src/plugins/plugin.archive_analytics.js +86 -0
  344. package/src/plugins/plugin.autoplay.js +129 -0
  345. package/src/plugins/plugin.chapters.js +251 -0
  346. package/src/plugins/plugin.iframe.js +48 -0
  347. package/src/plugins/plugin.mobile_nav.js +287 -0
  348. package/src/plugins/plugin.resume.js +68 -0
  349. package/src/plugins/plugin.text_selection.js +291 -0
  350. package/src/plugins/plugin.url.js +198 -0
  351. package/src/plugins/plugin.vendor-fullscreen.js +247 -0
  352. package/src/plugins/search/plugin.search.js +439 -0
  353. package/src/plugins/search/view.js +440 -0
  354. package/src/plugins/tts/AbstractTTSEngine.js +242 -0
  355. package/src/plugins/tts/FestivalTTSEngine.js +169 -0
  356. package/src/plugins/tts/PageChunk.js +107 -0
  357. package/src/plugins/tts/PageChunkIterator.js +163 -0
  358. package/src/plugins/tts/WebTTSEngine.js +352 -0
  359. package/src/plugins/tts/plugin.tts.js +335 -0
  360. package/src/plugins/tts/tooltip_dict.js +15 -0
  361. package/src/plugins/tts/utils.js +91 -0
  362. package/src/util/browserSniffing.js +30 -0
  363. package/src/util/debouncer.js +26 -0
  364. package/src/util/docCookies.js +67 -0
  365. package/src/util/strings.js +34 -0
  366. package/tests/BookReader/BookModel.test.js +312 -0
  367. package/tests/BookReader/BookReaderPublicFunctions.test.js +164 -0
  368. package/tests/BookReader/DebugConsole.test.js +25 -0
  369. package/tests/BookReader/ImageCache.test.js +150 -0
  370. package/tests/BookReader/Mode1UpLit.test.js +87 -0
  371. package/tests/BookReader/Mode2Up.test.js +245 -0
  372. package/tests/BookReader/ModeSmoothZoom.test.js +149 -0
  373. package/tests/BookReader/Navbar/Navbar.test.js +169 -0
  374. package/tests/BookReader/PageContainer.test.js +187 -0
  375. package/tests/BookReader/ReduceSet.test.js +38 -0
  376. package/tests/BookReader/Toolbar/Toolbar.test.js +26 -0
  377. package/tests/BookReader/utils/HTMLDimensionsCacher.test.js +59 -0
  378. package/tests/BookReader/utils/classes.test.js +88 -0
  379. package/tests/BookReader/utils.test.js +136 -0
  380. package/tests/BookReader.options.test.js +39 -0
  381. package/tests/BookReader.test.js +301 -0
  382. package/tests/e2e/README.md +75 -0
  383. package/tests/e2e/autoplay.test.js +13 -0
  384. package/tests/e2e/base.test.js +35 -0
  385. package/tests/e2e/helpers/base.js +263 -0
  386. package/tests/e2e/helpers/debug.js +13 -0
  387. package/tests/e2e/helpers/desktopSearch.js +72 -0
  388. package/tests/e2e/helpers/mobileSearch.js +85 -0
  389. package/tests/e2e/helpers/mockSearch.js +93 -0
  390. package/tests/e2e/helpers/rightToLeft.js +29 -0
  391. package/tests/e2e/ia-production/ia-prod-base.js +17 -0
  392. package/tests/e2e/models/BookReader.js +11 -0
  393. package/tests/e2e/models/Navigation.js +56 -0
  394. package/tests/e2e/rightToLeft.test.js +20 -0
  395. package/tests/e2e/viewmode.test.js +37 -0
  396. package/tests/karma/BookNavigator/book-navigator.test.js +180 -0
  397. package/tests/karma/BookNavigator/bookmarks/bookmark-edit.test.js +133 -0
  398. package/tests/karma/BookNavigator/bookmarks/bookmarks-list.test.js +222 -0
  399. package/tests/karma/BookNavigator/downloads/downloads-provider.test.js +64 -0
  400. package/tests/karma/BookNavigator/downloads/downloads.test.js +54 -0
  401. package/tests/karma/BookNavigator/search/search-provider.test.js +23 -0
  402. package/tests/karma/BookNavigator/search/search-results.test.js +240 -0
  403. package/tests/karma/BookNavigator/sharing/sharing-provider.test.js +40 -0
  404. package/tests/karma/BookNavigator/visual-adjustments.test.js +201 -0
  405. package/tests/karma/BookNavigator/volumes/volumes-provider.test.js +160 -0
  406. package/tests/karma/BookNavigator/volumes/volumes.test.js +98 -0
  407. package/tests/plugins/plugin.archive_analytics.test.js +23 -0
  408. package/tests/plugins/plugin.autoplay.test.js +52 -0
  409. package/tests/plugins/plugin.chapters.test.js +130 -0
  410. package/tests/plugins/plugin.iframe.test.js +42 -0
  411. package/tests/plugins/plugin.mobile_nav.test.js +66 -0
  412. package/tests/plugins/plugin.resume.test.js +98 -0
  413. package/tests/plugins/plugin.text_selection.test.js +193 -0
  414. package/tests/plugins/plugin.url.test.js +129 -0
  415. package/tests/plugins/plugin.vendor-fullscreen.test.js +65 -0
  416. package/tests/plugins/search/plugin.search.test.js +173 -0
  417. package/tests/plugins/search/plugin.search.view.test.js +106 -0
  418. package/tests/plugins/tts/AbstractTTSEngine.test.js +153 -0
  419. package/tests/plugins/tts/FestivalTTSEngine.test.js +59 -0
  420. package/tests/plugins/tts/PageChunk.test.js +57 -0
  421. package/tests/plugins/tts/PageChunkIterator.test.js +179 -0
  422. package/tests/plugins/tts/WebTTSEngine.test.js +126 -0
  423. package/tests/plugins/tts/utils.test.js +133 -0
  424. package/tests/util/browserSniffing.test.js +56 -0
  425. package/tests/util/docCookies.test.js +15 -0
  426. package/tests/util/strings.test.js +63 -0
  427. package/tests/utils.js +80 -0
  428. package/webpack.config.js +85 -0
@@ -0,0 +1,312 @@
1
+ import sinon from 'sinon';
2
+ import { deepCopy } from '../utils.js';
3
+ import { BookModel } from '../../src/BookReader/BookModel.js';
4
+ /** @typedef {import('../../src/BookReader/options.js').BookReaderOptions} BookReaderOptions */
5
+
6
+ afterEach(() => {
7
+ sinon.restore();
8
+ });
9
+
10
+ /** @type {BookReaderOptions['data']} */
11
+ const SAMPLE_DATA = [
12
+ [
13
+ { width: 123, height: 123, uri: 'https://archive.org/image0.jpg', pageNum: '1' },
14
+ ],
15
+ [
16
+ { width: 123, height: 123, uri: 'https://archive.org/image1.jpg', pageNum: '2' },
17
+ { width: 123, height: 123, uri: 'https://archive.org/image2.jpg', pageNum: '3' },
18
+ ],
19
+ [
20
+ { width: 123, height: 123, uri: 'https://archive.org/image3.jpg', pageNum: '4' },
21
+ ],
22
+ ];
23
+
24
+ describe('getMedianPageSize', () => {
25
+ test('handles single page data', () => {
26
+ const bm = new BookModel({ data: SAMPLE_DATA.slice(0, 1) });
27
+ expect(bm.getMedianPageSize()).toEqual({ width: 123, height: 123 });
28
+ });
29
+
30
+ test('handles odd pages data', () => {
31
+ const sizes = [
32
+ {width: 300, height: 2200},
33
+ {width: 200, height: 2100},
34
+ {width: 100, height: 2300},
35
+ ];
36
+ const data = deepCopy(SAMPLE_DATA);
37
+ delete data[2];
38
+ Object.assign(data[0][0], sizes[0]);
39
+ Object.assign(data[1][0], sizes[1]);
40
+ Object.assign(data[1][1], sizes[2]);
41
+ const bm = new BookModel({ data });
42
+ expect(bm.getMedianPageSize()).toEqual({ width: 200, height: 2200 });
43
+ });
44
+
45
+
46
+ test('handles even pages data', () => {
47
+ const sizes = [
48
+ {width: 300, height: 2200},
49
+ {width: 200, height: 2100},
50
+ {width: 100, height: 2300},
51
+ {width: 400, height: 2400},
52
+ ];
53
+ const data = deepCopy(SAMPLE_DATA);
54
+ Object.assign(data[0][0], sizes[0]);
55
+ Object.assign(data[1][0], sizes[1]);
56
+ Object.assign(data[1][1], sizes[2]);
57
+ Object.assign(data[2][0], sizes[3]);
58
+ const bm = new BookModel({ data });
59
+ expect(bm.getMedianPageSize()).toEqual({ width: 300, height: 2300 });
60
+ });
61
+
62
+ test('caches result', () => {
63
+ const bm = new BookModel({ data: SAMPLE_DATA });
64
+ const firstResult = bm.getMedianPageSize();
65
+ expect(bm.getMedianPageSize()).toBe(firstResult);
66
+ expect(bm.getMedianPageSize()).toBe(firstResult);
67
+ expect(bm.getMedianPageSize()).toBe(firstResult);
68
+ });
69
+ });
70
+
71
+ describe('getPageIndices', () => {
72
+ test('handles unique indices', () => {
73
+ const bm = new BookModel({ data: SAMPLE_DATA });
74
+ expect(bm.getPageIndices('1')).toEqual([0]);
75
+ });
76
+
77
+ test('handles invalid indices', () => {
78
+ const bm = new BookModel({ data: SAMPLE_DATA });
79
+ expect(bm.getPageIndices('foo')).toEqual([]);
80
+ expect(bm.getPageIndices('123')).toEqual([]);
81
+ });
82
+
83
+ test('handles non-unique indices', () => {
84
+ const data = deepCopy(SAMPLE_DATA);
85
+ data[0][0].pageNum = '2';
86
+ const bm = new BookModel({ data });
87
+ expect(bm.getPageIndices('2')).toEqual([0, 1]);
88
+ });
89
+
90
+ test('handles n-prefixed pages', () => {
91
+ const data = deepCopy(SAMPLE_DATA);
92
+ data[0][0].pageNum = 'n0';
93
+ const bm = new BookModel({ data });
94
+ expect(bm.getPageIndices('n0')).toEqual([0]);
95
+ });
96
+ });
97
+
98
+ test('getPageName', () => {
99
+ const bm = new BookModel({ data: SAMPLE_DATA });
100
+ expect(bm.getPageName(0)).toEqual('Page 1');
101
+ expect(bm.getPageName(1)).toEqual('Page 2');
102
+ });
103
+
104
+ describe('numLeafs', () => {
105
+ test('reads from data', () => {
106
+ const bm = new BookModel({ data: SAMPLE_DATA });
107
+ expect(bm.getNumLeafs()).toBe(4);
108
+ });
109
+
110
+ test('numLeafs can be overriden', () => {
111
+ const bm = new BookModel({ data: SAMPLE_DATA, numLeafs: 12 });
112
+ expect(bm.getNumLeafs()).toBe(12);
113
+ });
114
+ });
115
+
116
+ test('getPageNum', () => {
117
+ const bm = new BookModel({ data: SAMPLE_DATA });
118
+ expect(bm.getPageNum(0)).toBe('1');
119
+ });
120
+
121
+ test('getPageProp gets values from correct document', () => {
122
+ const bm = new BookModel({ data: SAMPLE_DATA });
123
+ expect(bm.getPageProp(1, 'uri')).toBe(SAMPLE_DATA[1][0].uri);
124
+ });
125
+
126
+ describe('getSpreadIndices', () => {
127
+ test('Works for left to right text', () => {
128
+ const bm = new BookModel({ data: SAMPLE_DATA, pageProgression: 'lr' });
129
+ expect(bm.getSpreadIndices(1)).toEqual([1, 2]);
130
+ expect(bm.getSpreadIndices(2)).toEqual([1, 2]);
131
+ });
132
+ });
133
+
134
+ describe('leafNumToIndex', () => {
135
+ test('returns input if no leafNum in data', () => {
136
+ const bm = new BookModel({ data: SAMPLE_DATA });
137
+ expect(bm.leafNumToIndex(1)).toBe(1);
138
+ expect(bm.leafNumToIndex(2)).toBe(2);
139
+ expect(bm.leafNumToIndex(3)).toBe(3);
140
+ });
141
+
142
+ test('returns true index when leafNum does not point to index', () => {
143
+ const data = deepCopy(SAMPLE_DATA);
144
+ for (const spread of data) {
145
+ for (const page of spread) {
146
+ page.leafNum = parseFloat(page.pageNum) + 2;
147
+ }
148
+ }
149
+
150
+ const bm = new BookModel({ data });
151
+ expect(bm.leafNumToIndex(3)).toBe(0);
152
+ });
153
+ });
154
+
155
+ describe('parsePageString', () => {
156
+ test('handles leaf-prefixed PageString', () => {
157
+ const data = deepCopy(SAMPLE_DATA);
158
+ for (const spread of data) {
159
+ for (const page of spread) {
160
+ page.leafNum = parseFloat(page.pageNum) + 2;
161
+ }
162
+ }
163
+
164
+ const bm = new BookModel({ data });
165
+ expect(bm.parsePageString('leaf3')).toBe(0);
166
+ });
167
+ });
168
+
169
+ describe('pagesIterator', () => {
170
+ test('Goes through all pages', () => {
171
+ const bm = new BookModel({ data: SAMPLE_DATA });
172
+ let i = 0;
173
+ for (const page of bm.pagesIterator()) {
174
+ expect(page.index).toBe(i++);
175
+ }
176
+ });
177
+
178
+ test('Can combine unviewables', () => {
179
+ const data = deepCopy(SAMPLE_DATA);
180
+ // add some more pages
181
+ data.splice(2, 0, deepCopy(data[0]));
182
+ data[1].forEach(page => page.viewable = false);
183
+ const bm = new BookModel({ data });
184
+ for (const page of bm.pagesIterator({combineConsecutiveUnviewables: true})) {
185
+ expect(page.isConsecutiveUnviewable).toBe(false);
186
+ }
187
+ });
188
+ });
189
+
190
+ describe('_getDataFlattened', () => {
191
+ test('Assigns correct page sides', () => {
192
+ const bm = new BookModel({ data: SAMPLE_DATA });
193
+ expect(bm._getDataFlattened().map(page => page.pageSide)).toEqual(['R', 'L', 'R', 'L']);
194
+ });
195
+
196
+ test('Memoized based on data length', () => {
197
+ const data = deepCopy(SAMPLE_DATA);
198
+ const bm = new BookModel({ data });
199
+ const firstResult = bm._getDataFlattened();
200
+ expect(bm._getDataFlattened()).toBe(firstResult);
201
+ expect(bm._getDataFlattened()).toBe(firstResult);
202
+ bm.br.data = data.slice(0, 1);
203
+ expect(bm._getDataFlattened()).not.toBe(firstResult);
204
+ });
205
+
206
+ test('Assigns unviewablesStart', () => {
207
+ const data = deepCopy(SAMPLE_DATA);
208
+ data.slice(1, -1)
209
+ .forEach(spread => spread.forEach(page => {
210
+ page.viewable = false;
211
+ }));
212
+ const bm = new BookModel({ data });
213
+ const pages = bm._getDataFlattened();
214
+ expect(pages[0].unviewablesStart).toBeUndefined();
215
+ expect(pages[1].unviewablesStart).toBe(1);
216
+ expect(pages[2].unviewablesStart).toBe(1);
217
+ expect(pages[3].unviewablesStart).toBeUndefined();
218
+ });
219
+ });
220
+
221
+ describe('getPage', () => {
222
+ test('loops around by default', () => {
223
+ const bm = new BookModel({ data: SAMPLE_DATA });
224
+ expect(bm.getPage(-1).index).toBe(3);
225
+ expect(bm.getPage(-2).index).toBe(2);
226
+ expect(bm.getPage(-3).index).toBe(1);
227
+ expect(bm.getPage(4).index).toBe(0);
228
+ expect(bm.getPage(5).index).toBe(1);
229
+ });
230
+
231
+ test('does not loop if loop=false', () => {
232
+ const bm = new BookModel({ data: SAMPLE_DATA });
233
+ expect(bm.getPage(-1, false)).toBeUndefined();
234
+ expect(bm.getPage(-2, false)).toBeUndefined();
235
+ expect(bm.getPage(4, false)).toBeUndefined();
236
+ expect(bm.getPage(5, false)).toBeUndefined();
237
+ });
238
+ });
239
+
240
+ describe('PageModel', () => {
241
+ test('constructor copies fields from book model', () => {
242
+ const bm = new BookModel({ data: SAMPLE_DATA });
243
+ const spy = sinon.spy(bm, 'getPageWidth');
244
+ const page = bm.getPage(0);
245
+ expect(spy.callCount).toBe(1);
246
+ expect(page.width).toBe(SAMPLE_DATA[0][0].width);
247
+ });
248
+
249
+ test('prev at start of book returns null', () => {
250
+ const bm = new BookModel({ data: SAMPLE_DATA });
251
+ expect(bm.getPage(0).prev).toBeUndefined();
252
+ });
253
+
254
+ test('prev to return previous', () => {
255
+ const bm = new BookModel({ data: SAMPLE_DATA });
256
+ expect(bm.getPage(1).prev.index).toBe(0);
257
+ expect(bm.getPage(3).prev.prev.index).toBe(1);
258
+ });
259
+
260
+ test('next at end of book returns null', () => {
261
+ const bm = new BookModel({ data: SAMPLE_DATA });
262
+ expect(bm.getPage(-1).next).toBeUndefined();
263
+ });
264
+
265
+ test('next to return next page', () => {
266
+ const bm = new BookModel({ data: SAMPLE_DATA });
267
+ expect(bm.getPage(0).next.index).toBe(1);
268
+ expect(bm.getPage(1).next.next.index).toBe(3);
269
+ });
270
+
271
+ describe('findNext combineConsecutiveUnviewables=true', () => {
272
+ const data = deepCopy(SAMPLE_DATA);
273
+ // add some more pages
274
+ data.splice(2, 0, deepCopy(data[0]));
275
+ data[1].forEach(page => page.viewable = false);
276
+
277
+ const bm = new BookModel({ data });
278
+
279
+ test('does not skip the first unviewable page', () => {
280
+ expect(bm.getPage(0).findNext({ combineConsecutiveUnviewables: true }).index).toBe(1);
281
+ });
282
+
283
+ test('skips consecutive unviewables', () => {
284
+ expect(bm.getPage(1).findNext({ combineConsecutiveUnviewables: true }).index).toBe(3);
285
+ });
286
+
287
+ test('at end is undefined', () => {
288
+ expect(bm.getPage(-1).findNext({ combineConsecutiveUnviewables: true })).toBeUndefined();
289
+ });
290
+ });
291
+
292
+ describe('findPrev', () => {
293
+ const data = deepCopy(SAMPLE_DATA);
294
+ // add some more pages
295
+ data.splice(2, 0, deepCopy(data[0]));
296
+ data[1].forEach(page => page.viewable = false);
297
+
298
+ const bm = new BookModel({ data });
299
+
300
+ test('works if called on first unviewable', () => {
301
+ expect(bm.getPage(1).findPrev({ combineConsecutiveUnviewables: true }).index).toBe(0);
302
+ });
303
+
304
+ test('works if called within unviewable chunk', () => {
305
+ expect(bm.getPage(2).findPrev({ combineConsecutiveUnviewables: true }).index).toBe(1);
306
+ });
307
+
308
+ test('at start is undefined', () => {
309
+ expect(bm.getPage(0).findPrev({ combineConsecutiveUnviewables: true })).toBeUndefined();
310
+ });
311
+ });
312
+ });
@@ -0,0 +1,164 @@
1
+ import BookReader from '../../src/BookReader';
2
+
3
+ beforeAll(() => {
4
+ global.alert = jest.fn();
5
+ });
6
+ afterEach(() => {
7
+ jest.restoreAllMocks();
8
+ });
9
+
10
+ describe('BookReader.prototype.toggleFullscreen', () => {
11
+ test('uses `isFullscreen` to check fullscreen state', () => {
12
+ const isFSmock = jest.fn();
13
+ isFSmock.mockReturnValueOnce(false);
14
+ const br = new BookReader();
15
+ br.mode = br.constMode1up;
16
+ br.enterFullscreen = jest.fn();
17
+ br.isFullscreen = isFSmock;
18
+
19
+ br.toggleFullscreen();
20
+ expect(br.isFullscreen).toHaveBeenCalled();
21
+ });
22
+
23
+ test('will always emit an event', async () => {
24
+ const br = new BookReader();
25
+ br.mode = br.constMode2up;
26
+ br.trigger = jest.fn();
27
+ br.switchMode = jest.fn();
28
+ br.refs.$brContainer = {
29
+ css: jest.fn(),
30
+ animate: (options, speed, style, callback) => callback()
31
+ };
32
+
33
+ await br.toggleFullscreen();
34
+ expect(br.trigger).toHaveBeenCalled();
35
+ });
36
+
37
+ test('will start with opening fullscreen', () => {
38
+ const br = new BookReader();
39
+ br.mode = br.constMode2up;
40
+ br.enterFullscreen = jest.fn();
41
+
42
+ br.toggleFullscreen();
43
+ expect(br.enterFullscreen).toHaveBeenCalled();
44
+ });
45
+
46
+ test('will close fullscreen if BookReader is in fullscreen', () => {
47
+ const br = new BookReader();
48
+ br.mode = br.constMode1up;
49
+ br.exitFullScreen = jest.fn();
50
+ br.isFullscreenActive = true;
51
+
52
+ br.toggleFullscreen();
53
+ expect(br.exitFullScreen).toHaveBeenCalled();
54
+ });
55
+ });
56
+
57
+ describe('BookReader.prototype.enterFullscreen', () => {
58
+ test('will bind `_fullscreenCloseHandler` by default', () => {
59
+ const br = new BookReader();
60
+ br.mode = br.constMode1up;
61
+ br.switchMode = jest.fn();
62
+ br.updateBrClasses = jest.fn();
63
+ br.refs.$brContainer = {
64
+ css: jest.fn(),
65
+ animate: jest.fn(),
66
+ };
67
+ expect(br._fullscreenCloseHandler).toBeUndefined();
68
+
69
+ br.enterFullscreen();
70
+ expect(br._fullscreenCloseHandler).toBeDefined();
71
+ });
72
+
73
+ test('fires certain events when called', async () => {
74
+ const br = new BookReader();
75
+ br.mode = br.constMode2up;
76
+ br.switchMode = jest.fn();
77
+ br.updateBrClasses = jest.fn();
78
+ br.trigger = jest.fn();
79
+ br.resize = jest.fn();
80
+ br.jumpToIndex = jest.fn();
81
+ br.refs.$brContainer = {
82
+ css: jest.fn(),
83
+ animate: (options, speed, style, callback) => callback()
84
+ };
85
+
86
+ await br.enterFullscreen();
87
+ expect(br.switchMode).toHaveBeenCalledTimes(1);
88
+ expect(br.updateBrClasses).toHaveBeenCalledTimes(0); // book nav's fullscreen manager will set these classes
89
+ expect(br.trigger).toHaveBeenCalledTimes(1);
90
+ expect(br.resize).toHaveBeenCalledTimes(1);
91
+ expect(br.jumpToIndex).toHaveBeenCalledTimes(1);
92
+ });
93
+ });
94
+
95
+ describe('BookReader.prototype.exitFullScreen', () => {
96
+ test('fires certain events when called', async () => {
97
+ const br = new BookReader();
98
+ br.mode = br.constMode2up;
99
+ br.switchMode = jest.fn();
100
+ br.updateBrClasses = jest.fn();
101
+ br.trigger = jest.fn();
102
+ br.resize = jest.fn();
103
+ br.refs.$brContainer = {
104
+ css: jest.fn(),
105
+ animate: (options, speed, style, callback) => callback()
106
+ };
107
+ await br.exitFullScreen();
108
+ expect(br.switchMode).toHaveBeenCalledTimes(1);
109
+ expect(br.updateBrClasses).toHaveBeenCalledTimes(1);
110
+ expect(br.trigger).toHaveBeenCalledTimes(1);
111
+ expect(br.resize).toHaveBeenCalledTimes(1);
112
+ });
113
+ });
114
+
115
+ describe('BookReader.prototype.trigger', () => {
116
+ test('fires custom event', () => {
117
+ const br = new BookReader();
118
+ global.br = br;
119
+ global.dispatchEvent = jest.fn();
120
+
121
+ const props = {bar: 1};
122
+ br.trigger('foo', props);
123
+ expect(global.dispatchEvent.mock.calls.length).toBe(1);
124
+ });
125
+ });
126
+
127
+ describe('`BookReader.prototype.prev`', () => {
128
+ const br = new BookReader();
129
+ global.br = br;
130
+ br.trigger = jest.fn();
131
+ br.flipBackToIndex = jest.fn();
132
+ br.jumpToIndex = jest.fn();
133
+
134
+ test('does not take action if user is on front page', () => {
135
+ br.firstIndex = 0;
136
+ br.prev();
137
+ expect(br.trigger.mock.calls.length).toBe(0);
138
+ expect(br.flipBackToIndex.mock.calls.length).toBe(0);
139
+ expect(br.jumpToIndex.mock.calls.length).toBe(0);
140
+ });
141
+
142
+ describe('2up mode', () => {
143
+ test('fires event and turns the page', () => {
144
+ br.firstIndex = 10;
145
+ br.mode = br.constMode2up;
146
+ br.prev();
147
+ expect(br.jumpToIndex.mock.calls.length).toBe(0); // <-- does not get called
148
+ expect(br.trigger.mock.calls.length).toBe(1);
149
+ expect(br.flipBackToIndex.mock.calls.length).toBe(1);
150
+ });
151
+ });
152
+
153
+ describe('non 2up mode', () => {
154
+ test('jumps to provided index', () => {
155
+ br.firstIndex = 100;
156
+ br.mode = br.constMode1up;
157
+ br.prev();
158
+ expect(br.jumpToIndex.mock.calls.length).toBe(1); // <-- gets called
159
+ expect(br.trigger.mock.calls.length).toBe(1); // <-- gets called by `jumpToIndex` internally
160
+ expect(br.flipBackToIndex.mock.calls.length).toBe(1); // <-- gets called by `jumpToIndex` internally
161
+ });
162
+ });
163
+ });
164
+
@@ -0,0 +1,25 @@
1
+ import sinon from 'sinon';
2
+ import { DebugConsole } from '../../src/BookReader/DebugConsole.js';
3
+
4
+ beforeEach(() => {
5
+ sinon.stub(console, 'log');
6
+ });
7
+ afterEach(() => {
8
+ sinon.restore();
9
+ });
10
+
11
+ test('hijacks console.log', () => {
12
+ const _realLog = console.log;
13
+ expect(_realLog).toBe(console.log);
14
+ new DebugConsole().init();
15
+ expect(_realLog).not.toBe(console.log);
16
+ });
17
+
18
+ test('logging the same thing twice does not create more entries', () => {
19
+ const dc = new DebugConsole();
20
+ dc.init();
21
+ dc.logToScreen(['hello']);
22
+ dc.logToScreen(['hello']);
23
+ expect(dc.$log.children('.log-entry')).toHaveLength(1);
24
+ expect(dc.$log.find('.count').text()).toBe('(2)');
25
+ });
@@ -0,0 +1,150 @@
1
+ import sinon from 'sinon';
2
+ import { BookModel } from '../../src/BookReader/BookModel.js';
3
+ import { ImageCache } from '../../src/BookReader/ImageCache.js';
4
+ import { Pow2ReduceSet } from '../../src/BookReader/ReduceSet.js';
5
+ /** @typedef {import('../../src/BookReader/options.js').BookReaderOptions} BookReaderOptions */
6
+
7
+ afterEach(() => {
8
+ jest.restoreAllMocks();
9
+ sinon.restore();
10
+ });
11
+
12
+ const CACHE_MOCK = { 1: [{ reduce: 3, loaded: true }] };
13
+ const FIRST_PAGE_MOCK = { width: 123, height: 123, uri: 'https://archive.org/image0.jpg', pageNum: '1' };
14
+ /** @type {BookReaderOptions['data']} */
15
+ const SAMPLE_DATA = [
16
+ [ FIRST_PAGE_MOCK ],
17
+ [
18
+ { width: 123, height: 123, uri: 'https://archive.org/image1.jpg', pageNum: '2' },
19
+ { width: 123, height: 123, uri: 'https://archive.org/image2.jpg', pageNum: '3' },
20
+ ],
21
+ [
22
+ { width: 123, height: 123, uri: 'https://archive.org/image3.jpg', pageNum: '4' },
23
+ { width: 123, height: 123, uri: 'https://archive.org/image4.jpg', pageNum: '5' },
24
+ ],
25
+ [
26
+ { width: 123, height: 123, uri: 'https://archive.org/image5.jpg', pageNum: '6' },
27
+ ],
28
+ ];
29
+
30
+ describe('Image Cache', () => {
31
+ describe('`image` call', () => {
32
+ test('calling `image` will create an image if none is cached', () => {
33
+ const reduceSet = Pow2ReduceSet;
34
+ const ic = new ImageCache(new BookModel({ data: SAMPLE_DATA, reduceSet }), reduceSet);
35
+ ic.cache = {};
36
+ ic.image(1, 5);
37
+ expect(Object.keys(ic.cache).length).toBe(1);
38
+ expect(ic.cache['1'].length).toBe(1);
39
+ });
40
+ test('will pull from cache if image of a good quality has been stored', () => {
41
+ const reduceSet = Pow2ReduceSet;
42
+ const ic = new ImageCache(new BookModel({ data: SAMPLE_DATA, reduceSet }), reduceSet);
43
+ const serveImgElSpy = sinon.spy(ic, '_serveImageElement');
44
+ ic.cache = CACHE_MOCK;
45
+ ic.image(1, 5);
46
+ expect(serveImgElSpy.callCount).toBe(1);
47
+ });
48
+ });
49
+
50
+ describe('`imageLoaded` call', () => {
51
+ test('returns true if image in cache', () => {
52
+ const reduceSet = Pow2ReduceSet;
53
+ const ic = new ImageCache(new BookModel({ data: SAMPLE_DATA, reduceSet }), reduceSet);
54
+ ic.cache = CACHE_MOCK;
55
+ const isImgLoaded = ic.imageLoaded(1, 3);
56
+ expect(isImgLoaded).toBe(true);
57
+ });
58
+ test('returns true if image reducer in cache is good enough', () => {
59
+ const reduceSet = Pow2ReduceSet;
60
+ const ic = new ImageCache(new BookModel({ data: SAMPLE_DATA, reduceSet }), reduceSet);
61
+ ic.cache = CACHE_MOCK;
62
+ const isImgLoaded = ic.imageLoaded(1, 5);
63
+ expect(isImgLoaded).toBe(true);
64
+ });
65
+ test('returns false if no image in cache', () => {
66
+ const reduceSet = Pow2ReduceSet;
67
+ const ic = new ImageCache(new BookModel({ data: SAMPLE_DATA, reduceSet }), reduceSet);
68
+ ic.cache = CACHE_MOCK;
69
+ const isImgLoaded = ic.imageLoaded(2, 3);
70
+ expect(isImgLoaded).toBe(false);
71
+ });
72
+ test('returns false if reducer to check is better than cache', () => {
73
+ const reduceSet = Pow2ReduceSet;
74
+ const ic = new ImageCache(new BookModel({ data: SAMPLE_DATA, reduceSet }), reduceSet);
75
+ ic.cache = CACHE_MOCK;
76
+ const isImgLoaded = ic.imageLoaded(1, 2);
77
+ expect(isImgLoaded).toBe(false);
78
+ });
79
+ test('returns false if image has not loaded', () => {
80
+ const reduceSet = Pow2ReduceSet;
81
+ const ic = new ImageCache(new BookModel({ data: SAMPLE_DATA, reduceSet }), reduceSet);
82
+ ic.cache = { 1: [{ reduce: 4, loaded: false }] };
83
+ const isImgLoaded = ic.imageLoaded(1, 2);
84
+ expect(isImgLoaded).toBe(false);
85
+ });
86
+ });
87
+
88
+ describe('`getBestLoadedReduce` call', () => {
89
+ test('handles empty cache', () => {
90
+ const reduceSet = Pow2ReduceSet;
91
+ const ic = new ImageCache(new BookModel({ data: SAMPLE_DATA, reduceSet }), reduceSet);
92
+ ic.cache = {};
93
+ expect(ic.getBestLoadedReduce(0)).toBeNull();
94
+ });
95
+
96
+ test('handles empty page-level cache', () => {
97
+ const reduceSet = Pow2ReduceSet;
98
+ const ic = new ImageCache(new BookModel({ data: SAMPLE_DATA, reduceSet }), reduceSet);
99
+ ic.cache = { 0: [] };
100
+ expect(ic.getBestLoadedReduce(0)).toBeNull();
101
+ ic.cache = { 0: [{ reduce: 10, loaded: false }] };
102
+ expect(ic.getBestLoadedReduce(0)).toBeNull();
103
+ });
104
+
105
+ test('chooses highest quality sufficient image', () => {
106
+ const reduceSet = Pow2ReduceSet;
107
+ const ic = new ImageCache(new BookModel({ data: SAMPLE_DATA, reduceSet }), reduceSet);
108
+ ic.cache = { 0: [{ reduce: 1, loaded: true }, { reduce: 4, loaded: true }, { reduce: 10, loaded: true }] };
109
+ expect(ic.getBestLoadedReduce(0, 5)).toBe(10);
110
+ });
111
+
112
+ test('chooses closest image if no lower images', () => {
113
+ const reduceSet = Pow2ReduceSet;
114
+ const ic = new ImageCache(new BookModel({ data: SAMPLE_DATA, reduceSet }), reduceSet);
115
+ ic.cache = { 0: [{ reduce: 1, loaded: true }, { reduce: 4, loaded: true }] };
116
+ expect(ic.getBestLoadedReduce(0, 5)).toBe(4);
117
+ });
118
+ });
119
+
120
+ describe('`_serveImageElement` call', () => {
121
+ test('returns jQuery image element', () => {
122
+ const reduceSet = Pow2ReduceSet;
123
+ const ic = new ImageCache(new BookModel({ data: SAMPLE_DATA, reduceSet }), reduceSet);
124
+ const img = ic._serveImageElement(0);
125
+ expect($(img).length).toBe(1);
126
+ expect($(img)[0].classList.contains('BRpageimage')).toBe(true);
127
+ expect($(img).attr('src')).toBe(FIRST_PAGE_MOCK.uri);
128
+ });
129
+
130
+ test('does not set srcset when useSrcSet=false', () => {
131
+ const reduceSet = Pow2ReduceSet;
132
+ const ic = new ImageCache(
133
+ new BookModel({ data: SAMPLE_DATA, reduceSet }),
134
+ { useSrcSet: false, reduceSet },
135
+ );
136
+ const $img = ic._serveImageElement(0);
137
+ expect($img[0].hasAttribute('srcset')).toBe(false);
138
+ });
139
+
140
+ test('sets srcset when useSrcSet=true', () => {
141
+ const reduceSet = Pow2ReduceSet;
142
+ const ic = new ImageCache(
143
+ new BookModel({ data: SAMPLE_DATA, reduceSet }),
144
+ { useSrcSet: true, reduceSet },
145
+ );
146
+ const $img = ic._serveImageElement(0, 9);
147
+ expect($img.attr('srcset')).toBeTruthy();
148
+ });
149
+ });
150
+ });