@internetarchive/bookreader 5.0.0-8 → 5.0.0-80

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 (313) hide show
  1. package/.eslintrc.js +17 -15
  2. package/.github/workflows/node.js.yml +73 -10
  3. package/.github/workflows/npm-publish.yml +6 -20
  4. package/.testcaferc.js +10 -0
  5. package/BookReader/BookReader.css +398 -1133
  6. package/BookReader/BookReader.js +1 -1
  7. package/BookReader/BookReader.js.LICENSE.txt +20 -20
  8. package/BookReader/BookReader.js.map +1 -1
  9. package/BookReader/ia-bookreader-bundle.js +1782 -0
  10. package/BookReader/ia-bookreader-bundle.js.LICENSE.txt +7 -0
  11. package/BookReader/ia-bookreader-bundle.js.map +1 -0
  12. package/BookReader/icons/1up.svg +1 -1
  13. package/BookReader/icons/2up.svg +1 -1
  14. package/BookReader/icons/advance.svg +1 -1
  15. package/BookReader/icons/chevron-right.svg +1 -1
  16. package/BookReader/icons/close-circle-dark.svg +1 -1
  17. package/BookReader/icons/close-circle.svg +1 -1
  18. package/BookReader/icons/fullscreen.svg +1 -1
  19. package/BookReader/icons/fullscreen_exit.svg +1 -1
  20. package/BookReader/icons/hamburger.svg +1 -1
  21. package/BookReader/icons/left-arrow.svg +1 -1
  22. package/BookReader/icons/magnify-minus.svg +1 -1
  23. package/BookReader/icons/magnify-plus.svg +1 -1
  24. package/BookReader/icons/magnify.svg +1 -1
  25. package/BookReader/icons/pause.svg +1 -1
  26. package/BookReader/icons/play.svg +1 -1
  27. package/BookReader/icons/playback-speed.svg +1 -1
  28. package/BookReader/icons/read-aloud.svg +1 -1
  29. package/BookReader/icons/review.svg +1 -1
  30. package/BookReader/icons/thumbnails.svg +1 -1
  31. package/BookReader/icons/voice.svg +1 -0
  32. package/BookReader/icons/volume-full.svg +1 -1
  33. package/BookReader/images/BRicons.svg +3 -3
  34. package/BookReader/images/books_graphic.svg +1 -1
  35. package/BookReader/images/icon_book.svg +1 -1
  36. package/BookReader/images/icon_bookmark.svg +1 -1
  37. package/BookReader/images/icon_gear.svg +1 -1
  38. package/BookReader/images/icon_hamburger.svg +1 -1
  39. package/BookReader/images/icon_home.svg +1 -1
  40. package/BookReader/images/icon_info.svg +1 -1
  41. package/BookReader/images/icon_one_page.svg +1 -1
  42. package/BookReader/images/icon_pause.svg +1 -1
  43. package/BookReader/images/icon_play.svg +1 -1
  44. package/BookReader/images/icon_playback-rate.svg +1 -1
  45. package/BookReader/images/icon_search_button.svg +1 -1
  46. package/BookReader/images/icon_share.svg +1 -1
  47. package/BookReader/images/icon_skip-ahead.svg +1 -1
  48. package/BookReader/images/icon_skip-back.svg +1 -1
  49. package/BookReader/images/icon_speaker.svg +1 -1
  50. package/BookReader/images/icon_speaker_open.svg +1 -1
  51. package/BookReader/images/icon_thumbnails.svg +1 -1
  52. package/BookReader/images/icon_toc.svg +1 -1
  53. package/BookReader/images/icon_two_pages.svg +1 -1
  54. package/BookReader/images/marker_chap-off.svg +1 -1
  55. package/BookReader/images/marker_chap-on.svg +1 -1
  56. package/BookReader/images/marker_srch-on.svg +1 -1
  57. package/BookReader/jquery-3.js +2 -0
  58. package/BookReader/jquery-3.js.LICENSE.txt +24 -0
  59. package/BookReader/plugins/plugin.archive_analytics.js +1 -1
  60. package/BookReader/plugins/plugin.archive_analytics.js.map +1 -1
  61. package/BookReader/plugins/plugin.autoplay.js +1 -1
  62. package/BookReader/plugins/plugin.autoplay.js.map +1 -1
  63. package/BookReader/plugins/plugin.chapters.js +25 -1
  64. package/BookReader/plugins/plugin.chapters.js.LICENSE.txt +1 -0
  65. package/BookReader/plugins/plugin.chapters.js.map +1 -1
  66. package/BookReader/plugins/plugin.iframe.js +1 -1
  67. package/BookReader/plugins/plugin.iframe.js.map +1 -1
  68. package/BookReader/plugins/plugin.iiif.js +2 -0
  69. package/BookReader/plugins/plugin.iiif.js.map +1 -0
  70. package/BookReader/plugins/plugin.resume.js +1 -1
  71. package/BookReader/plugins/plugin.resume.js.map +1 -1
  72. package/BookReader/plugins/plugin.search.js +2 -1
  73. package/BookReader/plugins/plugin.search.js.LICENSE.txt +1 -0
  74. package/BookReader/plugins/plugin.search.js.map +1 -1
  75. package/BookReader/plugins/plugin.text_selection.js +2 -1
  76. package/BookReader/plugins/plugin.text_selection.js.LICENSE.txt +1 -0
  77. package/BookReader/plugins/plugin.text_selection.js.map +1 -1
  78. package/BookReader/plugins/plugin.tts.js +1 -1
  79. package/BookReader/plugins/plugin.tts.js.LICENSE.txt +2 -0
  80. package/BookReader/plugins/plugin.tts.js.map +1 -1
  81. package/BookReader/plugins/plugin.url.js +1 -1
  82. package/BookReader/plugins/plugin.url.js.map +1 -1
  83. package/BookReader/plugins/plugin.vendor-fullscreen.js +1 -1
  84. package/BookReader/plugins/plugin.vendor-fullscreen.js.map +1 -1
  85. package/BookReader/webcomponents-bundle.js +3 -0
  86. package/BookReader/webcomponents-bundle.js.LICENSE.txt +9 -0
  87. package/BookReader/webcomponents-bundle.js.map +1 -0
  88. package/BookReaderDemo/BookReaderDemo.css +18 -19
  89. package/BookReaderDemo/BookReaderJSAdvanced.js +0 -3
  90. package/BookReaderDemo/BookReaderJSAutoplay.js +4 -1
  91. package/BookReaderDemo/BookReaderJSSimple.js +1 -0
  92. package/BookReaderDemo/IADemoBr.js +147 -0
  93. package/BookReaderDemo/demo-advanced.html +2 -2
  94. package/BookReaderDemo/demo-autoplay.html +2 -3
  95. package/BookReaderDemo/demo-embed-iframe-src.html +2 -1
  96. package/BookReaderDemo/demo-fullscreen-mobile.html +3 -5
  97. package/BookReaderDemo/demo-fullscreen.html +2 -4
  98. package/BookReaderDemo/demo-iiif.html +99 -12
  99. package/BookReaderDemo/demo-internetarchive.html +214 -18
  100. package/BookReaderDemo/demo-multiple.html +2 -1
  101. package/BookReaderDemo/demo-preview-pages.html +2 -1
  102. package/BookReaderDemo/demo-simple.html +2 -1
  103. package/BookReaderDemo/demo-vendor-fullscreen.html +2 -4
  104. package/BookReaderDemo/ia-multiple-volumes-manifest.js +170 -0
  105. package/BookReaderDemo/immersion-1up.html +2 -2
  106. package/BookReaderDemo/immersion-mode.html +2 -4
  107. package/BookReaderDemo/toggle_controls.html +3 -2
  108. package/BookReaderDemo/view_mode.html +2 -1
  109. package/BookReaderDemo/viewmode-cycle.html +2 -3
  110. package/CHANGELOG.md +536 -33
  111. package/README.md +14 -1
  112. package/babel.config.js +20 -0
  113. package/codecov.yml +6 -0
  114. package/index.html +4 -1
  115. package/jsconfig.json +19 -0
  116. package/netlify.toml +9 -0
  117. package/package.json +70 -60
  118. package/renovate.json +52 -0
  119. package/scripts/preversion.js +0 -1
  120. package/src/BookNavigator/assets/bookmark-colors.js +1 -1
  121. package/src/BookNavigator/assets/button-base.js +4 -2
  122. package/src/BookNavigator/assets/ia-logo.js +17 -0
  123. package/src/BookNavigator/assets/icon_checkmark.js +1 -1
  124. package/src/BookNavigator/assets/icon_close.js +1 -1
  125. package/src/BookNavigator/book-navigator.js +590 -0
  126. package/src/BookNavigator/bookmarks/bookmark-button.js +3 -2
  127. package/src/BookNavigator/bookmarks/bookmark-edit.js +3 -4
  128. package/src/BookNavigator/bookmarks/bookmarks-list.js +2 -3
  129. package/src/BookNavigator/bookmarks/bookmarks-loginCTA.js +3 -8
  130. package/src/BookNavigator/bookmarks/bookmarks-provider.js +27 -17
  131. package/src/BookNavigator/bookmarks/ia-bookmarks.js +116 -67
  132. package/src/BookNavigator/delete-modal-actions.js +1 -1
  133. package/src/BookNavigator/downloads/downloads-provider.js +36 -21
  134. package/src/BookNavigator/downloads/downloads.js +41 -25
  135. package/src/BookNavigator/search/search-provider.js +49 -27
  136. package/src/BookNavigator/search/search-results.js +23 -9
  137. package/src/BookNavigator/sharing.js +27 -0
  138. package/src/BookNavigator/viewable-files.js +95 -0
  139. package/src/BookNavigator/visual-adjustments/visual-adjustments-provider.js +11 -10
  140. package/src/BookNavigator/visual-adjustments/visual-adjustments.js +3 -3
  141. package/src/BookReader/BookModel.js +64 -34
  142. package/src/BookReader/DragScrollable.js +233 -0
  143. package/src/BookReader/Mode1Up.js +56 -351
  144. package/src/BookReader/Mode1UpLit.js +388 -0
  145. package/src/BookReader/Mode2Up.js +73 -1318
  146. package/src/BookReader/Mode2UpLit.js +776 -0
  147. package/src/BookReader/ModeCoordinateSpace.js +29 -0
  148. package/src/BookReader/ModeSmoothZoom.js +312 -0
  149. package/src/BookReader/ModeThumb.js +18 -12
  150. package/src/BookReader/Navbar/Navbar.js +14 -40
  151. package/src/BookReader/PageContainer.js +81 -6
  152. package/src/BookReader/ReduceSet.js +1 -1
  153. package/src/BookReader/Toolbar/Toolbar.js +10 -37
  154. package/src/BookReader/events.js +2 -3
  155. package/src/BookReader/options.js +27 -2
  156. package/src/BookReader/utils/HTMLDimensionsCacher.js +44 -0
  157. package/src/BookReader/utils/ScrollClassAdder.js +31 -0
  158. package/src/BookReader/utils/SelectionObserver.js +45 -0
  159. package/src/BookReader/utils.js +118 -13
  160. package/src/BookReader.js +427 -1061
  161. package/src/assets/icons/magnify-minus.svg +3 -7
  162. package/src/assets/icons/magnify-plus.svg +3 -7
  163. package/src/assets/icons/voice.svg +1 -0
  164. package/src/css/BookReader.scss +1 -5
  165. package/src/css/_BRBookmarks.scss +1 -1
  166. package/src/css/_BRComponent.scss +1 -1
  167. package/src/css/_BRmain.scss +16 -3
  168. package/src/css/_BRnav.scss +12 -39
  169. package/src/css/_BRpages.scss +149 -40
  170. package/src/css/_BRsearch.scss +68 -25
  171. package/src/css/_BRtoolbar.scss +5 -5
  172. package/src/css/_TextSelection.scss +87 -27
  173. package/src/css/_colorbox.scss +2 -2
  174. package/src/css/_controls.scss +20 -7
  175. package/src/css/_icons.scss +1 -1
  176. package/src/ia-bookreader/ia-bookreader.js +224 -0
  177. package/src/plugins/plugin.archive_analytics.js +3 -3
  178. package/src/plugins/plugin.autoplay.js +5 -11
  179. package/src/plugins/plugin.chapters.js +237 -191
  180. package/src/plugins/plugin.iiif.js +151 -0
  181. package/src/plugins/plugin.resume.js +3 -3
  182. package/src/plugins/plugin.text_selection.js +464 -134
  183. package/src/plugins/plugin.vendor-fullscreen.js +4 -4
  184. package/src/plugins/search/plugin.search.js +142 -125
  185. package/src/plugins/search/utils.js +43 -0
  186. package/src/plugins/search/view.js +33 -58
  187. package/src/plugins/tts/AbstractTTSEngine.js +71 -40
  188. package/src/plugins/tts/FestivalTTSEngine.js +13 -14
  189. package/src/plugins/tts/PageChunk.js +15 -21
  190. package/src/plugins/tts/PageChunkIterator.js +8 -12
  191. package/src/plugins/tts/WebTTSEngine.js +87 -71
  192. package/src/plugins/tts/plugin.tts.js +96 -127
  193. package/src/plugins/tts/utils.js +15 -25
  194. package/src/plugins/url/UrlPlugin.js +191 -0
  195. package/src/plugins/{plugin.url.js → url/plugin.url.js} +45 -16
  196. package/src/util/browserSniffing.js +22 -0
  197. package/src/util/docCookies.js +21 -2
  198. package/tests/e2e/README.md +37 -0
  199. package/tests/e2e/autoplay.test.js +2 -2
  200. package/tests/e2e/base.test.js +8 -16
  201. package/tests/e2e/helpers/base.js +53 -48
  202. package/tests/e2e/helpers/debug.js +1 -1
  203. package/tests/e2e/helpers/params.js +17 -0
  204. package/tests/e2e/helpers/rightToLeft.js +8 -14
  205. package/tests/e2e/helpers/search.js +73 -0
  206. package/tests/e2e/models/Navigation.js +20 -37
  207. package/tests/e2e/rightToLeft.test.js +4 -5
  208. package/tests/e2e/viewmode.test.js +40 -33
  209. package/tests/jest/BookNavigator/book-navigator.test.js +661 -0
  210. package/tests/jest/BookNavigator/bookmarks/bookmark-button.test.js +43 -0
  211. package/tests/{karma → jest}/BookNavigator/bookmarks/bookmark-edit.test.js +25 -26
  212. package/tests/{karma → jest}/BookNavigator/bookmarks/bookmarks-list.test.js +41 -42
  213. package/tests/jest/BookNavigator/bookmarks/ia-bookmarks.test.js +45 -0
  214. package/tests/jest/BookNavigator/downloads/downloads-provider.test.js +67 -0
  215. package/tests/jest/BookNavigator/downloads/downloads.test.js +53 -0
  216. package/tests/jest/BookNavigator/search/search-provider.test.js +167 -0
  217. package/tests/{karma → jest}/BookNavigator/search/search-results.test.js +109 -60
  218. package/tests/jest/BookNavigator/sharing/sharing-provider.test.js +49 -0
  219. package/tests/jest/BookNavigator/viewable-files/viewable-files-provider.test.js +80 -0
  220. package/tests/jest/BookNavigator/visual-adjustments.test.js +200 -0
  221. package/tests/{BookReader → jest/BookReader}/BookModel.test.js +74 -14
  222. package/tests/jest/BookReader/BookReaderPublicFunctions.test.js +193 -0
  223. package/tests/{BookReader → jest/BookReader}/ImageCache.test.js +4 -4
  224. package/tests/jest/BookReader/Mode1UpLit.test.js +73 -0
  225. package/tests/jest/BookReader/Mode2Up.test.js +98 -0
  226. package/tests/jest/BookReader/Mode2UpLit.test.js +190 -0
  227. package/tests/jest/BookReader/ModeCoordinateSpace.test.js +16 -0
  228. package/tests/jest/BookReader/ModeSmoothZoom.test.js +218 -0
  229. package/tests/jest/BookReader/ModeThumb.test.js +71 -0
  230. package/tests/{BookReader → jest/BookReader}/Navbar/Navbar.test.js +10 -10
  231. package/tests/{BookReader → jest/BookReader}/PageContainer.test.js +88 -6
  232. package/tests/{BookReader → jest/BookReader}/ReduceSet.test.js +1 -1
  233. package/tests/{BookReader → jest/BookReader}/Toolbar/Toolbar.test.js +2 -2
  234. package/tests/jest/BookReader/utils/HTMLDimensionsCacher.test.js +59 -0
  235. package/tests/jest/BookReader/utils/ScrollClassAdder.test.js +49 -0
  236. package/tests/jest/BookReader/utils/SelectionObserver.test.js +57 -0
  237. package/tests/{BookReader → jest/BookReader}/utils/classes.test.js +1 -1
  238. package/tests/jest/BookReader/utils.test.js +229 -0
  239. package/tests/jest/BookReader.keyboard.test.js +190 -0
  240. package/tests/{BookReader.options.test.js → jest/BookReader.options.test.js} +9 -1
  241. package/tests/{BookReader.test.js → jest/BookReader.test.js} +26 -37
  242. package/tests/{plugins → jest/plugins}/plugin.archive_analytics.test.js +2 -2
  243. package/tests/{plugins → jest/plugins}/plugin.autoplay.test.js +4 -4
  244. package/tests/jest/plugins/plugin.chapters.test.js +195 -0
  245. package/tests/{plugins → jest/plugins}/plugin.iframe.test.js +2 -2
  246. package/tests/{plugins → jest/plugins}/plugin.resume.test.js +3 -3
  247. package/tests/jest/plugins/plugin.text_selection.test.js +317 -0
  248. package/tests/{plugins → jest/plugins}/plugin.vendor-fullscreen.test.js +2 -2
  249. package/tests/{plugins → jest/plugins}/search/plugin.search.test.js +25 -47
  250. package/tests/{plugins → jest/plugins}/search/plugin.search.view.test.js +39 -6
  251. package/tests/jest/plugins/search/utils.js +25 -0
  252. package/tests/jest/plugins/search/utils.test.js +29 -0
  253. package/tests/{plugins → jest/plugins}/tts/AbstractTTSEngine.test.js +29 -9
  254. package/tests/{plugins → jest/plugins}/tts/FestivalTTSEngine.test.js +4 -4
  255. package/tests/{plugins → jest/plugins}/tts/PageChunk.test.js +1 -1
  256. package/tests/{plugins → jest/plugins}/tts/PageChunkIterator.test.js +3 -3
  257. package/tests/{plugins → jest/plugins}/tts/WebTTSEngine.test.js +47 -1
  258. package/tests/{plugins → jest/plugins}/tts/utils.test.js +1 -60
  259. package/tests/jest/plugins/url/UrlPlugin.test.js +198 -0
  260. package/tests/{plugins → jest/plugins/url}/plugin.url.test.js +53 -14
  261. package/tests/jest/setup.js +3 -0
  262. package/tests/{util → jest/util}/browserSniffing.test.js +1 -1
  263. package/tests/jest/util/docCookies.test.js +24 -0
  264. package/tests/{util → jest/util}/strings.test.js +1 -1
  265. package/tests/{utils.js → jest/utils.js} +38 -0
  266. package/webpack.config.js +12 -6
  267. package/.babelrc +0 -12
  268. package/.dependabot/config.yml +0 -6
  269. package/.testcaferc.json +0 -5
  270. package/BookReader/bookreader-component-bundle.js +0 -1450
  271. package/BookReader/bookreader-component-bundle.js.LICENSE.txt +0 -38
  272. package/BookReader/bookreader-component-bundle.js.map +0 -1
  273. package/BookReader/jquery-1.10.1.js +0 -2
  274. package/BookReader/jquery-1.10.1.js.LICENSE.txt +0 -24
  275. package/BookReader/plugins/plugin.menu_toggle.js +0 -2
  276. package/BookReader/plugins/plugin.menu_toggle.js.map +0 -1
  277. package/BookReader/plugins/plugin.mobile_nav.js +0 -2
  278. package/BookReader/plugins/plugin.mobile_nav.js.map +0 -1
  279. package/BookReaderDemo/IIIFBookReader.js +0 -207
  280. package/BookReaderDemo/bookreader-template-bundle.js +0 -7178
  281. package/BookReaderDemo/demo-iiif.js +0 -26
  282. package/BookReaderDemo/demo-plugin-menu-toggle.html +0 -34
  283. package/karma.conf.js +0 -23
  284. package/src/BookNavigator/BookModel.js +0 -14
  285. package/src/BookNavigator/BookNavigator.js +0 -446
  286. package/src/BookNavigator/assets/book-loader.js +0 -27
  287. package/src/BookNavigator/br-fullscreen-mgr.js +0 -83
  288. package/src/BookNavigator/search/a-search-result.js +0 -55
  289. package/src/BookReader/DebugConsole.js +0 -54
  290. package/src/BookReaderComponent/BookReaderComponent.js +0 -112
  291. package/src/ItemNavigator/ItemNavigator.js +0 -376
  292. package/src/ItemNavigator/providers/sharing.js +0 -29
  293. package/src/css/_MobileNav.scss +0 -194
  294. package/src/dragscrollable-br.js +0 -261
  295. package/src/lit-wrapper.js +0 -2
  296. package/src/plugins/menu_toggle/plugin.menu_toggle.js +0 -324
  297. package/src/plugins/plugin.mobile_nav.js +0 -287
  298. package/tests/BookReader/BookReaderPublicFunctions.test.js +0 -171
  299. package/tests/BookReader/DebugConsole.test.js +0 -25
  300. package/tests/BookReader/Mode1Up.test.js +0 -164
  301. package/tests/BookReader/Mode2Up.test.js +0 -247
  302. package/tests/BookReader/utils.test.js +0 -109
  303. package/tests/e2e/helpers/desktopSearch.js +0 -72
  304. package/tests/e2e/helpers/mobileSearch.js +0 -85
  305. package/tests/e2e/ia-production/ia-prod-base.js +0 -17
  306. package/tests/karma/BookNavigator/book-navigator.test.js +0 -132
  307. package/tests/karma/BookNavigator/search/search-provider.test.js +0 -23
  308. package/tests/karma/BookNavigator/visual-adjustments.test.js +0 -201
  309. package/tests/plugins/menu_toggle/plugin.menu_toggle.test.js +0 -68
  310. package/tests/plugins/plugin.chapters.test.js +0 -130
  311. package/tests/plugins/plugin.mobile_nav.test.js +0 -66
  312. package/tests/plugins/plugin.text_selection.test.js +0 -203
  313. package/tests/util/docCookies.test.js +0 -15
