@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
@@ -1,4 +1,11 @@
1
1
  /* global BookReader */
2
+ import { css, html, LitElement, nothing } from "lit";
3
+ import { customElement, property } from 'lit/decorators.js';
4
+ import { ifDefined } from 'lit/directives/if-defined.js';
5
+ import { styleMap } from 'lit/directives/style-map.js';
6
+ import '@internetarchive/icon-toc/icon-toc';
7
+ /** @typedef {import('@/src/BookNavigator/book-navigator.js').BookNavigator} BookNavigator */
8
+
2
9
  /**
3
10
  * Plugin for chapter markers in BookReader. Fetches from openlibrary.org
4
11
  * Could be forked, or extended to alter behavior
@@ -10,242 +17,281 @@ jQuery.extend(BookReader.defaultOptions, {
10
17
  bookId: '',
11
18
  });
12
19
 
13
- /** @override Extend the constructor to add search properties */
14
- BookReader.prototype.setup = (function (super_) {
15
- return function (options) {
16
- super_.call(this, options);
17
-
18
- this.olHost = options.olHost;
19
- this.enableChaptersPlugin = options.enableChaptersPlugin;
20
- this.bookId = options.bookId;
21
- };
22
- })(BookReader.prototype.setup);
23
-
24
20
  /** @override Extend to call Open Library for TOC */
25
21
  BookReader.prototype.init = (function(super_) {
26
22
  return function() {
27
23
  super_.call(this);
28
- if (this.enableChaptersPlugin && this.ui !== 'embed') {
29
- this.getOpenLibraryRecord();
30
- }
31
- if (this.enableMobileNav) {
32
- this.bind(BookReader.eventNames.mobileNavOpen,
33
- () => {
34
- this.updateTOCState(this.firstIndex, this._tocEntries);
35
- if ($('table-contents-list').parent().hasClass('mm-opened')) {
36
- this.updateTOCState(this.firstIndex, this._tocEntries);
37
- }
38
- }
39
- )
40
- $(".BRmobileMenu__tableContents").click(
41
- () => {
42
- this.updateTOCState(this.firstIndex, this._tocEntries);
43
- }
44
- );
24
+ if (this.options.enableChaptersPlugin && this.ui !== 'embed') {
25
+ this._chapterInit();
45
26
  }
46
- }
27
+ };
47
28
  })(BookReader.prototype.init);
48
29
 
