@readium/navigator 2.4.0-beta.9 → 2.5.0-beta.1

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 (138) hide show
  1. package/dist/ReadiumCSS-after-B_e3a-PY.js +592 -0
  2. package/dist/ReadiumCSS-after-C-T_0paD.js +530 -0
  3. package/dist/ReadiumCSS-after-lr-n3fz2.js +475 -0
  4. package/dist/ReadiumCSS-after-mXeKKPap.js +490 -0
  5. package/dist/ReadiumCSS-before-Bjd3POej.js +426 -0
  6. package/dist/ReadiumCSS-before-CfXPAGaQ.js +425 -0
  7. package/dist/ReadiumCSS-before-CrNWvuyE.js +425 -0
  8. package/dist/ReadiumCSS-before-KVen5ceo.js +425 -0
  9. package/dist/ReadiumCSS-default-BKAG5pGU.js +162 -0
  10. package/dist/ReadiumCSS-default-C63bYOYF.js +183 -0
  11. package/dist/ReadiumCSS-default-CclvbeNC.js +162 -0
  12. package/dist/ReadiumCSS-default-DnlgDaBu.js +180 -0
  13. package/dist/ReadiumCSS-ebpaj_fonts_patch-Dt2XliTg.js +82 -0
  14. package/dist/index.js +2642 -3430
  15. package/dist/index.umd.cjs +4407 -995
  16. package/package.json +2 -2
  17. package/src/audio/AudioNavigator.ts +155 -42
  18. package/src/audio/AudioPoolManager.ts +27 -14
  19. package/src/audio/engine/AudioEngine.ts +4 -3
  20. package/src/audio/engine/PreservePitchProcessor.js +166 -101
  21. package/src/audio/engine/PreservePitchWorklet.ts +2 -17
  22. package/src/audio/engine/WebAudioEngine.ts +138 -160
  23. package/src/audio/engine/index.ts +2 -2
  24. package/src/audio/index.ts +3 -3
  25. package/src/audio/preferences/AudioDefaults.ts +2 -2
  26. package/src/audio/preferences/AudioPreferences.ts +11 -11
  27. package/src/audio/preferences/AudioPreferencesEditor.ts +13 -13
  28. package/src/audio/preferences/AudioSettings.ts +3 -3
  29. package/src/audio/preferences/index.ts +4 -4
  30. package/src/audio/protection/AudioNavigatorProtector.ts +4 -4
  31. package/src/css/index.ts +1 -1
  32. package/src/epub/EpubNavigator.ts +113 -78
  33. package/src/epub/css/Properties.ts +15 -15
  34. package/src/epub/css/ReadiumCSS.ts +43 -43
  35. package/src/epub/css/index.ts +2 -2
  36. package/src/epub/frame/FrameBlobBuilder.ts +31 -31
  37. package/src/epub/frame/FrameComms.ts +1 -1
  38. package/src/epub/frame/FrameManager.ts +13 -9
  39. package/src/epub/frame/FramePoolManager.ts +13 -13
  40. package/src/epub/frame/index.ts +4 -4
  41. package/src/epub/fxl/FXLCoordinator.ts +3 -3
  42. package/src/epub/fxl/FXLFrameManager.ts +8 -8
  43. package/src/epub/fxl/FXLFramePoolManager.ts +18 -14
  44. package/src/epub/fxl/FXLPeripherals.ts +4 -4
  45. package/src/epub/fxl/index.ts +5 -5
  46. package/src/epub/helpers/scriptMode.ts +45 -0
  47. package/src/epub/index.ts +6 -5
  48. package/src/epub/preferences/EpubDefaults.ts +23 -23
  49. package/src/epub/preferences/EpubPreferences.ts +16 -16
  50. package/src/epub/preferences/EpubPreferencesEditor.ts +53 -53
  51. package/src/epub/preferences/EpubSettings.ts +101 -101
  52. package/src/epub/preferences/index.ts +4 -4
  53. package/src/helpers/index.ts +2 -2
  54. package/src/index.ts +8 -8
  55. package/src/injection/Injector.ts +42 -42
  56. package/src/injection/epubInjectables.ts +86 -17
  57. package/src/injection/index.ts +2 -2
  58. package/src/injection/webpubInjectables.ts +2 -2
  59. package/src/preferences/Configurable.ts +2 -2
  60. package/src/preferences/PreferencesEditor.ts +2 -2
  61. package/src/preferences/guards.ts +2 -2
  62. package/src/preferences/index.ts +5 -5
  63. package/src/protection/CopyProtector.ts +5 -1
  64. package/src/protection/DevToolsDetector.ts +16 -16
  65. package/src/protection/DragAndDropProtector.ts +14 -1
  66. package/src/protection/NavigatorProtector.ts +6 -6
  67. package/src/webpub/WebPubBlobBuilder.ts +1 -1
  68. package/src/webpub/WebPubFrameManager.ts +8 -8
  69. package/src/webpub/WebPubFramePoolManager.ts +7 -7
  70. package/src/webpub/WebPubNavigator.ts +27 -27
  71. package/src/webpub/css/Properties.ts +3 -3
  72. package/src/webpub/css/WebPubCSS.ts +11 -11
  73. package/src/webpub/css/index.ts +2 -2
  74. package/src/webpub/index.ts +6 -6
  75. package/src/webpub/preferences/WebPubDefaults.ts +12 -12
  76. package/src/webpub/preferences/WebPubPreferences.ts +8 -8
  77. package/src/webpub/preferences/WebPubPreferencesEditor.ts +31 -31
  78. package/src/webpub/preferences/WebPubSettings.ts +45 -45
  79. package/src/webpub/preferences/index.ts +4 -4
  80. package/types/src/audio/AudioNavigator.d.ts +34 -5
  81. package/types/src/audio/AudioPoolManager.d.ts +7 -4
  82. package/types/src/audio/engine/AudioEngine.d.ts +4 -3
  83. package/types/src/audio/engine/PreservePitchWorklet.d.ts +1 -4
  84. package/types/src/audio/engine/WebAudioEngine.d.ts +15 -9
  85. package/types/src/audio/engine/index.d.ts +2 -2
  86. package/types/src/audio/index.d.ts +3 -3
  87. package/types/src/audio/preferences/AudioPreferences.d.ts +9 -9
  88. package/types/src/audio/preferences/AudioPreferencesEditor.d.ts +4 -4
  89. package/types/src/audio/preferences/AudioSettings.d.ts +3 -3
  90. package/types/src/audio/preferences/index.d.ts +4 -4
  91. package/types/src/audio/protection/AudioNavigatorProtector.d.ts +2 -2
  92. package/types/src/css/index.d.ts +1 -1
  93. package/types/src/epub/EpubNavigator.d.ts +15 -14
  94. package/types/src/epub/css/Properties.d.ts +2 -2
  95. package/types/src/epub/css/ReadiumCSS.d.ts +3 -3
  96. package/types/src/epub/css/index.d.ts +2 -2
  97. package/types/src/epub/frame/FrameBlobBuilder.d.ts +1 -1
  98. package/types/src/epub/frame/FrameComms.d.ts +1 -1
  99. package/types/src/epub/frame/FrameManager.d.ts +3 -2
  100. package/types/src/epub/frame/FramePoolManager.d.ts +3 -3
  101. package/types/src/epub/frame/index.d.ts +4 -4
  102. package/types/src/epub/fxl/FXLFrameManager.d.ts +3 -3
  103. package/types/src/epub/fxl/FXLFramePoolManager.d.ts +5 -5
  104. package/types/src/epub/fxl/FXLPeripherals.d.ts +2 -2
  105. package/types/src/epub/fxl/index.d.ts +5 -5
  106. package/types/src/epub/helpers/scriptMode.d.ts +16 -0
  107. package/types/src/epub/index.d.ts +6 -5
  108. package/types/src/epub/preferences/EpubDefaults.d.ts +1 -1
  109. package/types/src/epub/preferences/EpubPreferences.d.ts +2 -2
  110. package/types/src/epub/preferences/EpubPreferencesEditor.d.ts +5 -5
  111. package/types/src/epub/preferences/EpubSettings.d.ts +4 -4
  112. package/types/src/epub/preferences/index.d.ts +4 -4
  113. package/types/src/helpers/index.d.ts +2 -2
  114. package/types/src/index.d.ts +8 -8
  115. package/types/src/injection/Injector.d.ts +1 -1
  116. package/types/src/injection/epubInjectables.d.ts +5 -3
  117. package/types/src/injection/index.d.ts +2 -2
  118. package/types/src/injection/webpubInjectables.d.ts +1 -1
  119. package/types/src/preferences/Configurable.d.ts +1 -1
  120. package/types/src/preferences/PreferencesEditor.d.ts +1 -1
  121. package/types/src/preferences/guards.d.ts +1 -1
  122. package/types/src/preferences/index.d.ts +5 -5
  123. package/types/src/protection/CopyProtector.d.ts +1 -0
  124. package/types/src/protection/DragAndDropProtector.d.ts +2 -0
  125. package/types/src/protection/NavigatorProtector.d.ts +1 -1
  126. package/types/src/webpub/WebPubBlobBuilder.d.ts +1 -1
  127. package/types/src/webpub/WebPubFrameManager.d.ts +2 -2
  128. package/types/src/webpub/WebPubFramePoolManager.d.ts +3 -3
  129. package/types/src/webpub/WebPubNavigator.d.ts +10 -10
  130. package/types/src/webpub/css/Properties.d.ts +2 -2
  131. package/types/src/webpub/css/WebPubCSS.d.ts +2 -2
  132. package/types/src/webpub/css/index.d.ts +2 -2
  133. package/types/src/webpub/index.d.ts +6 -6
  134. package/types/src/webpub/preferences/WebPubDefaults.d.ts +1 -1
  135. package/types/src/webpub/preferences/WebPubPreferences.d.ts +2 -2
  136. package/types/src/webpub/preferences/WebPubPreferencesEditor.d.ts +5 -5
  137. package/types/src/webpub/preferences/WebPubSettings.d.ts +4 -4
  138. package/types/src/webpub/preferences/index.d.ts +4 -4