@@ -0,0 +1,190 @@
1
+ import BookReader from '@/src/BookReader.js';
2
+ import * as utils from '@/src/BookReader/utils.js';
3
+
4
+ let br;
5
+ beforeAll(() => {
6
+ document.body.innerHTML = '<div id="BookReader">';
7
+ br = new BookReader();
8
+ });
9
+
10
+ afterEach(() => {
11
+ jest.clearAllMocks();
12
+ });
13
+
14
+ /**
15
+ * Only run init() once. Otherwise multiple EventListeners will be added.
16
+ */
17
+ test('Initialzation enables IntersectionObserver and defaults', () => {
18
+ const observe = jest.fn();
19
+ window.IntersectionObserver = jest.fn(() => ({
20
+ observe
21
+ }));
22
+ br.init();
23
+ expect(br.hasKeyFocus).toBe(true);
24
+ expect(observe).toHaveBeenCalledTimes(1);
25
+ });
26
+
27
+ describe('Keyboard shortcuts turned off', () => {
28
+
29
+ test('Focus flag disables', () => {
30
+ br.next = jest.fn();
31
+ br.hasKeyFocus = false;
32
+ const keyEvent = new KeyboardEvent('keydown', {'key': 'ArrowDown'});
33
+ keyEvent.preventDefault = jest.fn();
34
+ document.dispatchEvent(keyEvent);
35
+ expect(br.next).toHaveBeenCalledTimes(0);
36
+ expect(keyEvent.preventDefault).toHaveBeenCalledTimes(0);
37
+ // Must reset for following tests
38
+ br.hasKeyFocus = true;
39
+ });
40
+
41
+ test('Input active disables', () => {
42
+ // eslint-disable-next-line no-import-assign
43
+ utils.isInputActive = jest.fn(() => true);
44
+ br.next = jest.fn();
45
+ const keyEvent = new KeyboardEvent('keydown', {'key': 'ArrowDown'});
46
+ keyEvent.preventDefault = jest.fn();
47
+ document.dispatchEvent(keyEvent);
48
+ expect(br.next).toHaveBeenCalledTimes(0);
49
+ expect(keyEvent.preventDefault).toHaveBeenCalledTimes(0);
50
+ // Must reset for following tests
51
+ utils.isInputActive.mockReset();
52
+ });
53
+
54
+ });
55
+
56
+ describe('Keyboard shortcuts', () => {
57
+
58
+ test('Home key', () => {
59
+ br.first = jest.fn();
60
+ const keyEvent = new KeyboardEvent('keydown', {'key': 'Home'});
61
+ keyEvent.preventDefault = jest.fn();
62
+ document.dispatchEvent(keyEvent);
63
+ expect(br.first).toHaveBeenCalledTimes(1);
64
+ expect(keyEvent.preventDefault).toHaveBeenCalledTimes(1);
65
+ });
66
+
67
+ test('End key', () => {
68
+ br.last = jest.fn();
69
+ const keyEvent = new KeyboardEvent('keydown', {'key': 'End'});
70
+ keyEvent.preventDefault = jest.fn();
71
+ document.dispatchEvent(keyEvent);
72
+ expect(br.last).toHaveBeenCalledTimes(1);
73
+ expect(keyEvent.preventDefault).toHaveBeenCalledTimes(1);
74
+ });
75
+
76
+ test('ArrowDown key', () => {
77
+ br.mode = br.constMode2up;
78
+ br.next = jest.fn();
79
+ const keyEvent = new KeyboardEvent('keydown', {'key': 'ArrowDown'});
80
+ keyEvent.preventDefault = jest.fn();
81
+ document.dispatchEvent(keyEvent);
82
+ expect(br.next).toHaveBeenCalledTimes(1);
83
+ expect(keyEvent.preventDefault).toHaveBeenCalledTimes(1);
84
+ });
85
+
86
+ test('PageDown key', () => {
87
+ br.mode = br.constMode2up;
88
+ br.next = jest.fn();
89
+ const keyEvent = new KeyboardEvent('keydown', {'key': 'PageDown'});
90
+ keyEvent.preventDefault = jest.fn();
91
+ document.dispatchEvent(keyEvent);
92
+ expect(br.next).toHaveBeenCalledTimes(1);
93
+ expect(keyEvent.preventDefault).toHaveBeenCalledTimes(1);
94
+ });
95
+
96
+ test('ArrowUp key', () => {
97
+ br.mode = br.constMode2up;
98
+ br.prev = jest.fn();
99
+ const keyEvent = new KeyboardEvent('keydown', {'key': 'ArrowUp'});
100
+ keyEvent.preventDefault = jest.fn();
101
+ document.dispatchEvent(keyEvent);
102
+ expect(br.prev).toHaveBeenCalledTimes(1);
103
+ expect(keyEvent.preventDefault).toHaveBeenCalledTimes(1);
104
+ });
105
+
106
+ test('PageUp key', () => {
107
+ br.mode = br.constMode2up;
108
+ br.prev = jest.fn();
109
+ const keyEvent = new KeyboardEvent('keydown', {'key': 'PageUp'});
110
+ keyEvent.preventDefault = jest.fn();
111
+ document.dispatchEvent(keyEvent);
112
+ expect(br.prev).toHaveBeenCalledTimes(1);
113
+ expect(keyEvent.preventDefault).toHaveBeenCalledTimes(1);
114
+ });
115
+
116
+ test('ArrowLeft key', () => {
117
+ br.mode = br.constMode2up;
118
+ br.left = jest.fn();
119
+ const keyEvent = new KeyboardEvent('keydown', {'key': 'ArrowLeft'});
120
+ keyEvent.preventDefault = jest.fn();
121
+ document.dispatchEvent(keyEvent);
122
+ expect(br.left).toHaveBeenCalledTimes(1);
123
+ expect(keyEvent.preventDefault).toHaveBeenCalledTimes(1);
124
+ });
125
+
126
+ test('ArrowRight key', () => {
127
+ br.mode = br.constMode2up;
128
+ br.right = jest.fn();
129
+ const keyEvent = new KeyboardEvent('keydown', {'key': 'ArrowRight'});
130
+ keyEvent.preventDefault = jest.fn();
131
+ document.dispatchEvent(keyEvent);
132
+ expect(br.right).toHaveBeenCalledTimes(1);
133
+ expect(keyEvent.preventDefault).toHaveBeenCalledTimes(1);
134
+ });
135
+
136
+ test('Subtract key', () => {
137
+ br.zoom = jest.fn();
138
+ const keyEvent = new KeyboardEvent('keydown', {'key': 'Subtract'});
139
+ keyEvent.preventDefault = jest.fn();
140
+ document.dispatchEvent(keyEvent);
141
+ expect(br.zoom).toHaveBeenCalledTimes(1);
142
+ expect(keyEvent.preventDefault).toHaveBeenCalledTimes(1);
143
+ });
144
+
145
+ test('- key', () => {
146
+ br.zoom = jest.fn();
147
+ const keyEvent = new KeyboardEvent('keydown', {'key': '-'});
148
+ keyEvent.preventDefault = jest.fn();
149
+ document.dispatchEvent(keyEvent);
150
+ expect(br.zoom).toHaveBeenCalledTimes(1);
151
+ expect(keyEvent.preventDefault).toHaveBeenCalledTimes(1);
152
+ });
153
+
154
+ test('Add key', () => {
155
+ br.zoom = jest.fn();
156
+ const keyEvent = new KeyboardEvent('keydown', {'key': 'Add'});
157
+ keyEvent.preventDefault = jest.fn();
158
+ document.dispatchEvent(keyEvent);
159
+ expect(br.zoom).toHaveBeenCalledTimes(1);
160
+ expect(keyEvent.preventDefault).toHaveBeenCalledTimes(1);
161
+ });
162
+
163
+ test('+ key', () => {
164
+ br.zoom = jest.fn();
165
+ const keyEvent = new KeyboardEvent('keydown', {'key': '+'});
166
+ keyEvent.preventDefault = jest.fn();
167
+ document.dispatchEvent(keyEvent);
168
+ expect(br.zoom).toHaveBeenCalledTimes(1);
169
+ expect(keyEvent.preventDefault).toHaveBeenCalledTimes(1);
170
+ });
171
+
172
+ test('= key', () => {
173
+ br.zoom = jest.fn();
174
+ const keyEvent = new KeyboardEvent('keydown', {'key': '='});
175
+ keyEvent.preventDefault = jest.fn();
176
+ document.dispatchEvent(keyEvent);
177
+ expect(br.zoom).toHaveBeenCalledTimes(1);
178
+ expect(keyEvent.preventDefault).toHaveBeenCalledTimes(1);
179
+ });
180
+
181
+ test('F key', () => {
182
+ br.toggleFullscreen = jest.fn();
183
+ const keyEvent = new KeyboardEvent('keydown', {'key': 'F'});
184
+ keyEvent.preventDefault = jest.fn();
185
+ document.dispatchEvent(keyEvent);
186
+ expect(br.toggleFullscreen).toHaveBeenCalledTimes(1);
187
+ expect(keyEvent.preventDefault).toHaveBeenCalledTimes(1);
188
+ });
189
+
190
+ });
@@ -1,5 +1,5 @@
1
1
 
