@internetarchive/bookreader 5.0.0-36 → 5.0.0-39

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 (280) hide show
  1. package/.github/workflows/node.js.yml +69 -7
  2. package/.github/workflows/npm-publish.yml +2 -16
  3. package/BookReader/BookReader.css +8 -0
  4. package/BookReader/BookReader.js +1 -1
  5. package/BookReader/BookReader.js.LICENSE.txt +8 -29
  6. package/BookReader/BookReader.js.map +1 -1
  7. package/BookReader/ia-bookreader-bundle.js +144 -119
  8. package/BookReader/ia-bookreader-bundle.js.LICENSE.txt +15 -12
  9. package/BookReader/ia-bookreader-bundle.js.map +1 -1
  10. package/BookReader/icons/magnify-minus.svg +1 -1
  11. package/BookReader/icons/magnify-plus.svg +1 -1
  12. package/BookReader/plugins/plugin.autoplay.js +1 -1
  13. package/BookReader/plugins/plugin.autoplay.js.map +1 -1
  14. package/BookReader/plugins/plugin.chapters.js +1 -1
  15. package/BookReader/plugins/plugin.chapters.js.map +1 -1
  16. package/BookReader/plugins/plugin.mobile_nav.js +1 -1
  17. package/BookReader/plugins/plugin.mobile_nav.js.map +1 -1
  18. package/BookReader/plugins/plugin.resume.js +1 -1
  19. package/BookReader/plugins/plugin.resume.js.map +1 -1
  20. package/BookReader/plugins/plugin.search.js +1 -1
  21. package/BookReader/plugins/plugin.search.js.map +1 -1
  22. package/BookReader/plugins/plugin.text_selection.js +1 -1
  23. package/BookReader/plugins/plugin.text_selection.js.map +1 -1
  24. package/BookReader/plugins/plugin.tts.js +1 -1
  25. package/BookReader/plugins/plugin.tts.js.map +1 -1
  26. package/BookReader/plugins/plugin.url.js +1 -1
  27. package/BookReader/plugins/plugin.url.js.map +1 -1
  28. package/CHANGELOG.md +26 -0
  29. package/README.md +14 -1
  30. package/codecov.yml +6 -0
  31. package/package.json +30 -33
  32. package/renovate.json +43 -0
  33. package/src/BookNavigator/assets/bookmark-colors.js +1 -1
  34. package/src/BookNavigator/assets/button-base.js +1 -1
  35. package/src/BookNavigator/assets/ia-logo.js +1 -1
  36. package/src/BookNavigator/assets/icon_checkmark.js +1 -1
  37. package/src/BookNavigator/assets/icon_close.js +1 -1
  38. package/src/BookNavigator/assets/icon_sort_asc.js +1 -1
  39. package/src/BookNavigator/assets/icon_sort_desc.js +1 -1
  40. package/src/BookNavigator/assets/icon_sort_neutral.js +1 -1
  41. package/src/BookNavigator/assets/icon_volumes.js +1 -1
  42. package/src/BookNavigator/book-navigator.js +1 -2
  43. package/src/BookNavigator/bookmarks/bookmark-button.js +1 -1
  44. package/src/BookNavigator/bookmarks/bookmark-edit.js +2 -3
  45. package/src/BookNavigator/bookmarks/bookmarks-list.js +2 -3
  46. package/src/BookNavigator/bookmarks/bookmarks-loginCTA.js +1 -1
  47. package/src/BookNavigator/bookmarks/bookmarks-provider.js +1 -1
  48. package/src/BookNavigator/bookmarks/ia-bookmarks.js +4 -7
  49. package/src/BookNavigator/delete-modal-actions.js +1 -1
  50. package/src/BookNavigator/downloads/downloads-provider.js +1 -1
  51. package/src/BookNavigator/downloads/downloads.js +1 -2
  52. package/src/BookNavigator/search/a-search-result.js +2 -3
  53. package/src/BookNavigator/search/search-provider.js +1 -2
  54. package/src/BookNavigator/search/search-results.js +1 -2
  55. package/src/BookNavigator/sharing.js +1 -1
  56. package/src/BookNavigator/visual-adjustments/visual-adjustments-provider.js +1 -1
  57. package/src/BookNavigator/visual-adjustments/visual-adjustments.js +3 -3
  58. package/src/BookNavigator/volumes/volumes-provider.js +1 -1
  59. package/src/BookNavigator/volumes/volumes.js +2 -3
  60. package/src/BookReader/Mode1Up.js +2 -1
  61. package/src/BookReader/Mode1UpLit.js +10 -3
  62. package/src/BookReader/Mode2Up.js +11 -0
  63. package/src/BookReader/ModeSmoothZoom.js +2 -0
  64. package/src/BookReader/PageContainer.js +10 -4
  65. package/src/BookReader/utils/ScrollClassAdder.js +31 -0
  66. package/src/BookReader.js +4 -2
  67. package/src/assets/icons/magnify-minus.svg +3 -7
  68. package/src/assets/icons/magnify-plus.svg +3 -7
  69. package/src/css/_TextSelection.scss +13 -0
  70. package/src/ia-bookreader/ia-bookreader.js +1 -1
  71. package/src/plugins/plugin.chapters.js +11 -15
  72. package/src/plugins/plugin.text_selection.js +9 -10
  73. package/src/plugins/search/plugin.search.js +8 -18
  74. package/src/plugins/search/view.js +2 -0
  75. package/src/plugins/tts/AbstractTTSEngine.js +9 -4
  76. package/src/plugins/tts/FestivalTTSEngine.js +10 -11
  77. package/src/plugins/tts/PageChunk.js +11 -20
  78. package/src/plugins/tts/WebTTSEngine.js +22 -26
  79. package/tests/e2e/base.test.js +4 -5
  80. package/tests/e2e/helpers/desktopSearch.js +13 -12
  81. package/tests/e2e/models/Navigation.js +12 -3
  82. package/tests/e2e/rightToLeft.test.js +1 -1
  83. package/tests/e2e/viewmode.test.js +37 -31
  84. package/tests/jest/BookReader/Mode1UpLit.test.js +2 -1
  85. package/tests/jest/BookReader/PageContainer.test.js +5 -4
  86. package/tests/jest/BookReader/utils/ScrollClassAdder.test.js +49 -0
  87. package/tests/jest/plugins/plugin.text_selection.test.js +25 -23
  88. package/tests/jest/plugins/search/plugin.search.test.js +12 -20
  89. package/tests/jest/plugins/tts/AbstractTTSEngine.test.js +3 -3
  90. package/tests/karma/BookNavigator/bookmarks/bookmarks-list.test.js +2 -2
  91. package/tests/karma/BookNavigator/downloads/downloads.test.js +1 -1
  92. package/tests/karma/BookNavigator/volumes/volumes-provider.test.js +3 -3
  93. package/webpack.config.js +1 -1
  94. package/.github/dependabot.yml +0 -8
  95. package/.husky/_/husky.sh +0 -30
  96. package/BookReaderDemo/bookreader-template-bundle.js +0 -7178
  97. package/stat/BookNavigator/BookModel.js +0 -14
  98. package/stat/BookNavigator/BookNavigator.js +0 -482
  99. package/stat/BookNavigator/assets/bookmark-colors.js +0 -15
  100. package/stat/BookNavigator/assets/button-base.js +0 -61
  101. package/stat/BookNavigator/assets/ia-logo.js +0 -17
  102. package/stat/BookNavigator/assets/icon_checkmark.js +0 -6
  103. package/stat/BookNavigator/assets/icon_close.js +0 -3
  104. package/stat/BookNavigator/assets/icon_sort_asc.js +0 -5
  105. package/stat/BookNavigator/assets/icon_sort_desc.js +0 -5
  106. package/stat/BookNavigator/assets/icon_sort_neutral.js +0 -5
  107. package/stat/BookNavigator/assets/icon_volumes.js +0 -11
  108. package/stat/BookNavigator/bookmarks/bookmark-button.js +0 -64
  109. package/stat/BookNavigator/bookmarks/bookmark-edit.js +0 -215
  110. package/stat/BookNavigator/bookmarks/bookmarks-list.js +0 -285
  111. package/stat/BookNavigator/bookmarks/bookmarks-loginCTA.js +0 -28
  112. package/stat/BookNavigator/bookmarks/bookmarks-provider.js +0 -56
  113. package/stat/BookNavigator/bookmarks/ia-bookmarks.js +0 -523
  114. package/stat/BookNavigator/br-fullscreen-mgr.js +0 -82
  115. package/stat/BookNavigator/delete-modal-actions.js +0 -49
  116. package/stat/BookNavigator/downloads/downloads-provider.js +0 -72
  117. package/stat/BookNavigator/downloads/downloads.js +0 -139
  118. package/stat/BookNavigator/provider-config.js +0 -0
  119. package/stat/BookNavigator/search/a-search-result.js +0 -55
  120. package/stat/BookNavigator/search/search-provider.js +0 -180
  121. package/stat/BookNavigator/search/search-results.js +0 -360
  122. package/stat/BookNavigator/sharing.js +0 -31
  123. package/stat/BookNavigator/visual-adjustments/visual-adjustments-provider.js +0 -94
  124. package/stat/BookNavigator/visual-adjustments/visual-adjustments.js +0 -280
  125. package/stat/BookNavigator/volumes/volumes-provider.js +0 -83
  126. package/stat/BookNavigator/volumes/volumes.js +0 -178
  127. package/stat/BookReader/BookModel.js +0 -518
  128. package/stat/BookReader/DebugConsole.js +0 -54
  129. package/stat/BookReader/DragScrollable.js +0 -233
  130. package/stat/BookReader/ImageCache.js +0 -116
  131. package/stat/BookReader/Mode1Up.js +0 -102
  132. package/stat/BookReader/Mode1UpLit.js +0 -434
  133. package/stat/BookReader/Mode2Up.js +0 -1372
  134. package/stat/BookReader/ModeSmoothZoom.js +0 -177
  135. package/stat/BookReader/ModeThumb.js +0 -344
  136. package/stat/BookReader/Navbar/Navbar.js +0 -310
  137. package/stat/BookReader/PageContainer.js +0 -120
  138. package/stat/BookReader/ReduceSet.js +0 -26
  139. package/stat/BookReader/Toolbar/Toolbar.js +0 -384
  140. package/stat/BookReader/events.js +0 -20
  141. package/stat/BookReader/options.js +0 -324
  142. package/stat/BookReader/utils/HTMLDimensionsCacher.js +0 -44
  143. package/stat/BookReader/utils/classes.js +0 -36
  144. package/stat/BookReader/utils.js +0 -240
  145. package/stat/BookReader.js +0 -2550
  146. package/stat/BookReaderComponent/BookReaderComponent.js +0 -117
  147. package/stat/assets/icons/1up.svg +0 -12
  148. package/stat/assets/icons/2up.svg +0 -15
  149. package/stat/assets/icons/advance.svg +0 -26
  150. package/stat/assets/icons/chevron-right.svg +0 -1
  151. package/stat/assets/icons/close-circle-dark.svg +0 -1
  152. package/stat/assets/icons/close-circle.svg +0 -1
  153. package/stat/assets/icons/fullscreen.svg +0 -17
  154. package/stat/assets/icons/fullscreen_exit.svg +0 -17
  155. package/stat/assets/icons/hamburger.svg +0 -15
  156. package/stat/assets/icons/left-arrow.svg +0 -12
  157. package/stat/assets/icons/magnify-minus.svg +0 -16
  158. package/stat/assets/icons/magnify-plus.svg +0 -17
  159. package/stat/assets/icons/magnify.svg +0 -15
  160. package/stat/assets/icons/pause.svg +0 -23
  161. package/stat/assets/icons/play.svg +0 -22
  162. package/stat/assets/icons/playback-speed.svg +0 -34
  163. package/stat/assets/icons/read-aloud.svg +0 -22
  164. package/stat/assets/icons/review.svg +0 -22
  165. package/stat/assets/icons/thumbnails.svg +0 -17
  166. package/stat/assets/icons/voice.svg +0 -1
  167. package/stat/assets/icons/volume-full.svg +0 -22
  168. package/stat/assets/images/BRicons.png +0 -0
  169. package/stat/assets/images/BRicons.svg +0 -94
  170. package/stat/assets/images/BRicons_ia.png +0 -0
  171. package/stat/assets/images/back_pages.png +0 -0
  172. package/stat/assets/images/book_bottom_icon.png +0 -0
  173. package/stat/assets/images/book_down_icon.png +0 -0
  174. package/stat/assets/images/book_left_icon.png +0 -0
  175. package/stat/assets/images/book_leftmost_icon.png +0 -0
  176. package/stat/assets/images/book_right_icon.png +0 -0
  177. package/stat/assets/images/book_rightmost_icon.png +0 -0
  178. package/stat/assets/images/book_top_icon.png +0 -0
  179. package/stat/assets/images/book_up_icon.png +0 -0
  180. package/stat/assets/images/books_graphic.svg +0 -177
  181. package/stat/assets/images/booksplit.png +0 -0
  182. package/stat/assets/images/control_pause_icon.png +0 -0
  183. package/stat/assets/images/control_play_icon.png +0 -0
  184. package/stat/assets/images/embed_icon.png +0 -0
  185. package/stat/assets/images/icon-home-ia.png +0 -0
  186. package/stat/assets/images/icon_OL-logo-xs.png +0 -0
  187. package/stat/assets/images/icon_alert-xs.png +0 -0
  188. package/stat/assets/images/icon_book.svg +0 -12
  189. package/stat/assets/images/icon_bookmark.svg +0 -12
  190. package/stat/assets/images/icon_close-pop.png +0 -0
  191. package/stat/assets/images/icon_download.png +0 -0
  192. package/stat/assets/images/icon_gear.svg +0 -14
  193. package/stat/assets/images/icon_hamburger.svg +0 -20
  194. package/stat/assets/images/icon_home.png +0 -0
  195. package/stat/assets/images/icon_home.svg +0 -21
  196. package/stat/assets/images/icon_home_ia.png +0 -0
  197. package/stat/assets/images/icon_indicator.png +0 -0
  198. package/stat/assets/images/icon_info.svg +0 -11
  199. package/stat/assets/images/icon_one_page.svg +0 -8
  200. package/stat/assets/images/icon_pause.svg +0 -1
  201. package/stat/assets/images/icon_play.svg +0 -1
  202. package/stat/assets/images/icon_playback-rate.svg +0 -15
  203. package/stat/assets/images/icon_return.png +0 -0
  204. package/stat/assets/images/icon_search_button.svg +0 -8
  205. package/stat/assets/images/icon_share.svg +0 -9
  206. package/stat/assets/images/icon_skip-ahead.svg +0 -6
  207. package/stat/assets/images/icon_skip-back.svg +0 -13
  208. package/stat/assets/images/icon_speaker.svg +0 -18
  209. package/stat/assets/images/icon_speaker_open.svg +0 -10
  210. package/stat/assets/images/icon_thumbnails.svg +0 -12
  211. package/stat/assets/images/icon_toc.svg +0 -5
  212. package/stat/assets/images/icon_two_pages.svg +0 -9
  213. package/stat/assets/images/icon_zoomer.png +0 -0
  214. package/stat/assets/images/loading.gif +0 -0
  215. package/stat/assets/images/logo_icon.png +0 -0
  216. package/stat/assets/images/marker_chap-off.png +0 -0
  217. package/stat/assets/images/marker_chap-off.svg +0 -11
  218. package/stat/assets/images/marker_chap-off_ia.png +0 -0
  219. package/stat/assets/images/marker_chap-on.png +0 -0
  220. package/stat/assets/images/marker_chap-on.svg +0 -11
  221. package/stat/assets/images/marker_srch-on.svg +0 -11
  222. package/stat/assets/images/marker_srchchap-off.png +0 -0
  223. package/stat/assets/images/marker_srchchap-on.png +0 -0
  224. package/stat/assets/images/nav_control-dn.png +0 -0
  225. package/stat/assets/images/nav_control-dn_ia.png +0 -0
  226. package/stat/assets/images/nav_control-up.png +0 -0
  227. package/stat/assets/images/nav_control-up_ia.png +0 -0
  228. package/stat/assets/images/nav_control.png +0 -0
  229. package/stat/assets/images/one_page_mode_icon.png +0 -0
  230. package/stat/assets/images/paper-badge.png +0 -0
  231. package/stat/assets/images/print_icon.png +0 -0
  232. package/stat/assets/images/progressbar.gif +0 -0
  233. package/stat/assets/images/right_edges.png +0 -0
  234. package/stat/assets/images/slider.png +0 -0
  235. package/stat/assets/images/slider_ia.png +0 -0
  236. package/stat/assets/images/thumbnail_mode_icon.png +0 -0
  237. package/stat/assets/images/transparent.png +0 -0
  238. package/stat/assets/images/two_page_mode_icon.png +0 -0
  239. package/stat/assets/images/zoom_in_icon.png +0 -0
  240. package/stat/assets/images/zoom_out_icon.png +0 -0
  241. package/stat/css/BookReader.scss +0 -89
  242. package/stat/css/_BRBookmarks.scss +0 -29
  243. package/stat/css/_BRComponent.scss +0 -13
  244. package/stat/css/_BRfloat.scss +0 -197
  245. package/stat/css/_BRicon.scss +0 -48
  246. package/stat/css/_BRmain.scss +0 -251
  247. package/stat/css/_BRnav.scss +0 -359
  248. package/stat/css/_BRpages.scss +0 -139
  249. package/stat/css/_BRsearch.scss +0 -226
  250. package/stat/css/_BRtoolbar.scss +0 -84
  251. package/stat/css/_BRvendor.scss +0 -5
  252. package/stat/css/_MobileNav.scss +0 -194
  253. package/stat/css/_TextSelection.scss +0 -32
  254. package/stat/css/_colorbox.scss +0 -52
  255. package/stat/css/_controls.scss +0 -253
  256. package/stat/css/_icons.scss +0 -121
  257. package/stat/jquery-wrapper.js +0 -4
  258. package/stat/plugins/plugin.archive_analytics.js +0 -86
  259. package/stat/plugins/plugin.autoplay.js +0 -129
  260. package/stat/plugins/plugin.chapters.js +0 -248
  261. package/stat/plugins/plugin.iframe.js +0 -48
  262. package/stat/plugins/plugin.mobile_nav.js +0 -288
  263. package/stat/plugins/plugin.resume.js +0 -68
  264. package/stat/plugins/plugin.text_selection.js +0 -291
  265. package/stat/plugins/plugin.url.js +0 -198
  266. package/stat/plugins/plugin.vendor-fullscreen.js +0 -247
  267. package/stat/plugins/search/plugin.search.js +0 -439
  268. package/stat/plugins/search/view.js +0 -439
  269. package/stat/plugins/tts/AbstractTTSEngine.js +0 -249
  270. package/stat/plugins/tts/FestivalTTSEngine.js +0 -169
  271. package/stat/plugins/tts/PageChunk.js +0 -107
  272. package/stat/plugins/tts/PageChunkIterator.js +0 -163
  273. package/stat/plugins/tts/WebTTSEngine.js +0 -357
  274. package/stat/plugins/tts/plugin.tts.js +0 -357
  275. package/stat/plugins/tts/tooltip_dict.js +0 -15
  276. package/stat/plugins/tts/utils.js +0 -91
  277. package/stat/util/browserSniffing.js +0 -30
  278. package/stat/util/debouncer.js +0 -26
  279. package/stat/util/docCookies.js +0 -67
  280. package/stat/util/strings.js +0 -34