@@ -1,6 +1,6 @@
1
- import { MediaType } from "@readium/shared";
2
- import { Link, Publication } from "@readium/shared";
3
- import { Injector } from "../../injection/Injector";
1
+ import { Link, MediaType, Publication, ReadingProgression } from "@readium/shared";
2
+ import { Injector } from "../../injection/Injector.ts";
3
+ import { getScriptMode } from "../helpers/scriptMode.ts";
4
4
 
5
5
  const csp = (domains: string[]) => {
6
6
  const d = domains.join(" ");
@@ -58,12 +58,12 @@ export default class FrameBlobBuider {
58
58
  // Load the HTML resource
59
59
  const txt = await this.pub.get(this.item).readAsString();
60
60
  if(!txt) throw new Error(`Failed reading item ${this.item.href}`);
61
-
61
+
62
62
  const doc = new DOMParser().parseFromString(
63
63
  txt,
64
64
  this.item.mediaType.string as DOMParserSupportedType
65
65
  );
66
-
66
+
67
67
  const perror = doc.querySelector("parsererror");
68
68
  if (perror) {
69
69
  const details = perror.querySelector("div");
@@ -101,7 +101,7 @@ export default class FrameBlobBuider {
101
101
 
102
102
  // Get allowed domains from injector if it exists
103
103
  const allowedDomains = this.injector?.getAllowedDomains?.() || [];
104
-
104
+
105
105
  // Always include the root domain if provided
106
106
  const domains = [...new Set([
107
107
  ...(root ? [root] : []),
@@ -126,10 +126,10 @@ export default class FrameBlobBuider {
126
126
  img.setAttribute("fetchpriority", "high");
127
127
  });
128
128
 
129
- // We need to ensure that lang is set on the root element
129
+ // We need to ensure that lang is set on the root element
130
130
  // since it is used for settings such as font-family, hyphens, ligatures, etc.
131
131
  // but also screen readers, etc.
132
- // Metadata’s effectiveReadingProgression uses first item in array as primary language
132
+ // Metadata’s effectiveReadingProgression uses first item in array as primary language
133
133
  // so we keep it consistent.
134
134
  if (mediaType.isHTML && this.pub.metadata.languages?.[0]) {
135
135
  const primaryLanguage = this.pub.metadata.languages[0];
@@ -137,37 +137,37 @@ export default class FrameBlobBuider {
137
137
  if (mediaType === MediaType.XHTML) {
138
138
  // InDesign is infamous for setting xml:lang on the body instead of the root element
139
139
  // So we have to check whether lang is set on the body and move it to the root element
140
- const rootLang = document.documentElement.lang || document.documentElement.getAttribute("xml:lang");
141
- const bodyLang = document.body.lang || document.body.getAttribute("xml:lang");
140
+ const rootLang = doc.documentElement.lang || doc.documentElement.getAttribute("xml:lang");
141
+ const bodyLang = doc.body.lang || doc.body.getAttribute("xml:lang");
142
142
  if (bodyLang && !rootLang) {
143
- document.documentElement.lang = bodyLang;
144
- document.documentElement.setAttribute("xml:lang", bodyLang);
145
- document.body.removeAttribute("xml:lang");
146
- document.body.removeAttribute("lang");
143
+ doc.documentElement.lang = bodyLang;
144
+ doc.documentElement.setAttribute("xml:lang", bodyLang);
145
+ doc.body.removeAttribute("xml:lang");
146
+ doc.body.removeAttribute("lang");
147
147
  } else if (!rootLang) {
148
- document.documentElement.lang = primaryLanguage;
149
- document.documentElement.setAttribute("xml:lang", primaryLanguage);
148
+ doc.documentElement.lang = primaryLanguage;
149
+ doc.documentElement.setAttribute("xml:lang", primaryLanguage);
150
150
  }
151
151
  } else if (
152
- mediaType === MediaType.HTML &&
153
- !document.documentElement.lang
152
+ mediaType === MediaType.HTML &&
153
+ !doc.documentElement.lang
154
154
  ) {
155
- document.documentElement.lang = primaryLanguage;
155
+ doc.documentElement.lang = primaryLanguage;
156
156
  }
157
157
  }
158
158
 
159
- // We need to ensure that dir is set on the root element if rtl
160
- // Since body can bubble up, we also need to check it’s not here.
161
- // https://github.com/readium/readium-css/blob/develop/docs/CSS03-injection_and_pagination.md#be-cautious-the-direction-propagates
162
-
163
- // TODO: ReadiumCSS stylesheets are injected as LTR/default no matter what so disabled ATM
164
- /* if (
165
- !document.documentElement.dir &&
166
- !document.body.dir &&
167
- this.pub.metadata.effectiveReadingProgression === ReadingProgression.rtl
159
+ // Set dir="rtl" on the root element for RTL publications if the author
160
+ // has not already declared a direction on html or body.
161
+ // See: https://github.com/readium/readium-css/blob/develop/docs/CSS03-injection_and_pagination.md#be-cautious-the-direction-propagates
162
+ // CJK modes must NEVER receive a dir attribute — writing-mode handles
163
+ // directionality visually, and dir="rtl" would break vertical layout.
164
+ const scriptMode = getScriptMode(this.pub.metadata);
165
+ if (scriptMode === "rtl" &&
166
+ !doc.documentElement.dir &&
167
+ !doc.body.dir
168
168
  ) {
169
- document.documentElement.dir = this.pub.metadata.effectiveReadingProgression;
170
- } */
169
+ doc.documentElement.dir = ReadingProgression.rtl;
170
+ }
171
171
 
172
172
  if (base !== undefined) {
173
173
  // Set all URL bases. Very convenient!
@@ -193,4 +193,4 @@ export default class FrameBlobBuider {
193
193
  })
194
194
  );
195
195
  }
196
- }
196
+ }
@@ -6,7 +6,7 @@ import {
6
6
  mid,
7
7
  CommsEventKey,
8
8
  } from "@readium/navigator-html-injectables";
9
- import { ManagerEventKey } from "../EpubNavigator";
9
+ import { ManagerEventKey } from "../EpubNavigator.ts";
10
10
 
11
11
  interface RegistryValue {
12
12
  time: number;
@@ -1,8 +1,8 @@
1
1
  import { Loader, ModuleName } from "@readium/navigator-html-injectables";
2
- import { FrameComms } from "./FrameComms";
3
- import { ReadiumWindow } from "../../../../navigator-html-injectables/types/src/helpers/dom";
4
- import { sML } from "../../helpers";
5
- import type { IContentProtectionConfig, IKeyboardPeripheralsConfig } from "../../Navigator";
2
+ import { FrameComms } from "./FrameComms.ts";
3
+ import type { ReadiumWindow } from "../../../../navigator-html-injectables/types/src/helpers/dom";
4
+ import { sML } from "../../helpers/index.ts";
5
+ import type { IContentProtectionConfig, IKeyboardPeripheralsConfig } from "../../Navigator.ts";
6
6
 
7
7
 
8
8
  export class FrameManager {
@@ -70,10 +70,10 @@ export class FrameManager {
70
70
 
71
71
  private applyContentProtection() {
72
72
  if (!this.comms) this.comms!.resume();
73
-
73
+
74
74
  // Send content protection config
75
75
  this.comms!.send("peripherals_protection", this.contentProtectionConfig);
76
-
76
+
77
77
  // Send keyboard peripherals separately
78
78
  if (this.keyboardPeripheralsConfig && this.keyboardPeripheralsConfig.length > 0) {
79
79
  this.comms!.send("keyboard_peripherals", this.keyboardPeripheralsConfig);
@@ -126,7 +126,7 @@ export class FrameManager {
126
126
  this.comms?.send("focus", undefined, () => {
127
127
  // Apply content protection synchronously
128
128
  this.applyContentProtection();
129
-
129
+
130
130
  const remove = () => {
131
131
  this.frame.style.removeProperty("visibility");
132
132
  this.frame.style.removeProperty("aria-hidden");
@@ -152,7 +152,7 @@ export class FrameManager {
152
152
 
153
153
  setCSSProperties(properties: { [key: string]: string }) {
154
154
  if(this.destroyed || !this.frame.contentWindow) return;
155
-
155
+
156
156
  // We need to resume and halt postMessage to update the properties
157
157
  // if the frame is hidden since it’s been halted in hide()
158
158
  if (this.hidden) {
@@ -173,6 +173,10 @@ export class FrameManager {
173
173
  return this.frame.getBoundingClientRect();
174
174
  }
175
175
 
176
+ get isDestroyed() {
177
+ return this.destroyed;
178
+ }
179
+
176
180
  get window() {
177
181
  if(this.destroyed || !this.frame.contentWindow) throw Error("Trying to use frame window when it doesn't exist");
178
182
  return this.frame.contentWindow;
@@ -193,4 +197,4 @@ export class FrameManager {
193
197
  get ldr() {
194
198
  return this.loader;
195
199
  }
196
- }
200
+ }
@@ -1,9 +1,9 @@
1
1
  import { ModuleName } from "@readium/navigator-html-injectables";
2
2
  import { Locator, Publication } from "@readium/shared";
3
- import FrameBlobBuider from "./FrameBlobBuilder";
4
- import { FrameManager } from "./FrameManager";
5
- import { Injector } from "../../injection/Injector";
6
- import { IContentProtectionConfig, IKeyboardPeripheralsConfig } from "../../Navigator";
3
+ import FrameBlobBuider from "./FrameBlobBuilder.ts";
4
+ import { FrameManager } from "./FrameManager.ts";
5
+ import { Injector } from "../../injection/Injector.ts";
6
+ import { IContentProtectionConfig, IKeyboardPeripheralsConfig } from "../../Navigator.ts";
7
7
 
8
8
  const UPPER_BOUNDARY = 5;
9
9
  const LOWER_BOUNDARY = 3;
@@ -23,8 +23,8 @@ export class FramePoolManager {
23
23
  private readonly keyboardPeripheralsConfig: IKeyboardPeripheralsConfig;
24
24
 
25
25
  constructor(
26
- container: HTMLElement,
27
- positions: Locator[],
26
+ container: HTMLElement,
27
+ positions: Locator[],
28
28
  cssProperties?: { [key: string]: string },
29
29
  injector?: Injector | null,
30
30
  contentProtectionConfig?: IContentProtectionConfig,
@@ -158,9 +158,9 @@ export class FramePoolManager {
158
158
  if(!itm) return; // TODO throw?
159
159
  if(!this.blobs.has(href)) {
160
160
  const blobBuilder = new FrameBlobBuider(
161
- pub,
162
- this.currentBaseURL || "",
163
- itm,
161
+ pub,
162
+ this.currentBaseURL || "",
163
+ itm,
164
164
  {
165
165
  cssProperties: this.currentCssProperties,
166
166
  injector: this.injector
@@ -208,17 +208,17 @@ export class FramePoolManager {
208
208
  const deepCompare = (obj1: { [key: string]: string }, obj2: { [key: string]: string }) => {
209
209
  const keys1 = Object.keys(obj1);
210
210
  const keys2 = Object.keys(obj2);
211
-
211
+
212
212
  if (keys1.length !== keys2.length) {
213
213
  return false;
214
214
  }
215
-
215
+
216
216
  for (const key of keys1) {
217
217
  if (obj1[key] !== obj2[key]) {
218
218
  return false;
219
219
  }
220
220
  }
221
-
221
+
222
222
  return true;
223
223
  };
224
224
 
@@ -270,4 +270,4 @@ export class FramePoolManager {
270
270
  });
271
271
  return ret as DOMRect;
272
272
  }
273
- }
273
+ }
@@ -1,4 +1,4 @@
1
- export * from "./FrameBlobBuilder";
2
- export * from "./FrameComms";
3
- export * from "./FrameManager";
4
- export * from "./FramePoolManager";
1
+ export * from "./FrameBlobBuilder.ts";
2
+ export * from "./FrameComms.ts";
3
+ export * from "./FrameManager.ts";
4
+ export * from "./FramePoolManager.ts";
@@ -1,4 +1,4 @@
1
- import { sML } from "../../helpers/sML";
1
+ import { sML } from "../../helpers/sML.ts";
2
2
 
3
3
  export interface Point {
4
4
  X: number;
@@ -108,7 +108,7 @@ export class FXLCoordinator {
108
108
  const y2 = Eve.touches[1].screenY - this.outerHeight - subT;
109
109
  return { X: (x1 + x2) / 2, Y: (y1 + y2) / 2 };
110
110
  }
111
-
111
+
112
112
  getBibiEvent(Eve: Event): BibiEvent {
113
113
  if(!Eve) return {
114
114
  Coord: null,
@@ -149,4 +149,4 @@ export class FXLCoordinator {
149
149
  Division: Division
150
150
  };
151
151
  }
152
- }
152
+ }
@@ -1,9 +1,9 @@
1
1
  import { Loader, ModuleName } from "@readium/navigator-html-injectables";
2
2
  import { Page, ReadingProgression } from "@readium/shared";
3
- import { FrameComms } from "../frame/FrameComms";
4
- import { FXLPeripherals } from "./FXLPeripherals";
5
- import { ReadiumWindow } from "../../../../navigator-html-injectables/types/src/helpers/dom";
6
- import { IContentProtectionConfig, IKeyboardPeripheralsConfig } from "../../Navigator";
3
+ import { FrameComms } from "../frame/FrameComms.ts";
4
+ import { FXLPeripherals } from "./FXLPeripherals.ts";
5
+ import type { ReadiumWindow } from "../../../../navigator-html-injectables/types/src/helpers/dom";
6
+ import { IContentProtectionConfig, IKeyboardPeripheralsConfig } from "../../Navigator.ts";
7
7
 
8
8
  export class FXLFrameManager {
9
9
  private frame: HTMLIFrameElement;
@@ -22,8 +22,8 @@ export class FXLFrameManager {
22
22
  private showPromise: Promise<void> | undefined;
23
23
 
24
24
  constructor(
25
- peripherals: FXLPeripherals,
26
- direction: ReadingProgression,
25
+ peripherals: FXLPeripherals,
26
+ direction: ReadingProgression,
27
27
  debugHref: string,
28
28
  contentProtectionConfig: IContentProtectionConfig = {},
29
29
  keyboardPeripheralsConfig: IKeyboardPeripheralsConfig = []
@@ -212,7 +212,7 @@ export class FXLFrameManager {
212
212
 
213
213
  // Send content protection config
214
214
  this.comms!.send("peripherals_protection", this.contentProtectionConfig);
215
-
215
+
216
216
  // Send keyboard peripherals separately
217
217
  if (this.keyboardPeripheralsConfig && this.keyboardPeripheralsConfig.length > 0) {
218
218
  this.comms!.send("keyboard_peripherals", this.keyboardPeripheralsConfig);
@@ -313,4 +313,4 @@ export class FXLFrameManager {
313
313
  get ldr() {
314
314
  return this.loader;
315
315
  }
316
- }
316
+ }
@@ -1,12 +1,12 @@
1
1
  import { ModuleName } from "@readium/navigator-html-injectables";
2
2
  import { Locator, Publication, ReadingProgression, Page, Link } from "@readium/shared";
3
- import { FrameCommsListener } from "../frame";
4
- import FrameBlobBuider from "../frame/FrameBlobBuilder";
5
- import { FXLFrameManager } from "./FXLFrameManager";
6
- import { FXLPeripherals } from "./FXLPeripherals";
7
- import { FXLSpreader, Orientation, Spread } from "./FXLSpreader";
8
- import { VisualNavigatorViewport, IContentProtectionConfig, IKeyboardPeripheralsConfig } from "../../Navigator";
9
- import { Injector } from "../../injection/Injector";
3
+ import { FrameCommsListener } from "../frame/index.ts";
4
+ import FrameBlobBuider from "../frame/FrameBlobBuilder.ts";
5
+ import { FXLFrameManager } from "./FXLFrameManager.ts";
6
+ import { FXLPeripherals } from "./FXLPeripherals.ts";
7
+ import { FXLSpreader, Orientation, Spread } from "./FXLSpreader.ts";
8
+ import { VisualNavigatorViewport, IContentProtectionConfig, IKeyboardPeripheralsConfig } from "../../Navigator.ts";
9
+ import { Injector } from "../../injection/Injector.ts";
10
10
 
11
11
  const UPPER_BOUNDARY = 8;
12
12
  const LOWER_BOUNDARY = 5;
@@ -49,8 +49,8 @@ export class FXLFramePoolManager {
49
49
  public readonly peripherals: FXLPeripherals;
50
50
 
51
51
  constructor(
52
- container: HTMLElement,
53
- positions: Locator[],
52
+ container: HTMLElement,
53
+ positions: Locator[],
54
54
  pub: Publication,
55
55
  injector?: Injector | null,
56
56
  contentProtectionConfig?: IContentProtectionConfig,
@@ -134,7 +134,7 @@ export class FXLFramePoolManager {
134
134
 
135
135
  clearTimeout(this.resizeTimeout);
136
136
  this.resizeTimeout = window.setTimeout(() => {
137
- // TODO optimize this expensive set of loops and operations
137
+ // TODO optimize this expensive set of loops and operations
138
138
  this.pool.forEach((frm, linkHref) => {
139
139
  let i = this.pub.readingOrder.items.findIndex(l => l.href === linkHref);
140
140
  const link = this.pub.readingOrder.items[i];
@@ -513,8 +513,8 @@ export class FXLFramePoolManager {
513
513
  if(!itm) return; // TODO throw?
514
514
  if(!this.blobs.has(href)) {
515
515
  const blobBuilder = new FrameBlobBuider(
516
- pub,
517
- this.currentBaseURL || "",
516
+ pub,
517
+ this.currentBaseURL || "",
518
518
  itm,
519
519
  {
520
520
  injector: this.injector
@@ -633,7 +633,11 @@ export class FXLFramePoolManager {
633
633
  progressions: new Map(),
634
634
  positions: null
635
635
  };
636
- const currentSpread = this.spreader.currentSpread(this.currentSlide, this.perPage);
636
+ // Mirror currentFrames: for single-page mode use currentSlide directly,
637
+ // otherwise use the spreader (which indexes by spread, not by item).
638
+ const currentSpread = this.perPage < 2
639
+ ? [this.pub.readingOrder.items[this.currentSlide]]
640
+ : this.spreader.currentSpread(this.currentSlide, this.perPage);
637
641
  currentSpread.forEach(link => {
638
642
  viewport.readingOrder.push(link.href);
639
643
  viewport.progressions.set(link.href, { start: 0, end: 1 }); // FXL always uses [0,1] progression
@@ -641,7 +645,7 @@ export class FXLFramePoolManager {
641
645
 
642
646
  // Set positions using currentNumbers
643
647
  viewport.positions = this.getCurrentNumbers();
644
-
648
+
645
649
  return viewport;
646
650
  }
647
651
 
@@ -1,6 +1,6 @@
1
- import { FXLCoordinator, Point } from "./FXLCoordinator";
2
- import { FXLFramePoolManager } from "./FXLFramePoolManager";
3
- import { FXLPeripheralsDebug } from "./FXLPeripheralsDebug";
1
+ import { FXLCoordinator, Point } from "./FXLCoordinator.ts";
2
+ import { FXLFramePoolManager } from "./FXLFramePoolManager.ts";
3
+ import { FXLPeripheralsDebug } from "./FXLPeripheralsDebug.ts";
4
4
 
5
5
  const MAX_SCALE = 6; // 6x zoom
6
6
  const MIN_SCALE = 1.02;
@@ -584,4 +584,4 @@ export class FXLPeripherals {
584
584
  // this.ui.toggle(false);
585
585
  this.manager.slideToCurrent(true, true); // slideToNegativeClone || slideToPositiveClone
586
586
  }
587
- }
587
+ }
@@ -1,5 +1,5 @@
1
- export * from "./FXLCoordinator";
2
- export * from "./FXLFrameManager";
3
- export * from "./FXLFramePoolManager";
4
- export * from "./FXLPeripherals";
5
- export * from "./FXLSpreader";
1
+ export * from "./FXLCoordinator.ts";
2
+ export * from "./FXLFrameManager.ts";
3
+ export * from "./FXLFramePoolManager.ts";
4
+ export * from "./FXLPeripherals.ts";
5
+ export * from "./FXLSpreader.ts";
@@ -0,0 +1,45 @@
1
+ import { Metadata, ReadingProgression } from "@readium/shared";
2
+
3
+ export type ScriptMode = 'ltr' | 'rtl' | 'cjk-horizontal' | 'cjk-vertical';
4
+
5
+ /**
6
+ * Derives the script mode from publication metadata.
7
+ *
8
+ * Rules:
9
+ * - Only the first language in the array is used. A Latin book containing
10
+ * some Japanese is still Latin.
11
+ * - For CJK (zh/ja/ko): both language AND explicit reading progression are
12
+ * required. CJK vertical = explicit rtl + CJK language. CJK horizontal =
13
+ * CJK language with ltr or unset progression.
14
+ * - For RTL (ar/fa/he): language wins. If the primary language is a RTL
15
+ * script, RTL mode is applied regardless of the explicit progression
16
+ * direction declared in the OPF.
17
+ */
18
+ export function getScriptMode(metadata: Metadata): ScriptMode {
19
+ const primaryLang = metadata.languages?.[0]?.toLowerCase();
20
+ // Use explicit readingProgression only — effectiveReadingProgression
21
+ // auto-detects from language, which would create circular logic here.
22
+ const progression = metadata.readingProgression;
23
+
24
+ if (primaryLang) {
25
+ const isCJK = primaryLang.startsWith('zh') ||
26
+ primaryLang.startsWith('ja') ||
27
+ primaryLang.startsWith('ko');
28
+ if (isCJK) {
29
+ // Vertical requires explicit rtl progression. If progression
30
+ // conflicts (e.g. ltr) we fall back to horizontal.
31
+ return progression === ReadingProgression.rtl
32
+ ? 'cjk-vertical'
33
+ : 'cjk-horizontal';
34
+ }
35
+
36
+ // RTL: language is authoritative. ar/fa/he → rtl regardless of
37
+ // what the OPF says about page-progression-direction.
38
+ const isRTLScript = primaryLang.startsWith('ar') ||
39
+ primaryLang.startsWith('fa') ||
40
+ primaryLang.startsWith('he');
41
+ if (isRTLScript) return 'rtl';
42
+ }
43
+
44
+ return 'ltr';
45
+ }
package/src/epub/index.ts CHANGED
@@ -1,5 +1,6 @@
1
- export * from "./EpubNavigator";
2
- export * from "./frame";
3
- export * from "./fxl";
4
- export * from "./preferences";
5
- export * from "./css";
1
+ export * from "./EpubNavigator.ts";
2
+ export * from "./frame/index.ts";
3
+ export * from "./fxl/index.ts";
4
+ export * from "./preferences/index.ts";
5
+ export * from "./css/index.ts";
6
+ export { getScriptMode, type ScriptMode } from "./helpers/scriptMode.ts";
@@ -1,25 +1,25 @@
1
- import {
1
+ import {
2
2
  ExperimentKey,
3
- fontSizeRangeConfig,
4
- fontWeightRangeConfig,
5
- fontWidthRangeConfig,
3
+ fontSizeRangeConfig,
4
+ fontWeightRangeConfig,
5
+ fontWidthRangeConfig,
6
6
  TextAlignment
7
- } from "../../preferences/Types";
7
+ } from "../../preferences/Types.ts";
8
8
 
9
- import {
10
- ensureBoolean,
11
- ensureEnumValue,
12
- ensureExperiment,
13
- ensureFilter,
14
- ensureLessThanOrEqual,
15
- ensureMoreThanOrEqual,
16
- ensureNonNegative,
17
- ensureString,
18
- ensureValueInRange,
19
- withFallback
20
- } from "../../preferences/guards";
9
+ import {
10
+ ensureBoolean,
11
+ ensureEnumValue,
12
+ ensureExperiment,
13
+ ensureFilter,
14
+ ensureLessThanOrEqual,
15
+ ensureMoreThanOrEqual,
16
+ ensureNonNegative,
17
+ ensureString,
18
+ ensureValueInRange,
19
+ withFallback
20
+ } from "../../preferences/guards.ts";
21
21
 
22
- import { sMLWithRequest } from "../../helpers";
22
+ import { sMLWithRequest } from "../../helpers/index.ts";
23
23
 
24
24
  export interface IEpubDefaults {
25
25
  backgroundColor?: string | null,
@@ -127,11 +127,11 @@ export class EpubDefaults {
127
127
  this.hyphens = ensureBoolean(defaults.hyphens) ?? null;
128
128
  this.invertFilter = ensureFilter(defaults.invertFilter) ?? false;
129
129
  this.invertGaijiFilter = ensureFilter(defaults.invertGaijiFilter) ?? false;
130
- this.iOSPatch = defaults.iOSPatch === false
131
- ? false
130
+ this.iOSPatch = defaults.iOSPatch === false
131
+ ? false
132
132
  : ((sMLWithRequest.OS.iOS || sMLWithRequest.OS.iPadOS) && sMLWithRequest.iOSRequest === "mobile");
133
- this.iPadOSPatch = defaults.iPadOSPatch === false
134
- ? false
133
+ this.iPadOSPatch = defaults.iPadOSPatch === false
134
+ ? false
135
135
  : (sMLWithRequest.OS.iPadOS && sMLWithRequest.iOSRequest === "desktop");
136
136
  this.letterSpacing = ensureNonNegative(defaults.letterSpacing) || null;
137
137
  this.ligatures = ensureBoolean(defaults.ligatures) ?? null;
@@ -160,4 +160,4 @@ export class EpubDefaults {
160
160
 
161
161
  this.experiments = ensureExperiment(defaults.experiments) || null;
162
162
  }
163
- }
163
+ }
@@ -1,20 +1,20 @@
1
- import { ConfigurablePreferences } from "../../preferences/Configurable";
1
+ import { ConfigurablePreferences } from "../../preferences/Configurable.ts";
2
2
 
3
- import {
4
- TextAlignment,
5
- fontSizeRangeConfig,
6
- fontWeightRangeConfig,
7
- fontWidthRangeConfig
8
- } from "../../preferences/Types";
3
+ import {
4
+ TextAlignment,
5
+ fontSizeRangeConfig,
6
+ fontWeightRangeConfig,
7
+ fontWidthRangeConfig
8
+ } from "../../preferences/Types.ts";
9
9
 
10
- import {
11
- ensureBoolean,
12
- ensureEnumValue,
13
- ensureFilter,
14
- ensureNonNegative,
15
- ensureString,
16
- ensureValueInRange
17
- } from "../../preferences/guards";
10
+ import {
11
+ ensureBoolean,
12
+ ensureEnumValue,
13
+ ensureFilter,
14
+ ensureNonNegative,
15
+ ensureString,
16
+ ensureValueInRange
17
+ } from "../../preferences/guards.ts";
18
18
 
19
19
  export interface IEpubPreferences {
20
20
  backgroundColor?: string | null,
@@ -181,4 +181,4 @@ export class EpubPreferences implements ConfigurablePreferences<EpubPreferences>
181
181
  }
182
182
  return new EpubPreferences(merged);
183
183
  }
184
- }
184
+ }