2
- import BookReader from '../src/BookReader.js';
2
+ import BookReader from '@/src/BookReader.js';
3
3
 
4
4
  beforeAll(() => {
5
5
  document.body.innerHTML = '<div id="BookReader">';
@@ -36,4 +36,12 @@ describe('BookReader options', () => {
36
36
  expect(br.options.autoResize).toBe(true);
37
37
  });
38
38
  });
39
+
40
+ describe('`showNavbar`', () => {
41
+ it('is on by default', () => {
42
+ const br = new BookReader();
43
+ br.init();
44
+ expect(br.options.showNavbar).toBe(true);
45
+ });
46
+ });
39
47
  });
@@ -1,7 +1,7 @@
1
1
 
2
- import BookReader from '../src/BookReader.js';
3
- import '../src/plugins/plugin.resume.js';
4
- import '../src/plugins/plugin.url.js';
2
+ import BookReader, {_modeStringToNumber} from '@/src/BookReader.js';
3
+ import '@/src/plugins/plugin.resume.js';
4
+ import '@/src/plugins/url/plugin.url.js';
5
5
 
6
6
  let br;
7
7
  beforeAll(() => {
@@ -124,7 +124,7 @@ test('has suppressFragmentChange false when init with fragment', () => {
124
124
  test('has suppressFragmentChange false when init with hash fragment', () => {
125
125
  br.getResumeValue = jest.fn(() => null);
126
126
  br.urlReadFragment = jest.fn(() => '');
127
- br.urlReadHashFragment = jest.fn(() => 'mode/1up')
127
+ br.urlReadHashFragment = jest.fn(() => 'mode/1up');
128
128
  br.switchMode = jest.fn();
129
129
  br.options.urlMode = 'history',
130
130
 
@@ -157,39 +157,20 @@ test('does not add q= term to urlMode=hash query string', () => {
157
157
  )).toBe('?name=value');
158
158
  });
159
159
 
160
- test('_getPageURISrcset with 0 page book', () => {
161
- br._models.book.getNumLeafs = jest.fn(() => 0);
162
- br._models.book.getPageURI = jest.fn((index, scale, rotate) => "correctURL.png&scale=" + scale);
163
- br.init();
164
- expect(br._getPageURISrcset(5, undefined, undefined)).toBe("");
165
- });
166
-
167
- test('_getPageURISrcset with negative index', () => {
168
- br._models.book.getNumLeafs = jest.fn(() => 0);
169
- br._models.book.getPageURI = jest.fn((index, scale, rotate) => "correctURL.png&scale=" + scale);
170
- br.init();
171
- expect(br._getPageURISrcset(-7, undefined, undefined)).toBe("");
172
- });
173
-
174
- test('_getPageURISrcset with 0 elements in srcset', () => {
175
- br._models.book.getNumLeafs = jest.fn(() => 30);
176
- br._models.book.getPageURI = jest.fn((index, scale, rotate) => "correctURL.png&scale=" + scale);
177
- br.init();
178
- expect(br._getPageURISrcset(5, 1, undefined)).toBe("");
179
- });
180
-
181
- test('_getPageURISrcset with 2 elements in srcset', () => {
182
- br._models.book.getNumLeafs = jest.fn(() => 30);
183
- br._models.book.getPageURI = jest.fn((index, scale, rotate) => "correctURL.png&scale=" + scale);
184
- br.init();
185
- expect(br._getPageURISrcset(5, 5, undefined)).toBe("correctURL.png&scale=2 2x, correctURL.png&scale=1 4x");
186
- });
187
-
188
- test('_getPageURISrcset with the most elements in srcset', () => {
189
- br._models.book.getNumLeafs = jest.fn(() => 30);
190
- br._models.book.getPageURI = jest.fn((index, scale, rotate) => "correctURL.png&scale=" + scale);
191
- br.init();
192
- expect(br._getPageURISrcset(5, 35, undefined)).toBe("correctURL.png&scale=16 2x, correctURL.png&scale=8 4x, correctURL.png&scale=4 8x, correctURL.png&scale=2 16x, correctURL.png&scale=1 32x");
160
+ describe('Navigation Bars', () => {
161
+ test('Standard navigation is being used by default', () => {
162
+ br.initNavbar = jest.fn();
163
+ br.options.ui = '';
164
+ br.init();
165
+ expect(br.initNavbar).toHaveBeenCalledTimes(1);
166
+ });
167
+ test('Standard navigation is being used by default - when bookreader is embedded', () => {
168
+ br.initNavbar = jest.fn();
169
+ br.options.ui = 'embed';
170
+ br.init();
171
+ expect(br.initNavbar).toHaveBeenCalledTimes(1);
172
+ expect(br.options.ui).toEqual('embed');
173
+ });
193
174
  });
194
175
 
195
176
  describe('quantizeReduce', () => {
@@ -299,3 +280,11 @@ describe('nextReduce', () => {
299
280
  });
300
281
  });
301
282
  });
283
+
284
+ describe('_modeStringToNumber', () => {
285
+ test('Returns correct number', () => {
286
+ expect(_modeStringToNumber('mode/1up')).toBe(1);
287
+ expect(_modeStringToNumber('mode/2up')).toBe(2);
288
+ expect(_modeStringToNumber('mode/thumb')).toBe(3);
289
+ });
290
+ });
@@ -1,6 +1,6 @@
1
1
  import sinon from 'sinon';
2
- import BookReader from '../../src/BookReader.js';
3
- import '../../src/plugins/plugin.archive_analytics.js';
2
+ import BookReader from '@/src/BookReader.js';
3
+ import '@/src/plugins/plugin.archive_analytics.js';
4
4
 
5
5
  describe('archiveAnalyticsSendEvent', () => {
6
6
  const sendEvent = BookReader.prototype.archiveAnalyticsSendEvent;
@@ -1,6 +1,6 @@
1
1
 
2
- import BookReader from '../../src/BookReader.js';
3
- import '../../src/plugins/plugin.autoplay.js';
2
+ import BookReader from '@/src/BookReader.js';
3
+ import '@/src/plugins/plugin.autoplay.js';
4
4
 
5
5
 
6
6
  let br;
@@ -38,12 +38,12 @@ describe('Plugin: Menu Toggle', () => {
38
38
  });
39
39
  test('autoplay will run without `flipSpeed` parameters', () => {
40
40
  const initialAutoTimer = br.autoTimer;
41
- br.flipFwdToIndex = jest.fn();
41
+ br.next = jest.fn();
42
42
  br.autoStop = jest.fn();
43
43
  br.init();
44
44
  br.autoToggle();
45
45
  // internally referenced functions that fire
46
- expect(br.flipFwdToIndex).toHaveBeenCalledTimes(1);
46
+ expect(br.next).toHaveBeenCalledTimes(1);
47
47
 
48
48
  expect(initialAutoTimer).toBeFalsy();
49
49
  // br.autoTimer changes when autoToggle turns on
@@ -0,0 +1,195 @@
1
+ import sinon from "sinon";
2
+
3
+ import BookReader from "@/src/BookReader.js";
4
+ import "@/src/plugins/plugin.chapters.js";
5
+ import { BookModel } from "@/src/BookReader/BookModel";
6
+ import { deepCopy } from "../utils";
7
+ /** @typedef {import('@/src/plugins/plugin.chapters').TocEntry} TocEntry */
8
+
9
+ /** @type {TocEntry[]} */
10
+ const SAMPLE_TOC = [{
11
+ "pagenum": "3",
12
+ "level": 1,
13
+ "label": "CHAPTER I",
14
+ "type": { "key": "/type/toc_item" },
15
+ "title": "THE COUNTRY AND THE MISSION 1",
16
+ "pageIndex": 3,
17
+ }, {
18
+ "pagenum": "17",
19
+ "level": 1,
20
+ "label": "CHAPTER II",
21
+ "type": { "key": "/type/toc_item" },
22
+ "title": "THE COUNTRY AND THE MISSION 2",
23
+ "pageIndex": 17,
24
+ }, {
25
+ "pagenum": "undefined",
26
+ "level": 1,
27
+ "label": "CHAPTER III",
28
+ "type": { "key": "/type/toc_item" },
29
+ "title": "THE COUNTRY AND THE MISSION 3",
30
+ }, {
31
+ "pagenum": "40",
32
+ "level": 1,
33
+ "label": "CHAPTER IV",
34
+ "type": { "key": "/type/toc_item" },
35
+ "title": "THE COUNTRY AND THE MISSION 4",
36
+ "pageIndex": 40,
37
+ }];
38
+
39
+ /** @type {TocEntry[]} */
40
+ const SAMPLE_TOC_UNDEF = [
41
+ {
42
+ "level": 1,
43
+ "label": "CHAPTER I",
44
+ "type": { "key": "/type/toc_item" },
45
+ "title": "THE COUNTRY AND THE MISSION 1",
46
+ },
47
+ {
48
+ "level": 1,
49
+ "label": "CHAPTER II",
50
+ "type": { "key": "/type/toc_item" },
51
+ "title": "THE COUNTRY AND THE MISSION 2",
52
+ },
53
+ ];
54
+
55
+ /** @type {TocEntry[]} */
56
+ const SAMPLE_TOC_OPTION = [
57
+ {
58
+ "level": 1,
59
+ "title": "THE COUNTRY AND THE MISSION 1",
60
+ },
61
+ {
62
+ "level": 1,
63
+ "title": "THE COUNTRY AND THE MISSION 2",
64
+ },
65
+ ];
66
+
67
+ afterEach(() => {
68
+ sinon.restore();
69
+ });
70
+
71
+ describe("BRChaptersPlugin", () => {
72
+ beforeEach(() => {
73
+ sinon.stub(BookModel.prototype, "getPageIndex").callsFake((str) =>
74
+ parseFloat(str)
75
+ );
76
+ });
77
+
78
+ describe("_chaptersInit", () => {
79
+ test("does not render when no open library record", async () => {
80
+ const fakeBR = {
81
+ options: {},
82
+ getOpenLibraryRecord: async () => null,
83
+ _chaptersRender: sinon.stub(),
84
+ };
85
+ await BookReader.prototype._chapterInit.call(fakeBR);
86
+ expect(fakeBR._chaptersRender.callCount).toBe(0);
87
+ });
88
+
89
+ test("does not render when open library record with no TOC", async () => {
90
+ const fakeBR = {
91
+ options: {},
92
+ getOpenLibraryRecord: async () => ({ key: "/books/OL1M" }),
93
+ _chaptersRender: sinon.stub(),
94
+ };
95
+ await BookReader.prototype._chapterInit.call(fakeBR);
96
+ expect(fakeBR._chaptersRender.callCount).toBe(0);
97
+ });
98
+
99
+ test("renders if valid TOC on open library", async () => {
100
+ const fakeBR = {
101
+ options: {},
102
+ bind: sinon.stub(),
103
+ book: {
104
+ getPageIndex: (str) => parseFloat(str),
105
+ },
106
+ getOpenLibraryRecord: async () => ({
107
+ "title": "The Adventures of Sherlock Holmes",
108
+ "table_of_contents": deepCopy(SAMPLE_TOC_OPTION),
109
+ "ocaid": "adventureofsherl0000unse",
110
+ }),
111
+ _chaptersRender: sinon.stub(),
112
+ };
113
+ await BookReader.prototype._chapterInit.call(fakeBR);
114
+ expect(fakeBR._chaptersRender.callCount).toBe(1);
115
+ });
116
+
117
+ test("does not fetch open library record if table of contents in options", async () => {
118
+ const fakeBR = {
119
+ options: {
120
+ table_of_contents: deepCopy(SAMPLE_TOC_UNDEF),
121
+ },
122
+ bind: sinon.stub(),
123
+ getOpenLibraryRecord: sinon.stub(),
124
+ _chaptersRender: sinon.stub(),
125
+ };
126
+ await BookReader.prototype._chapterInit.call(fakeBR);
127
+ expect(fakeBR.getOpenLibraryRecord.callCount).toBe(0);
128
+ expect(fakeBR._chaptersRender.callCount).toBe(1);
129
+ });
130
+
131
+ test("converts leafs and pagenums to page index", async () => {
132
+ const table_of_contents = deepCopy(SAMPLE_TOC_UNDEF);
133
+ table_of_contents[0].leaf = 0;
134
+ table_of_contents[1].pagenum = '17';
135
+ const fakeBR = {
136
+ options: {
137
+ table_of_contents,
138
+ },
139
+ bind: sinon.stub(),
140
+ book: {
141
+ leafNumToIndex: (leaf) => leaf + 1,
142
+ getPageIndex: (str) => parseFloat(str),
143
+ },
144
+ _chaptersRender: sinon.stub(),
145
+ };
146
+ await BookReader.prototype._chapterInit.call(fakeBR);
147
+ expect(fakeBR._chaptersRender.callCount).toBe(1);
148
+ expect(fakeBR._tocEntries[0].pageIndex).toBe(1);
149
+ expect(fakeBR._tocEntries[1].pageIndex).toBe(17);
150
+ });
151
+ });
152
+
153
+ describe('_chaptersRender', () => {
154
+ test('renders markers and panel', () => {
155
+ const fakeBR = {
156
+ _tocEntries: SAMPLE_TOC,
157
+ _chaptersRenderMarker: sinon.stub(),
158
+ shell: {
159
+ menuProviders: {},
160
+ addMenuShortcut: sinon.stub(),
161
+ updateMenuContents: sinon.stub(),
162
+ }
163
+ };
164
+ BookReader.prototype._chaptersRender.call(fakeBR);
165
+ expect(fakeBR.shell.menuProviders['chapters']).toBeTruthy();
166
+ expect(fakeBR.shell.addMenuShortcut.callCount).toBe(1);
167
+ expect(fakeBR.shell.updateMenuContents.callCount).toBe(1);
168
+ expect(fakeBR._chaptersRenderMarker.callCount).toBeGreaterThan(1);
169
+ });
170
+ });
171
+
172
+ describe('_chaptersUpdateCurrent', () => {
173
+ test('highlights the current chapter', () => {
174
+ const fakeBR = {
175
+ mode: 2,
176
+ firstIndex: 16,
177
+ displayedIndices: [16, 17],
178
+ _tocEntries: SAMPLE_TOC,
179
+ _chaptersPanel: {
180
+ currentChapter: null,
181
+ }
182
+ };
183
+ BookReader.prototype._chaptersUpdateCurrent.call(fakeBR);
184
+ expect(fakeBR._chaptersPanel.currentChapter).toEqual(SAMPLE_TOC[1]);
185
+
186
+ fakeBR.mode = 1;
187
+ BookReader.prototype._chaptersUpdateCurrent.call(fakeBR);
188
+ expect(fakeBR._chaptersPanel.currentChapter).toEqual(SAMPLE_TOC[0]);
189
+
190
+ fakeBR.firstIndex = 0;
191
+ BookReader.prototype._chaptersUpdateCurrent.call(fakeBR);
192
+ expect(fakeBR._chaptersPanel.currentChapter).toBeUndefined();
193
+ });
194
+ });
195
+ });
@@ -1,7 +1,7 @@
1
1
  import sinon from 'sinon';
2
2
 
3
- import BookReader from '../../src/BookReader.js';
4
- import { _attachEventListeners } from '../../src/plugins/plugin.iframe.js';
3
+ import BookReader from '@/src/BookReader.js';
4
+ import { _attachEventListeners } from '@/src/plugins/plugin.iframe.js';
5
5
 
6
6
  afterEach(() => {
7
7
  sinon.restore();
@@ -1,8 +1,8 @@
1
- import BookReader from '../../src/BookReader.js';
2
- import '../../src/plugins/plugin.resume.js';
1
+ import BookReader from '@/src/BookReader.js';
2
+ import '@/src/plugins/plugin.resume.js';
3
3
 
4
4
  import sinon from 'sinon';
5
- import * as docCookies from '../../src/util/docCookies.js';
5
+ import * as docCookies from '@/src/util/docCookies.js';
6
6
 
7
7
  let br;
8
8
  beforeAll(() => {