49
- /**
50
- * Adds chapter marker to navigation scrubber
51
- *
52
- * @param {string} chapterTitle
53
- * @param {string} pageNumber
54
- * @param {number} pageIndex
55
- */
56
- BookReader.prototype.addChapter = function(chapterTitle, pageNumber, pageIndex) {
57
- const uiStringPage = 'Page'; // i18n
58
- const percentThrough = BookReader.util.cssPercentage(pageIndex, this.getNumLeafs() - 1);
59
- const jumpToChapter = (event) => {
60
- this.jumpToIndex($(event.delegateTarget).data('pageIndex'));
61
- $('.current-chapter').removeClass('current-chapter');
62
- $(event.delegateTarget).addClass('current-chapter');
63
- }
64
- const title = `${chapterTitle} | `;
65
- const pageStr = `${uiStringPage} ${pageNumber}`;
66
-
67
- //adding items to mobile table of contents
68
- const mobileChapter = $(`<li></li>`).append($(`<span class='BRTOCElementTitle'></span>`).text(title))
69
- .append($(`<span class='BRTOCElementPage'></span>`).text(pageStr));
70
- mobileChapter.addClass('BRtable-contents-el')
71
- .appendTo(this.$('.table-contents-list'))
72
- .data({ pageIndex });
73
-
74
- //adds .BRchapters to the slider only if pageIndex exists
75
- if (pageIndex != undefined) {
76
- $(`<div></div>`)
77
- .append($('<div />').text(title + pageStr))
78
- .addClass('BRchapter')
79
- .css({ left: percentThrough })
80
- .appendTo(this.$('.BRnavline'))
81
- .data({ pageIndex })
82
- .hover(event => {
83
- // remove hover effect from other markers then turn on just for this
84
- const marker = event.currentTarget;
85
- const tooltip = marker.querySelector('div');
86
- const tooltipOffset = tooltip.getBoundingClientRect();
87
- const targetOffset = marker.getBoundingClientRect();
88
- const boxSizeAdjust = parseInt(getComputedStyle(tooltip).paddingLeft) * 2;
89
- if (tooltipOffset.x - boxSizeAdjust < 0) {
90
- tooltip.style.setProperty('transform', `translateX(-${targetOffset.left - boxSizeAdjust}px)`);
91
- }
92
- this.$('.BRsearch,.BRchapter').removeClass('front');
93
- $(event.target).addClass('front');
94
- },
95
- event => $(event.target).removeClass('front')
96
- )
97
- .on('click', jumpToChapter);
98
-
99
- //adding clickable properties to mobile chapters
100
- mobileChapter.bind('click', jumpToChapter)
101
- .addClass('chapter-clickable')
102
- .attr("data-event-click-tracking","BRTOCPanel|GoToChapter");
30
+ BookReader.prototype._chapterInit = async function() {
31
+ let rawTableOfContents = null;
32
+ // Prefer IA TOC for now, until we update the second half to check for
33
+ // `openlibrary_edition` on the IA metadata instead of making a bunch of
34
+ // requests to OL.
35
+ if (this.options.table_of_contents?.length) {
36
+ rawTableOfContents = this.options.table_of_contents;
37
+ } else {
38
+ const olEdition = await this.getOpenLibraryRecord(this.options.olHost, this.options.bookId);
39
+ if (olEdition?.table_of_contents?.length) {
40
+ rawTableOfContents = olEdition.table_of_contents;
41
+ }
103
42
  }
104
43
 
105
- };
106
-
107
- /*
108
- * Remove all chapters.
109
- */
110
- BookReader.prototype.removeChapters = function() {
111
- this.$('.BRnavpos .BRchapter').remove();
44
+ if (rawTableOfContents) {
45
+ this._tocEntries = rawTableOfContents
46
+ .map(rawTOCEntry => (Object.assign({}, rawTOCEntry, {
47
+ pageIndex: (
48
+ typeof(rawTOCEntry.leaf) == 'number' ? this.book.leafNumToIndex(rawTOCEntry.leaf) :
49
+ rawTOCEntry.pagenum ? this.book.getPageIndex(rawTOCEntry.pagenum) :
50
+ undefined
51
+ ),
52
+ })));
53
+ this._chaptersRender(this._tocEntries);
54
+ this.bind(BookReader.eventNames.pageChanged, () => this._chaptersUpdateCurrent());
55
+ }
112
56
  };
113
57
 
114
58
  /**
115
59
  * Update the table of contents based on array of TOC entries.
116
- * @param {TocEntry[]} tocEntries
117
60
  */
118
- BookReader.prototype.updateTOC = function(tocEntries) {
119
- this.removeChapters();
120
- if (this.enableMobileNav && tocEntries.length > 0) {
121
- this.$(".BRmobileMenu__tableContents").show();
122
- }
123
- for (let i = 0; i < tocEntries.length; i++) {
124
- this.addChapterFromEntry(tocEntries[i]);
125
- }
126
- this._tocEntries = tocEntries;
127
- $('.table-contents-list').children().each((i, el) => {
128
- tocEntries[i].mobileHTML = el;
129
- })
61
+ BookReader.prototype._chaptersRender = function() {
62
+ const shell = /** @type {BookNavigator} */(this.shell);
63
+ shell.menuProviders['chapters'] = {
64
+ id: 'chapters',
65
+ icon: html`<ia-icon-toc style="width: var(--iconWidth); height: var(--iconHeight);"></ia-icon-toc>`,
66
+ label: 'Table of Contents',
67
+ component: html`<br-chapters-panel
68
+ .contents="${this._tocEntries}"
69
+ .jumpToPage="${(pageIndex) => {
70
+ this._chaptersUpdateCurrent(pageIndex);
71
+ this.jumpToIndex(pageIndex);
72
+ }}"
73
+ @connected="${(e) => {
74
+ this._chaptersPanel = e.target;
75
+ this._chaptersUpdateCurrent();
76
+ }}"
77
+ />`,
78
+ };
79
+ shell.addMenuShortcut('chapters');
80
+ shell.updateMenuContents();
81
+ this._tocEntries.forEach((tocEntry, i) => this._chaptersRenderMarker(tocEntry, i));
130
82
  };
131
83
 
132
84
  /**
133
85
  * @typedef {Object} TocEntry
134
- * Table of contents entry as defined -- format is defined by Open Library
135
- * @property {string} pagenum
136
- * @property {number} level
137
- * @property {string} label
138
- * @property {{type: '/type/toc_item'}} type
139
- * @property {string} title
140
- * @property {HTMLElement} mobileHTML
141
- * @property {number} pageIndex
142
-
86
+ * Table of contents entry as defined by Open Library, with some extra values for internal use
87
+ * @property {number} [level]
88
+ * @property {string} [label]
89
+ * @property {string} [title]
90
+ * @property {PageString} [pagenum]
91
+ * @property {LeafNum} [leaf]
92
+ * @property {number} [pageIndex] - Added
143
93
  *
144
94
  * @example {
145
95
  * "pagenum": "17",
146
96
  * "level": 1,
147
97
  * "label": "CHAPTER I",
148
- * "type": {"key": "/type/toc_item"},
149
98
  * "title": "THE COUNTRY AND THE MISSION"
150
99
  * }
151
100
  */
152
101
 
153
102
  /**
154
- * @param {TocEntry} tocEntryObject
103
+ * @param {TocEntry} tocEntry
104
+ * @param {number} entryIndex
155
105
  */
156
- BookReader.prototype.addChapterFromEntry = function(tocEntryObject) {
157
- tocEntryObject.pageIndex = this.getPageIndex(tocEntryObject['pagenum']);
158
- //creates a string with non-void tocEntryObject.label and tocEntryObject.title
159
- const chapterStr = [tocEntryObject.label, tocEntryObject.title]
106
+ BookReader.prototype._chaptersRenderMarker = function(tocEntry, entryIndex) {
107
+ if (tocEntry.pageIndex == undefined) return;
108
+
109
+ //creates a string with non-void tocEntry.label and tocEntry.title
110
+ const chapterStr = [tocEntry.label, tocEntry.title]
160
111
  .filter(x => x)
161
- .join(' ');
162
- this.addChapter(chapterStr, tocEntryObject['pagenum'], tocEntryObject.pageIndex);
112
+ .join(' ') || `Chapter ${entryIndex + 1}`;
113
+
114
+ const percentThrough = BookReader.util.cssPercentage(tocEntry.pageIndex, this.book.getNumLeafs() - 1);
115
+ $(`<div></div>`)
116
+ .append(
117
+ $('<div />')
118
+ .text(chapterStr)
119
+ .append(
120
+ $('<div class="BRchapterPage" />')
121
+ .text(this.book.getPageName(tocEntry.pageIndex))
122
+ )
123
+ )
124
+ .addClass('BRchapter')
125
+ .css({ left: percentThrough })
126
+ .appendTo(this.$('.BRnavline'))
127
+ .on("mouseenter", event => {
128
+ // remove hover effect from other markers then turn on just for this
129
+ const marker = event.currentTarget;
130
+ const tooltip = marker.querySelector('div');
131
+ const tooltipOffset = tooltip.getBoundingClientRect();
132
+ const targetOffset = marker.getBoundingClientRect();
133
+ const boxSizeAdjust = parseInt(getComputedStyle(tooltip).paddingLeft) * 2;
134
+ if (tooltipOffset.x - boxSizeAdjust < 0) {
135
+ tooltip.style.setProperty('transform', `translateX(-${targetOffset.left - boxSizeAdjust}px)`);
136
+ }
137
+ this.$('.BRsearch,.BRchapter').removeClass('front');
138
+ $(event.target).addClass('front');
139
+ })
140
+ .on("mouseleave", event => $(event.target).removeClass('front'))
141
+ .on('click', () => {
142
+ this._chaptersUpdateCurrent(tocEntry.pageIndex);
143
+ this.jumpToIndex(tocEntry.pageIndex);
144
+ });
145
+
163
146
  this.$('.BRchapter, .BRsearch').each((i, el) => {
164
147
  const $el = $(el);
165
- $el.hover(
166
- () => $el.addClass('front'),
167
- () => $el.removeClass('front'));
148
+ $el
149
+ .on("mouseenter", () => $el.addClass('front'))
150
+ .on("mouseleave", () => $el.removeClass('front'));
168
151
  });
169
152
  };
170
153
 
171
154
  /**
172
- * getOpenLibraryRecord
173
- *
174
- * The bookreader is designed to call openlibrary API and constructs the
175
- * "Return book" button using the response.
176
- *
177
155
  * This makes a call to OL API and calls the given callback function with the
178
156
  * response from the API.
157
+ *
158
+ * @param {string} olHost
159
+ * @param {string} ocaid
179
160
  */
180
- BookReader.prototype.getOpenLibraryRecord = function () {
161
+ BookReader.prototype.getOpenLibraryRecord = async function (olHost, ocaid) {
181
162
  // Try looking up by ocaid first, then by source_record
182
- const baseURL = `${this.olHost}/query.json?type=/type/edition&*=`;
183
- const fetchUrlByBookId = `${baseURL}&ocaid=${this.bookId}`;
184
-
185
- /*
186
- * Update Chapter markers based on received record from Open Library.
187
- * Notes that Open Library record is used for extra metadata, and also for lending
188
- */
189
- const setUpChapterMarkers = (olObject) => {
190
- if (olObject && olObject.table_of_contents) {
191
- // XXX check here that TOC is valid
192
- this.updateTOC(olObject.table_of_contents);
193
- }
194
- };
163
+ const baseURL = `${olHost}/query.json?type=/type/edition&*=`;
164
+ const fetchUrlByBookId = `${baseURL}&ocaid=${ocaid}`;
195
165
 
196
- $.ajax({ url: fetchUrlByBookId, dataType: 'jsonp' })
197
- .then(data => {
198
- if (data && data.length > 0) {
199
- return data;
200
- } else {
201
- // try sourceid
202
- return $.ajax({ url: `${baseURL}&source_records=ia:${this.bookId}`, dataType: 'jsonp' });
203
- }
204
- })
205
- .then(data => {
206
- if (data && data.length > 0) {
207
- setUpChapterMarkers(data[0]);
208
- }
209
- });
210
- }
166
+ let data = await $.ajax({ url: fetchUrlByBookId, dataType: 'jsonp' });
211
167
 
212
- // Extend buildMobileDrawerElement with table of contents list
213
- BookReader.prototype.buildMobileDrawerElement = (function (super_) {
214
- return function () {
215
- const $el = super_.call(this);
216
- if (this.enableMobileNav && this.options.enableChaptersPlugin) {
217
- $el.find('.BRmobileMenu__moreInfoRow').after($(`
218
- <li class="BRmobileMenu__tableContents" data-event-click-tracking="BRSidebar|TOCPanel">
219
- <span>
220
- <span class="DrawerIconWrapper">
221
- <img class="DrawerIcon" src="${this.imagesBaseURL}icon_toc.svg" alt="toc-icon"/>
222
- </span>
223
- Table of Contents
224
- </span>
225
- <div>
226
- <ol class="table-contents-list">
227
- </ol>
228
- </div>
229
- </li>`).hide());
230
- }
231
- return $el;
232
- };
233
- })(BookReader.prototype.buildMobileDrawerElement);
168
+ if (!data || !data.length) {
169
+ // try sourceid
170
+ data = await $.ajax({ url: `${baseURL}&source_records=ia:${ocaid}`, dataType: 'jsonp' });
171
+ }
172
+
173
+ return data?.[0];
174
+ };
234
175
 
235
176
  /**
236
- * highlights the current chapter based on current page
237
177
  * @private
238
- * @param {TocEntry[]} tocEntries
239
- * @param {number} tocEntries
178
+ * Highlights the current chapter based on current page
179
+ * @param {PageIndex} curIndex
240
180
  */
241
- BookReader.prototype.updateTOCState = function(currIndex, tocEntries) {
242
- //this function won't have any effects if called before OpenLibrary request is finished
243
- if (!tocEntries) {return}
244
- $('.current-chapter').removeClass('current-chapter');
245
- const tocEntriesIndexed = tocEntries.filter((el) => el.pageIndex != undefined).reverse();
246
- const currChapter = tocEntriesIndexed[tocEntriesIndexed.findIndex(
247
- (el) => el.pageIndex <= currIndex)];
248
- if (currChapter != undefined) {
249
- $(currChapter.mobileHTML).addClass('current-chapter');
181
+ BookReader.prototype._chaptersUpdateCurrent = function(
182
+ curIndex = (this.mode == 2 ? Math.max(...this.displayedIndices) : this.firstIndex)
183
+ ) {
184
+ const tocEntriesIndexed = this._tocEntries.filter((el) => el.pageIndex != undefined).reverse();
185
+ const currChapter = tocEntriesIndexed[
186
+ // subtract one so that 2up shows the right label
187
+ tocEntriesIndexed.findIndex((chapter) => chapter.pageIndex <= curIndex)
188
+ ];
189
+ if (this._chaptersPanel) {
190
+ this._chaptersPanel.currentChapter = currChapter;
191
+ }
192
+ };
193
+
194
+ @customElement('br-chapters-panel')
195
+ export class BRChaptersPanel extends LitElement {
196
+ /** @type {TocEntry[]} */
197
+ @property({ type: Array })
198
+ contents = [];
199
+
200
+ /** @type {TocEntry?} */
201
+ @property({ type: Object })
202
+ currentChapter = {};
203
+
204
+ /** @type {(pageIndex: PageIndex) => void} */
205
+ jumpToPage = () => {};
206
+
207
+ /**
208
+ * @param {TocEntry[]} contents
209
+ */
210
+ constructor(contents) {
211
+ super();
212
+ this.contents = contents;
213
+ }
214
+
215
+ render() {
216
+ return html`
217
+ <ol>
218
+ ${this.contents.map(tocEntry => this.renderTOCEntry(tocEntry))}
219
+ </ol>
220
+ `;
221
+ }
222
+
223
+ /**
224
+ * @param {TocEntry} tocEntry
225
+ */
226
+ renderTOCEntry(tocEntry) {
227
+ const chapterTitle = [tocEntry.label, tocEntry.title]
228
+ .filter(x => x)
229
+ .join(' ');
230
+ const clickable = tocEntry.pageIndex != undefined;
231
+ // note the click-tracking won't work...
232
+ return html`
233
+ <li
234
+ class="
235
+ BRtable-contents-el
236
+ ${clickable ? 'clickable' : ''}
237
+ ${tocEntry == this.currentChapter ? 'current' : ''}
238
+ "
239
+ style="${styleMap({marginLeft: (tocEntry.level - 1) * 10 + 'px'})}"
240
+ data-event-click-tracking="${ifDefined(clickable ? "BRTOCPanel|GoToChapter" : undefined)}"
241
+ @click="${() => this.jumpToPage(tocEntry.pageIndex)}"
242
+ >
243
+ ${chapterTitle}
244
+ ${tocEntry.pagenum ? html`
245
+ <br />
246
+ <span class="BRTOCElementPage">Page ${tocEntry.pagenum}</span>
247
+ ` : nothing}
248
+ </li>`;
249
+ }
250
+
251
+ connectedCallback() {
252
+ super.connectedCallback();
253
+ this.dispatchEvent(new CustomEvent('connected'));
254
+ }
255
+
256
+ updated(changedProperties) {
257
+ if (changedProperties.has('currentChapter')) {
258
+ this.shadowRoot.querySelector('li.current')?.scrollIntoView({
259
+ block: 'nearest',
260
+ behavior: 'smooth',
261
+ });
262
+ }
263
+ }
264
+
265
+ static get styles() {
266
+ return css`
267
+ ol {
268
+ padding: 0;
269
+ margin: 0;
270
+ margin-right: 5px;
271
+ }
272
+ li {
273
+ padding: 10px;
274
+ overflow: hidden;
275
+ border-radius: 4px;
276
+ }
277
+ li.clickable {
278
+ font-weight: normal;
279
+ cursor: pointer;
280
+ transition: background-color 0.2s;
281
+ }
282
+
283
+ li.clickable:not(.current):hover {
284
+ background-color: rgba(255,255,255, 0.05);
285
+ }
286
+
287
+ li.current {
288
+ background-color: rgba(255,255,255,0.9);
289
+ color: #333;
290
+ }
291
+
292
+ .BRTOCElementPage {
293
+ font-size: 0.85em;
294
+ opacity: .8;
295
+ }`;
250
296
  }
251
297
  }
@@ -0,0 +1,151 @@
1
+ // @ts-check
2
+ const BookReader = /** @type {typeof import('../BookReader').default} */(window.BookReader);
3
+
4
+ export const DEFAULT_OPTIONS = {
5
+ enabled: true,
6
+ /** @type {import('@iiif/presentation-3').Manifest | import('@iiif/presentation-2').Manifest} */
7
+ manifest: null,
8
+ };
9
+
10
+ class IIIFPlugin {
11
+ constructor(options = DEFAULT_OPTIONS, optionVariables) {
12
+ this.options = options;
13
+ this.optionVariables = optionVariables;
14
+ this.manifest = options.manifest;
15
+ }
16
+
17
+ load() {
18
+ if (this.manifest["@context"] == "http://iiif.io/api/presentation/2/context.json") {
19
+ const manifest = /** @type {import('@iiif/presentation-2').Manifest} */(this.manifest);
20
+ return this.manifestToBookReaderV2(manifest);
21
+ } else if (this.manifest["@context"] == "http://iiif.io/api/presentation/3/context.json") {
22
+ const manifest = /** @type {import('@iiif/presentation-3').Manifest} */(this.manifest);
23
+ return this.manifestToBookReaderV3(manifest);
24
+ } else {
25
+ throw new Error("Unsupported IIIF context " + this.manifest["@context"]);
26
+ }
27
+ }
28
+
29
+ /**
30
+ * @param {import('@iiif/presentation-3').Manifest} manifest
31
+ */
32
+ manifestToBookReaderV3(manifest) {
33
+ /** @type {import('../BookReader/options.js').BookReaderOptions} */
34
+ const book = {
35
+ bookTitle: resolveInternationalString(manifest.label),
36
+ pageProgression: manifest.viewingDirection == "right-to-left" ? "rl" : "lr",
37
+ // numLeafs: manifest.items.length,
38
+ metadata: manifest.metadata.map((metadata) => {
39
+ return {
40
+ label: resolveInternationalString(metadata.label),
41
+ value: resolveInternationalString(metadata.value),
42
+ };
43
+ }),
44
+ data: [],
45
+ /**
46
+ * @this {import('../BookReader.js').default}
47
+ */
48
+ getPageURI(pageIndex, reduce, rotate) {
49
+ const percent = Math.floor(100 * 1 / reduce);
50
+ const bodyArr = manifest.items[pageIndex].items[0].items[0].body;
51
+ const body = bodyArr instanceof Array ? bodyArr[0] : bodyArr;
52
+ const uri = body.service[0].id;
53
+ return `${uri}/full/pct:${percent}/0/default.jpg`;
54
+ }
55
+ };
56
+
57
+ if (manifest.viewingDirection == "top-to-bottom" || manifest.viewingDirection == "bottom-to-top") {
58
+ console.warn("Unsupported viewingDirection", manifest.viewingDirection);
59
+ }
60
+
61
+ let spread = [];
62
+ manifest.items.forEach((item, index) => {
63
+ const bodyArr = manifest.items[index].items[0].items[0].body;
64
+ const body = bodyArr instanceof Array ? bodyArr[0] : bodyArr;
65
+ const uri = body.service[0].id;
66
+ /** @type {import('../BookReader/options.js').PageData} */
67
+ const pageData = {
68
+ uri,
69
+ width: item.width,
70
+ height: item.height,
71
+ pageNum: resolveInternationalString(item.label),
72
+ };
73
+ spread.push(pageData);
74
+ if (index % 2 == 0) {
75
+ book.data.push(spread);
76
+ spread = [];
77
+ }
78
+ });
79
+
80
+ return book;
81
+ }
82
+
83
+ /**
84
+ * @param {import('@iiif/presentation-2').Manifest} manifest
85
+ */
86
+ manifestToBookReaderV2(manifest) {
87
+ /** @type {import('../BookReader/options.js').BookReaderOptions} */
88
+ const book = {
89
+ bookTitle: manifest.label,
90
+ metadata: manifest.metadata,
91
+ thumbnail: manifest.thumbnail?.['@id'],
92
+ // numLeafs: manifest.sequences[0].canvases.length,
93
+ data: [],
94
+ /**
95
+ * @this {import('../BookReader.js').default}
96
+ */
97
+ getPageURI(pageIndex, reduce, rotate) {
98
+ const percent = Math.floor(100 * 1 / reduce);
99
+ const uri = manifest.sequences[0].canvases[pageIndex].images[0].resource.service['@id'];
100
+ return `${uri}/full/pct:${percent}/0/default.jpg`;
101
+ }
102
+ };
103
+
104
+ let spread = [];
105
+ manifest.sequences[0].canvases.forEach((canvas, index) => {
106
+ /** @type {import('../BookReader/options.js').PageData} */
107
+ const pageData = {
108
+ uri: canvas.images[0].resource.service['@id'],
109
+ width: canvas.width,
110
+ height: canvas.height,
111
+ pageNum: canvas.label,
112
+ };
113
+ spread.push(pageData);
114
+ if (index % 2 == 0) {
115
+ book.data.push(spread);
116
+ spread = [];
117
+ }
118
+ });
119
+
120
+ return book;
121
+ }
122
+ }
123
+
124
+ /**
125
+ * @param {import('@iiif/presentation-3').InternationalString} internationalString
126
+ */
127
+ function resolveInternationalString(internationalString) {
128
+ const anyLang = Object.keys(internationalString)[0];
129
+ return (internationalString[navigator.language] || internationalString[anyLang])[0];
130
+ }
131
+
132
+ export class BookReaderWithIIIFPlugin extends BookReader {
133
+ setup(options) {
134
+ const pluginOpts = Object.assign(
135
+ {},
136
+ DEFAULT_OPTIONS,
137
+ options.plugins.iiif,
138
+ );
139
+
140
+ if (pluginOpts.enabled) {
141
+ this.iiifPlugin = new IIIFPlugin(pluginOpts, options.vars);
142
+ // Write this back; this way the plugin is the source of truth, and BR just
143
+ // contains a reference to it.
144
+ options.plugins.iiif = this.iiifPlugin.options;
145
+ Object.assign(options, this.iiifPlugin.load());
146
+ }
147
+ return super.setup(options);
148
+ }
149
+ }
150
+ window.BookReader = BookReaderWithIIIFPlugin;
151
+ export default BookReaderWithIIIFPlugin;
@@ -37,7 +37,7 @@ BookReader.prototype.getResumeValue = function() {
37
37
  const val = BookReader.docCookies.getItem('br-resume');
38
38
  if (val !== null) return parseInt(val);
39
39
  else return null;
40
- }
40
+ };
41
41
 
42
42
  /**
43
43
  * Return cookie path using pathname up to /page/... or /mode/...
@@ -49,7 +49,7 @@ BookReader.prototype.getResumeValue = function() {
49
49
  */
50
50
  BookReader.prototype.getCookiePath = function(urlPathPart) {
51
51
  return urlPathPart.match('.+?(?=/page/|/mode/|$)')[0];
52
- }
52
+ };
53
53
 
54
54
  /**
55
55
  * Sets page resume value, for remembering reader's page
@@ -65,4 +65,4 @@ BookReader.prototype.updateResumeValue = function(index, cookieName) {
65
65
  const path = this.options.resumeCookiePath
66
66
  || this.getCookiePath(window.location.pathname);
67
67
  BookReader.docCookies.setItem(cookieName || 'br-resume', index, ttl, path, null, false);
68
- }
68
+ };