@@ -1,291 +0,0 @@
1
- //@ts-check
2
- import { createSVGPageLayer } from '../BookReader/PageContainer.js';
3
- import { isFirefox, isSafari } from '../util/browserSniffing.js';
4
- import { applyVariables } from '../util/strings.js';
5
- /** @typedef {import('../util/strings.js').StringWithVars} StringWithVars */
6
- /** @typedef {import('../BookReader/PageContainer.js').PageContainer} PageContainer */
7
-
8
- const BookReader = /** @type {typeof import('../BookReader').default} */(window.BookReader);
9
-
10
- export const DEFAULT_OPTIONS = {
11
- enabled: true,
12
- /** @type {StringWithVars} The URL to fetch the entire DJVU xml. Supports options.vars */
13
- fullDjvuXmlUrl: null,
14
- /** @type {StringWithVars} The URL to fetch a single page of the DJVU xml. Supports options.vars. Also has {{pageIndex}} */
15
- singlePageDjvuXmlUrl: null,
16
- };
17
- /** @typedef {typeof DEFAULT_OPTIONS} TextSelectionPluginOptions */
18
-
19
- /**
20
- * @template T
21
- */
22
- export class Cache {
23
- constructor(maxSize = 10) {
24
- this.maxSize = maxSize;
25
- /** @type {T[]} */
26
- this.entries = [];
27
- }
28
-
29
- /**
30
- * @param {T} entry
31
- */
32
- add(entry) {
33
- if (this.entries.length >= this.maxSize) {
34
- this.entries.shift();
35
- }
36
- this.entries.push(entry);
37
- }
38
- }
39
-
40
- export class TextSelectionPlugin {
41
-
42
- constructor(options = DEFAULT_OPTIONS, optionVariables, avoidTspans = isFirefox(), pointerEventsOnParagraph = isSafari()) {
43
- this.options = options;
44
- this.optionVariables = optionVariables;
45
- /**@type {PromiseLike<JQuery<HTMLElement>|undefined>} */
46
- this.djvuPagesPromise = null;
47
- // Using text elements instead of tspans for words because Firefox does not allow svg tspan stretch.
48
- // Tspans are necessary on Chrome because they prevent newline character after every word when copying
49
- this.svgParagraphElement = "text";
50
- this.svgWordElement = "tspan";
51
- this.insertNewlines = avoidTspans;
52
- // Safari has a bug where `pointer-events` doesn't work on `<tspans>`. So
53
- // there we will set `pointer-events: all` on the paragraph element. We don't
54
- // do this everywhere, because it's a worse experience. Thanks Safari :/
55
- this.pointerEventsOnParagraph = pointerEventsOnParagraph;
56
- if (avoidTspans) {
57
- this.svgParagraphElement = "g";
58
- this.svgWordElement = "text";
59
- }
60
-
61
- /** @type {Cache<{index: number, response: any}>} */
62
- this.pageTextCache = new Cache();
63
-
64
- /**
65
- * Sometimes there are too many words on a page, and the browser becomes near
66
- * unusable. For now don't render text layer for pages with too many words.
67
- */
68
- this.maxWordRendered = 2500;
69
- }
70
-
71
- init() {
72
- // Only fetch the full djvu xml if the single page url isn't there
73
- if (this.options.singlePageDjvuXmlUrl) return;
74
- this.djvuPagesPromise = $.ajax({
75
- type: "GET",
76
- url: applyVariables(this.options.fullDjvuXmlUrl, this.optionVariables),
77
- dataType: "html",
78
- error: (e) => undefined
79
- }).then((res) => {
80
- try {
81
- const xmlMap = $.parseXML(res);
82
- return xmlMap && $(xmlMap).find("OBJECT");
83
- } catch (e) {
84
- return undefined;
85
- }
86
- });
87
- }
88
-
89
- /**
90
- * @param {number} index
91
- * @returns {Promise<HTMLElement|undefined>}
92
- */
93
- async getPageText(index) {
94
- if (this.options.singlePageDjvuXmlUrl) {
95
- const cachedEntry = this.pageTextCache.entries.find(x => x.index == index);
96
- if (cachedEntry) {
97
- return cachedEntry.response;
98
- }
99
- return $.ajax({
100
- type: "GET",
101
- url: applyVariables(this.options.singlePageDjvuXmlUrl, this.optionVariables, { pageIndex: index }),
102
- dataType: "html",
103
- error: (e) => undefined,
104
- }).then((res) => {
105
- try {
106
- const xmlDoc = $.parseXML(res);
107
- const result = xmlDoc && $(xmlDoc).find("OBJECT")[0];
108
- this.pageTextCache.add({ index, response: result });
109
- return result;
110
- } catch (e) {
111
- return undefined;
112
- }
113
- });
114
- } else {
115
- const XMLpagesArr = await this.djvuPagesPromise;
116
- if (XMLpagesArr) return XMLpagesArr[index];
117
- }
118
- }
119
-
120
- /**
121
- * Intercept copied text to remove any styling applied to it
122
- * @param {JQuery} $container
123
- */
124
- interceptCopy($container) {
125
- $container[0].addEventListener('copy', (event) => {
126
- const selection = document.getSelection();
127
- event.clipboardData.setData('text/plain', selection.toString());
128
- event.preventDefault();
129
- });
130
- }
131
-
132
- /**
133
- * Applies mouse events when in default mode
134
- * @param {SVGElement} svg
135
- */
136
- defaultMode(svg) {
137
- svg.classList.remove("selectingSVG");
138
- $(svg).on("mousedown.textSelectPluginHandler", (event) => {
139
- if (!$(event.target).is(".BRwordElement")) return;
140
- event.stopPropagation();
141
- svg.classList.add("selectingSVG");
142
- $(svg).one("mouseup.textSelectPluginHandler", (event) => {
143
- if (window.getSelection().toString() != "") {
144
- event.stopPropagation();
145
- $(svg).off(".textSelectPluginHandler");
146
- this.textSelectingMode(svg);
147
- }
148
- else svg.classList.remove("selectingSVG");
149
- });
150
- });
151
- }
152
-
153
- /**
154
- * Applies mouse events when in textSelecting mode
155
- * @param {SVGElement} svg
156
- */
157
- textSelectingMode(svg) {
158
- $(svg).on('mousedown.textSelectPluginHandler', (event) => {
159
- if (!$(event.target).is(".BRwordElement")) {
160
- if (window.getSelection().toString() != "") window.getSelection().removeAllRanges();
161
- }
162
- event.stopPropagation();
163
- });
164
- $(svg).on('mouseup.textSelectPluginHandler', (event) => {
165
- event.stopPropagation();
166
- if (window.getSelection().toString() == "") {
167
- $(svg).off(".textSelectPluginHandler");
168
- this.defaultMode(svg); }
169
- });
170
- }
171
-
172
- /**
173
- * Initializes text selection modes if there is an svg on the page
174
- * @param {JQuery} $container
175
- */
176
- stopPageFlip($container) {
177
- /** @type {JQuery<SVGElement>} */
178
- const $svg = $container.find('svg.textSelectionSVG');
179
- if (!$svg.length) return;
180
- $svg.each((i, s) => this.defaultMode(s));
181
- this.interceptCopy($container);
182
- }
183
-
184
- /**
185
- * @param {PageContainer} pageContainer
186
- */
187
- async createTextLayer(pageContainer) {
188
- const pageIndex = pageContainer.page.index;
189
- const $container = pageContainer.$container;
190
- const $svgLayers = $container.find('.textSelectionSVG');
191
- if ($svgLayers.length) return;
192
- const XMLpage = await this.getPageText(pageIndex);
193
- if (!XMLpage) return;
194
-
195
- const totalWords = $(XMLpage).find("WORD").length;
196
- if (totalWords > this.maxWordRendered) {
197
- console.log(`Page ${pageIndex} has too many words (${totalWords} > ${this.maxWordRendered}). Not rendering text layer.`);
198
- return;
199
- }
200
-
201
- const svg = createSVGPageLayer(pageContainer.page, 'textSelectionSVG');
202
- $container.append(svg);
203
-
204
- $(XMLpage).find("PARAGRAPH").each((i, paragraph) => {
205
- // Adding text element for each paragraph in the page
206
- const words = $(paragraph).find("WORD");
207
- if (!words.length) return;
208
- const paragSvg = document.createElementNS("http://www.w3.org/2000/svg", this.svgParagraphElement);
209
- paragSvg.setAttribute("class", "BRparagElement");
210
- if (this.pointerEventsOnParagraph) {
211
- paragSvg.style.pointerEvents = "all";
212
- }
213
-
214
- const wordHeightArr = [];
215
-
216
- for (let i = 0; i < words.length; i++) {
217
- // Adding tspan for each word in paragraph
218
- const currWord = words[i];
219
- // eslint-disable-next-line no-unused-vars
220
- const [left, bottom, right, top] = $(currWord).attr("coords").split(',').map(parseFloat);
221
- const wordHeight = bottom - top;
222
- wordHeightArr.push(wordHeight);
223
-
224
- const wordTspan = document.createElementNS("http://www.w3.org/2000/svg", this.svgWordElement);
225
- wordTspan.setAttribute("class", "BRwordElement");
226
- wordTspan.setAttribute("x", left.toString());
227
- wordTspan.setAttribute("y", bottom.toString());
228
- wordTspan.setAttribute("textLength", (right - left).toString());
229
- wordTspan.setAttribute("lengthAdjust", "spacingAndGlyphs");
230
- wordTspan.textContent = currWord.textContent;
231
- paragSvg.appendChild(wordTspan);
232
-
233
- // Adding spaces after words except at the end of the paragraph
234
- // TODO: assumes left-to-right text
235
- if (i < words.length - 1) {
236
- const nextWord = words[i + 1];
237
- // eslint-disable-next-line no-unused-vars
238
- const [leftNext, bottomNext, rightNext, topNext] = $(nextWord).attr("coords").split(',').map(parseFloat);
239
- const spaceTspan = document.createElementNS("http://www.w3.org/2000/svg", this.svgWordElement);
240
- spaceTspan.setAttribute("class", "BRwordElement");
241
- spaceTspan.setAttribute("x", right.toString());
242
- spaceTspan.setAttribute("y", bottom.toString());
243
- if ((leftNext - right) > 0) spaceTspan.setAttribute("textLength", (leftNext - right).toString());
244
- spaceTspan.setAttribute("lengthAdjust", "spacingAndGlyphs");
245
- spaceTspan.textContent = " ";
246
- paragSvg.appendChild(spaceTspan);
247
- }
248
-
249
- // Adds newline at the end of paragraph on Firefox
250
- if ((i == words.length - 1 && (this.insertNewlines))) {
251
- paragSvg.appendChild(document.createTextNode("\n"));
252
- }
253
- }
254
-
255
- wordHeightArr.sort();
256
- const paragWordHeight = wordHeightArr[Math.floor(wordHeightArr.length * 0.85)];
257
- paragSvg.setAttribute("font-size", paragWordHeight.toString());
258
- svg.appendChild(paragSvg);
259
- });
260
- this.stopPageFlip($container);
261
- }
262
- }
263
-
264
- export class BookreaderWithTextSelection extends BookReader {
265
- init() {
266
- const options = Object.assign({}, DEFAULT_OPTIONS, this.options.plugins.textSelection);
267
- if (options.enabled) {
268
- this.textSelectionPlugin = new TextSelectionPlugin(options, this.options.vars);
269
- // Write this back; this way the plugin is the source of truth, and BR just
270
- // contains a reference to it.
271
- this.options.plugins.textSelection = options;
272
- this.textSelectionPlugin.init();
273
- }
274
- super.init();
275
- }
276
-
277
- /**
278
- * @param {number} index
279
- */
280
- _createPageContainer(index) {
281
- const pageContainer = super._createPageContainer(index);
282
- // Disable if thumb mode; it's too janky
283
- // .page can be null for "pre-cover" region
284
- if (this.mode !== this.constModeThumb && pageContainer.page) {
285
- this.textSelectionPlugin?.createTextLayer(pageContainer);
286
- }
287
- return pageContainer;
288
- }
289
- }
290
- window.BookReader = BookreaderWithTextSelection;
291
- export default BookreaderWithTextSelection;
@@ -1,198 +0,0 @@
1
- /* global BookReader */
2
- /**
3
- * Plugin for URL management in BookReader
4
- * Note read more about the url "fragment" here:
5
- * https://openlibrary.org/dev/docs/bookurls
6
- */
7
-
8
- jQuery.extend(BookReader.defaultOptions, {
9
- enableUrlPlugin: true,
10
- bookId: '',
11
- /** @type {string} Defaults can be a urlFragment string */
12
- defaults: null,
13
- updateWindowTitle: false,
14
-
15
- /** @type {'history' | 'hash'} */
16
- urlMode: 'hash',
17
-
18
- /**
19
- * When using 'history' mode, this part of the URL is kept constant
20
- * @example /details/plato/
21
- */
22
- urlHistoryBasePath: '/',
23
-
24
- /** Only these params will be reflected onto the URL */
25
- urlTrackedParams: ['page', 'search', 'mode', 'region', 'highlight', 'view'],
26
-
27
- /** If true, don't update the URL when `page == n0 (eg "/page/n0")` */
28
- urlTrackIndex0: false,
29
- });
30
-
31
- /** @override */
32
- BookReader.prototype.setup = (function(super_) {
33
- return function(options) {
34
- super_.call(this, options);
35
-
36
- this.bookId = options.bookId;
37
- this.defaults = options.defaults;
38
-
39
- this.locationPollId = null;
40
- this.oldLocationHash = null;
41
- this.oldUserHash = null;
42
- };
43
- })(BookReader.prototype.setup);
44
-
45
- /** @override */
46
- BookReader.prototype.init = (function(super_) {
47
- return function() {
48
-
49
- if (this.options.enableUrlPlugin) {
50
- this.bind(BookReader.eventNames.PostInit, () => {
51
- const { updateWindowTitle, urlMode } = this.options;
52
- if (updateWindowTitle) {
53
- document.title = this.shortTitle(50);
54
- }
55
- if (urlMode === 'hash') {
56
- this.urlStartLocationPolling();
57
- }
58
- });
59
-
60
- this.bind(BookReader.eventNames.fragmentChange,
61
- this.urlUpdateFragment.bind(this)
62
- );
63
- }
64
- super_.call(this);
65
- };
66
- })(BookReader.prototype.init);
67
-
68
- /**
69
- * Returns a shortened version of the title with the maximum number of characters
70
- * @param {number} maximumCharacters
71
- * @return {string}
72
- */
73
- BookReader.prototype.shortTitle = function(maximumCharacters) {
74
- if (this.bookTitle.length < maximumCharacters) {
75
- return this.bookTitle;
76
- }
77
-
78
- const title = `${this.bookTitle.substr(0, maximumCharacters - 3)}...`;
79
- return title;
80
- };
81
-
82
- /**
83
- * Starts polling of window.location to see hash fragment changes
84
- */
85
- BookReader.prototype.urlStartLocationPolling = function() {
86
- this.oldLocationHash = this.urlReadFragment();
87
-
88
- if (this.locationPollId) {
89
- clearInterval(this.locationPollID);
90
- this.locationPollId = null;
91
- }
92
-
93
- const updateHash = () => {
94
- const newFragment = this.urlReadFragment();
95
- const hasFragmentChange = (newFragment != this.oldLocationHash) && (newFragment != this.oldUserHash);
96
-
97
- if (!hasFragmentChange) { return; }
98
-
99
- const params = this.paramsFromFragment(newFragment);
100
-
101
- const updateParams = () => this.updateFromParams(params);
102
-
103
- this.trigger(BookReader.eventNames.stop);
104
- if (this.animating) {
105
- // Queue change if animating
106
- if (this.autoStop) this.autoStop();
107
- this.animationFinishedCallback = updateParams;
108
- } else {
109
- // update immediately
110
- updateParams();
111
- }
112
- this.oldUserHash = newFragment;
113
- };
114
-
115
- this.locationPollId = setInterval(updateHash, 500);
116
- };
117
-
118
- /**
119
- * Update URL from the current parameters.
120
- * Call this instead of manually using window.location.replace
121
- */
122
- BookReader.prototype.urlUpdateFragment = function() {
123
- const allParams = this.paramsFromCurrent();
124
- const { urlMode, urlTrackIndex0, urlTrackedParams } = this.options;
125
-
126
- if (!urlTrackIndex0
127
- && (typeof(allParams.index) !== 'undefined')
128
- && allParams.index === 0) {
129
- delete allParams.index;
130
- delete allParams.page;
131
- }
132
-
133
- const params = urlTrackedParams.reduce((validParams, paramName) => {
134
- if (paramName in allParams) {
135
- validParams[paramName] = allParams[paramName];
136
- }
137
- return validParams;
138
- }, {});
139
-
140
- const newFragment = this.fragmentFromParams(params, urlMode);
141
- const currFragment = this.urlReadFragment();
142
- const currQueryString = this.getLocationSearch();
143
- const newQueryString = this.queryStringFromParams(params, currQueryString, urlMode);
144
- if (currFragment === newFragment && currQueryString === newQueryString) {
145
- return;
146
- }
147
-
148
- if (urlMode === 'history') {
149
- if (window.history && window.history.replaceState) {
150
- const baseWithoutSlash = this.options.urlHistoryBasePath.replace(/\/+$/, '');
151
- const newFragmentWithSlash = newFragment === '' ? '' : `/${newFragment}`;
152
-
153
- const newUrlPath = `${baseWithoutSlash}${newFragmentWithSlash}${newQueryString}`;
154
- window.history.replaceState({}, null, newUrlPath);
155
- this.oldLocationHash = newFragment + newQueryString;
156
-
157
- }
158
- } else {
159
- const newQueryStringSearch = this.urlParamsFiltersOnlySearch(this.readQueryString());
160
- window.location.replace('#' + newFragment + newQueryStringSearch);
161
- this.oldLocationHash = newFragment + newQueryStringSearch;
162
-
163
- }
164
- };
165
-
166
- /**
167
- * @private
168
- * Filtering query parameters to select only book search param (?q=foo)
169
- This needs to be updated/URL system modified if future query params are to be added
170
- * @param {string} url
171
- * @return {string}
172
- * */
173
- BookReader.prototype.urlParamsFiltersOnlySearch = function(url) {
174
- const params = new URLSearchParams(url);
175
- return params.has('q') ? `?${new URLSearchParams({ q: params.get('q') })}` : '';
176
- };
177
-
178
-
179
- /**
180
- * Will read either the hash or URL and return the bookreader fragment
181
- * @return {string}
182
- */
183
- BookReader.prototype.urlReadFragment = function() {
184
- const { urlMode, urlHistoryBasePath } = this.options;
185
- if (urlMode === 'history') {
186
- return window.location.pathname.substr(urlHistoryBasePath.length);
187
- } else {
188
- return window.location.hash.substr(1);
189
- }
190
- };
191
-
192
- /**
193
- * Will read the hash return the bookreader fragment
194
- * @return {string}
195
- */
196
- BookReader.prototype.urlReadHashFragment = function() {
197
- return window.location.hash.substr(1);
198
- };