@readium/navigator 2.2.6 → 2.2.8

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 (47) hide show
  1. package/dist/ar-DyHX_uy2-DyHX_uy2-DyHX_uy2.js +7 -0
  2. package/dist/ar-DyHX_uy2-DyHX_uy2.js +7 -0
  3. package/dist/da-Dct0PS3E-Dct0PS3E-Dct0PS3E.js +7 -0
  4. package/dist/da-Dct0PS3E-Dct0PS3E.js +7 -0
  5. package/dist/fr-C5HEel98-C5HEel98-C5HEel98.js +7 -0
  6. package/dist/fr-C5HEel98-C5HEel98.js +7 -0
  7. package/dist/index.js +4389 -2401
  8. package/dist/index.umd.cjs +1571 -39
  9. package/dist/it-DFOBoXGy-DFOBoXGy-DFOBoXGy.js +7 -0
  10. package/dist/it-DFOBoXGy-DFOBoXGy.js +7 -0
  11. package/dist/pt_PT-Di3sVjze-Di3sVjze-Di3sVjze.js +7 -0
  12. package/dist/pt_PT-Di3sVjze-Di3sVjze.js +7 -0
  13. package/dist/sv-BfzAFsVN-BfzAFsVN-BfzAFsVN.js +7 -0
  14. package/dist/sv-BfzAFsVN-BfzAFsVN.js +7 -0
  15. package/package.json +6 -5
  16. package/src/dom/_readium_cssSelectorGenerator.js +1 -0
  17. package/src/dom/_readium_executionCleanup.js +13 -0
  18. package/src/dom/_readium_executionPrevention.js +65 -0
  19. package/src/dom/_readium_webpubExecution.js +4 -0
  20. package/src/epub/EpubNavigator.ts +26 -2
  21. package/src/epub/frame/FrameBlobBuilder.ts +37 -130
  22. package/src/epub/frame/FramePoolManager.ts +34 -5
  23. package/src/epub/fxl/FXLFramePoolManager.ts +20 -2
  24. package/src/helpers/minify.ts +14 -0
  25. package/src/index.ts +2 -1
  26. package/src/injection/Injectable.ts +85 -0
  27. package/src/injection/Injector.ts +356 -0
  28. package/src/injection/epubInjectables.ts +90 -0
  29. package/src/injection/index.ts +2 -0
  30. package/src/injection/webpubInjectables.ts +59 -0
  31. package/src/webpub/WebPubBlobBuilder.ts +19 -76
  32. package/src/webpub/WebPubFramePoolManager.ts +29 -4
  33. package/src/webpub/WebPubNavigator.ts +15 -1
  34. package/types/src/epub/EpubNavigator.d.ts +3 -0
  35. package/types/src/epub/frame/FrameBlobBuilder.d.ts +7 -4
  36. package/types/src/epub/frame/FramePoolManager.d.ts +3 -1
  37. package/types/src/epub/fxl/FXLFramePoolManager.d.ts +3 -1
  38. package/types/src/helpers/minify.d.ts +12 -0
  39. package/types/src/index.d.ts +1 -0
  40. package/types/src/injection/Injectable.d.ts +68 -0
  41. package/types/src/injection/Injector.d.ts +22 -0
  42. package/types/src/injection/epubInjectables.d.ts +6 -0
  43. package/types/src/injection/index.d.ts +2 -0
  44. package/types/src/injection/webpubInjectables.d.ts +5 -0
  45. package/types/src/webpub/WebPubBlobBuilder.d.ts +7 -3
  46. package/types/src/webpub/WebPubFramePoolManager.d.ts +3 -1
  47. package/types/src/webpub/WebPubNavigator.d.ts +3 -0
@@ -2,6 +2,7 @@ import { ModuleName } from "@readium/navigator-html-injectables";
2
2
  import { Locator, Publication } from "@readium/shared";
3
3
  import { WebPubBlobBuilder } from "./WebPubBlobBuilder";
4
4
  import { WebPubFrameManager } from "./WebPubFrameManager";
5
+ import { Injector } from "../injection/Injector";
5
6
 
6
7
  export class WebPubFramePoolManager {
7
8
  private readonly container: HTMLElement;
@@ -12,10 +13,16 @@ export class WebPubFramePoolManager {
12
13
  private readonly inprogress: Map<string, Promise<void>> = new Map();
13
14
  private pendingUpdates: Map<string, { inPool: boolean }> = new Map();
14
15
  private currentBaseURL: string | undefined;
16
+ private readonly injector?: Injector | null = null;
15
17
 
16
- constructor(container: HTMLElement, cssProperties?: { [key: string]: string }) {
18
+ constructor(
19
+ container: HTMLElement,
20
+ cssProperties?: { [key: string]: string },
21
+ injector?: Injector | null
22
+ ) {
17
23
  this.container = container;
18
24
  this.currentCssProperties = cssProperties;
25
+ this.injector = injector;
19
26
  }
20
27
 
21
28
  async destroy() {
@@ -42,9 +49,15 @@ export class WebPubFramePoolManager {
42
49
  this.pool.clear();
43
50
 
44
51
  // Revoke all blobs
45
- this.blobs.forEach(v => URL.revokeObjectURL(v));
52
+ this.blobs.forEach(v => {
53
+ this.injector?.releaseBlobUrl?.(v);
54
+ URL.revokeObjectURL(v);
55
+ });
46
56
  this.blobs.clear();
47
57
 
58
+ // Clean up injector if it exists
59
+ this.injector?.dispose();
60
+
48
61
  // Empty container of elements
49
62
  this.container.childNodes.forEach(v => {
50
63
  if(v.nodeType === Node.ELEMENT_NODE || v.nodeType === Node.TEXT_NODE) v.remove();
@@ -87,7 +100,10 @@ export class WebPubFramePoolManager {
87
100
  });
88
101
 
89
102
  if(this.currentBaseURL !== undefined && pub.baseURL !== this.currentBaseURL) {
90
- this.blobs.forEach(v => URL.revokeObjectURL(v));
103
+ this.blobs.forEach(v => {
104
+ this.injector?.releaseBlobUrl?.(v);
105
+ URL.revokeObjectURL(v);
106
+ });
91
107
  this.blobs.clear();
92
108
  }
93
109
  this.currentBaseURL = pub.baseURL;
@@ -97,6 +113,7 @@ export class WebPubFramePoolManager {
97
113
  if(this.pendingUpdates.has(href) && this.pendingUpdates.get(href)?.inPool === false) {
98
114
  const url = this.blobs.get(href);
99
115
  if(url) {
116
+ this.injector?.releaseBlobUrl?.(url);
100
117
  URL.revokeObjectURL(url);
101
118
  this.blobs.delete(href);
102
119
  this.pendingUpdates.delete(href);
@@ -117,7 +134,15 @@ export class WebPubFramePoolManager {
117
134
  const itm = pub.readingOrder.findWithHref(href);
118
135
  if(!itm) return;
119
136
  if(!this.blobs.has(href)) {
120
- const blobBuilder = new WebPubBlobBuilder(pub, this.currentBaseURL || "", itm, this.currentCssProperties);
137
+ const blobBuilder = new WebPubBlobBuilder(
138
+ pub,
139
+ this.currentBaseURL || "",
140
+ itm,
141
+ {
142
+ cssProperties: this.currentCssProperties,
143
+ injector: this.injector
144
+ }
145
+ );
121
146
  const blobURL = await blobBuilder.build();
122
147
  this.blobs.set(href, blobURL);
123
148
  }
@@ -14,10 +14,14 @@ import { IWebPubDefaults, WebPubDefaults } from "./preferences/WebPubDefaults";
14
14
  import { WebPubSettings } from "./preferences/WebPubSettings";
15
15
  import { IPreferencesEditor } from "../preferences/PreferencesEditor";
16
16
  import { WebPubPreferencesEditor } from "./preferences/WebPubPreferencesEditor";
17
+ import { Injector } from "../injection/Injector";
18
+ import { createReadiumWebPubRules } from "../injection/webpubInjectables";
19
+ import { IInjectablesConfig } from "../injection/Injectable";
17
20
 
18
21
  export interface WebPubNavigatorConfiguration {
19
22
  preferences: IWebPubPreferences;
20
23
  defaults: IWebPubDefaults;
24
+ injectables?: IInjectablesConfig;
21
25
  }
22
26
 
23
27
  export interface WebPubNavigatorListeners {
@@ -57,6 +61,7 @@ export class WebPubNavigator extends VisualNavigator implements Configurable<Web
57
61
  private _settings: WebPubSettings;
58
62
  private _css: WebPubCSS;
59
63
  private _preferencesEditor: WebPubPreferencesEditor | null = null;
64
+ private readonly _injector: Injector | null = null;
60
65
 
61
66
  private webViewport: VisualNavigatorViewport = {
62
67
  readingOrder: [],
@@ -79,6 +84,15 @@ export class WebPubNavigator extends VisualNavigator implements Configurable<Web
79
84
  userProperties: new WebUserProperties({ zoom: this._settings.zoom })
80
85
  });
81
86
 
87
+ // Combine WebPub rules with user-provided injectables
88
+ const webpubRules = createReadiumWebPubRules();
89
+ const userConfig = configuration.injectables || { rules: [], allowedDomains: [] };
90
+
91
+ this._injector = new Injector({
92
+ rules: [...webpubRules, ...userConfig.rules],
93
+ allowedDomains: userConfig.allowedDomains
94
+ });
95
+
82
96
  // Initialize current location
83
97
  if (initialPosition && typeof initialPosition.copyWithLocations === 'function') {
84
98
  this.currentLocation = initialPosition;
@@ -95,7 +109,7 @@ export class WebPubNavigator extends VisualNavigator implements Configurable<Web
95
109
  public async load() {
96
110
  await this.updateCSS(false);
97
111
  const cssProperties = this.compileCSSProperties(this._css);
98
- this.framePool = new WebPubFramePoolManager(this.container, cssProperties);
112
+ this.framePool = new WebPubFramePoolManager(this.container, cssProperties, this._injector);
99
113
 
100
114
  await this.apply();
101
115
  }
@@ -10,10 +10,12 @@ import { IEpubPreferences, EpubPreferences } from "./preferences/EpubPreferences
10
10
  import { IEpubDefaults } from "./preferences/EpubDefaults";
11
11
  import { EpubSettings } from "./preferences";
12
12
  import { EpubPreferencesEditor } from "./preferences/EpubPreferencesEditor";
13
+ import { IInjectablesConfig } from "../injection/Injectable";
13
14
  export type ManagerEventKey = "zoom";
14
15
  export interface EpubNavigatorConfiguration {
15
16
  preferences: IEpubPreferences;
16
17
  defaults: IEpubDefaults;
18
+ injectables?: IInjectablesConfig;
17
19
  }
18
20
  export interface EpubNavigatorListeners {
19
21
  frameLoaded: (wnd: Window) => void;
@@ -42,6 +44,7 @@ export declare class EpubNavigator extends VisualNavigator implements Configurab
42
44
  private _settings;
43
45
  private _css;
44
46
  private _preferencesEditor;
47
+ private readonly _injector;
45
48
  private resizeObserver;
46
49
  private reflowViewport;
47
50
  constructor(container: HTMLElement, pub: Publication, listeners: EpubNavigatorListeners, positions?: Locator[], initialPosition?: Locator | undefined, configuration?: EpubNavigatorConfiguration);
@@ -1,17 +1,20 @@
1
1
  import { Link, Publication } from "@readium/shared";
2
+ import { Injector } from "../../injection/Injector";
2
3
  export default class FrameBlobBuider {
3
4
  private readonly item;
4
5
  private readonly burl;
5
6
  private readonly pub;
6
7
  private readonly cssProperties?;
7
- constructor(pub: Publication, baseURL: string, item: Link, cssProperties?: {
8
- [key: string]: string;
8
+ private readonly injector;
9
+ constructor(pub: Publication, baseURL: string, item: Link, options: {
10
+ cssProperties?: {
11
+ [key: string]: string;
12
+ };
13
+ injector?: Injector | null;
9
14
  });
10
15
  build(fxl?: boolean): Promise<string>;
11
16
  private buildHtmlFrame;
12
17
  private buildImageFrame;
13
- private hasExecutable;
14
- private hasStyle;
15
18
  private setProperties;
16
19
  private finalizeDOM;
17
20
  }
@@ -1,6 +1,7 @@
1
1
  import { ModuleName } from "@readium/navigator-html-injectables";
2
2
  import { Locator, Publication } from "@readium/shared";
3
3
  import { FrameManager } from "./FrameManager";
4
+ import { Injector } from "../../injection/Injector";
4
5
  export declare class FramePoolManager {
5
6
  private readonly container;
6
7
  private readonly positions;
@@ -11,9 +12,10 @@ export declare class FramePoolManager {
11
12
  private readonly inprogress;
12
13
  private pendingUpdates;
13
14
  private currentBaseURL;
15
+ private readonly injector;
14
16
  constructor(container: HTMLElement, positions: Locator[], cssProperties?: {
15
17
  [key: string]: string;
16
- });
18
+ }, injector?: Injector | null);
17
19
  destroy(): Promise<void>;
18
20
  update(pub: Publication, locator: Locator, modules: ModuleName[], force?: boolean): Promise<void>;
19
21
  setCSSProperties(properties: {
@@ -4,6 +4,7 @@ import { FrameCommsListener } from "../frame";
4
4
  import { FXLFrameManager } from "./FXLFrameManager";
5
5
  import { FXLPeripherals } from "./FXLPeripherals";
6
6
  import { VisualNavigatorViewport } from "../../Navigator";
7
+ import { Injector } from "../../injection/Injector";
7
8
  export declare class FXLFramePoolManager {
8
9
  private readonly container;
9
10
  private readonly positions;
@@ -14,6 +15,7 @@ export declare class FXLFramePoolManager {
14
15
  private readonly delayedTimeout;
15
16
  private currentBaseURL;
16
17
  private previousFrames;
18
+ private readonly injector;
17
19
  private readonly bookElement;
18
20
  readonly spineElement: HTMLDivElement;
19
21
  private readonly pub;
@@ -28,7 +30,7 @@ export declare class FXLFramePoolManager {
28
30
  private containerHeightCached;
29
31
  private resizeTimeout;
30
32
  readonly peripherals: FXLPeripherals;
31
- constructor(container: HTMLElement, positions: Locator[], pub: Publication);
33
+ constructor(container: HTMLElement, positions: Locator[], pub: Publication, injector?: Injector | null);
32
34
  private _listener;
33
35
  set listener(listener: FrameCommsListener);
34
36
  get listener(): FrameCommsListener;
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Utilities for processing CSS and JavaScript content
3
+ */
4
+ /**
5
+ * Minifies JavaScript by removing comments and normalizing whitespace
6
+ */
7
+ export declare const stripJS: (source: string) => string;
8
+ /**
9
+ * Minifies CSS by removing comments and normalizing whitespace
10
+ * Note: URL resolution should be handled by the caller with correct context
11
+ */
12
+ export declare const stripCSS: (source: string) => string;
@@ -5,3 +5,4 @@ export * from './audio';
5
5
  export * from './helpers';
6
6
  export * from './preferences';
7
7
  export * from './css';
8
+ export * from './injection';
@@ -0,0 +1,68 @@
1
+ import { Link } from "@readium/shared";
2
+ type ForbiddenAttributes = "type" | "rel" | "href" | "src";
3
+ type AllowedAttributes = {
4
+ [K in string]: K extends ForbiddenAttributes ? never : (string | boolean | undefined);
5
+ } & {
6
+ [K in ForbiddenAttributes]?: never;
7
+ };
8
+ export interface IBaseInjectable {
9
+ id?: string;
10
+ target?: "head" | "body";
11
+ type?: string;
12
+ condition?: (doc: Document) => boolean;
13
+ attributes?: AllowedAttributes;
14
+ }
15
+ export interface IScriptInjectable extends IBaseInjectable {
16
+ as: "script";
17
+ rel?: never;
18
+ }
19
+ export interface ILinkInjectable extends IBaseInjectable {
20
+ as: "link";
21
+ rel: string;
22
+ }
23
+ export interface IUrlInjectable {
24
+ url: string;
25
+ }
26
+ export interface IBlobInjectable {
27
+ blob: Blob;
28
+ }
29
+ export type IInjectable = (IScriptInjectable | ILinkInjectable) & (IUrlInjectable | IBlobInjectable);
30
+ /**
31
+ * Defines a rule for resource injection, specifying which resources to inject into which documents.
32
+ */
33
+ export interface IInjectableRule {
34
+ /**
35
+ * List of resource URLs or patterns that this rule applies to.
36
+ * Can be exact URLs or patterns with wildcards.
37
+ */
38
+ resources: Array<string | RegExp>;
39
+ /**
40
+ * Resources to inject at the beginning of the target (in array order)
41
+ */
42
+ prepend?: IInjectable[];
43
+ /**
44
+ * Resources to inject at the end of the target (in array order)
45
+ */
46
+ append?: IInjectable[];
47
+ }
48
+ export interface IInjectablesConfig {
49
+ rules: IInjectableRule[];
50
+ allowedDomains?: string[];
51
+ }
52
+ export interface IInjector {
53
+ /**
54
+ * Injects resources into a document based on matching rules
55
+ * @param doc The document to inject resources into
56
+ * @param link The link being loaded, used to match against injection rules
57
+ */
58
+ injectForDocument(doc: Document, link: Link): Promise<void>;
59
+ /**
60
+ * Cleans up any resources used by the injector
61
+ */
62
+ dispose(): void;
63
+ /**
64
+ * Get the list of allowed domains
65
+ */
66
+ getAllowedDomains(): string[];
67
+ }
68
+ export {};
@@ -0,0 +1,22 @@
1
+ import { IInjector, IInjectablesConfig } from "./Injectable";
2
+ import { Link } from "@readium/shared";
3
+ export declare class Injector implements IInjector {
4
+ private readonly blobStore;
5
+ private readonly createdBlobUrls;
6
+ private readonly rules;
7
+ private readonly allowedDomains;
8
+ private injectableIdCounter;
9
+ constructor(config: IInjectablesConfig);
10
+ dispose(): void;
11
+ getAllowedDomains(): string[];
12
+ injectForDocument(doc: Document, link: Link): Promise<void>;
13
+ private matchesRule;
14
+ private getOrCreateBlobUrl;
15
+ releaseBlobUrl(url: string): Promise<void>;
16
+ private getResourceUrl;
17
+ private createPreloadLink;
18
+ private createElement;
19
+ private applyRule;
20
+ private processInjectable;
21
+ private isValidUrl;
22
+ }
@@ -0,0 +1,6 @@
1
+ import { IInjectableRule } from "../injection/Injectable";
2
+ import { Metadata } from "@readium/shared";
3
+ /**
4
+ * Creates injectable rules for EPUB content documents
5
+ */
6
+ export declare function createReadiumEpubRules(metadata: Metadata): IInjectableRule[];
@@ -0,0 +1,2 @@
1
+ export * from "./Injectable";
2
+ export * from "./Injector";
@@ -0,0 +1,5 @@
1
+ import { IInjectableRule } from "../injection/Injectable";
2
+ /**
3
+ * Creates injectable rules for WebPub content documents
4
+ */
5
+ export declare function createReadiumWebPubRules(): IInjectableRule[];
@@ -1,15 +1,19 @@
1
1
  import { Link, Publication } from "@readium/shared";
2
+ import { Injector } from "../injection/Injector";
2
3
  export declare class WebPubBlobBuilder {
3
4
  private readonly item;
4
5
  private readonly burl;
5
6
  private readonly pub;
6
7
  private readonly cssProperties?;
7
- constructor(pub: Publication, baseURL: string, item: Link, cssProperties?: {
8
- [key: string]: string;
8
+ private readonly injector;
9
+ constructor(pub: Publication, baseURL: string, item: Link, options: {
10
+ cssProperties?: {
11
+ [key: string]: string;
12
+ };
13
+ injector?: Injector | null;
9
14
  });
10
15
  build(): Promise<string>;
11
16
  private buildHtmlFrame;
12
- private hasExecutable;
13
17
  private setProperties;
14
18
  private finalizeDOM;
15
19
  private serializeAsHTML;
@@ -1,6 +1,7 @@
1
1
  import { ModuleName } from "@readium/navigator-html-injectables";
2
2
  import { Locator, Publication } from "@readium/shared";
3
3
  import { WebPubFrameManager } from "./WebPubFrameManager";
4
+ import { Injector } from "../injection/Injector";
4
5
  export declare class WebPubFramePoolManager {
5
6
  private readonly container;
6
7
  private _currentFrame;
@@ -10,9 +11,10 @@ export declare class WebPubFramePoolManager {
10
11
  private readonly inprogress;
11
12
  private pendingUpdates;
12
13
  private currentBaseURL;
14
+ private readonly injector?;
13
15
  constructor(container: HTMLElement, cssProperties?: {
14
16
  [key: string]: string;
15
- });
17
+ }, injector?: Injector | null);
16
18
  destroy(): Promise<void>;
17
19
  update(pub: Publication, locator: Locator, modules: ModuleName[]): Promise<void>;
18
20
  setCSSProperties(properties: {
@@ -8,9 +8,11 @@ import { IWebPubPreferences, WebPubPreferences } from "./preferences/WebPubPrefe
8
8
  import { IWebPubDefaults } from "./preferences/WebPubDefaults";
9
9
  import { WebPubSettings } from "./preferences/WebPubSettings";
10
10
  import { IPreferencesEditor } from "../preferences/PreferencesEditor";
11
+ import { IInjectablesConfig } from "../injection/Injectable";
11
12
  export interface WebPubNavigatorConfiguration {
12
13
  preferences: IWebPubPreferences;
13
14
  defaults: IWebPubDefaults;
15
+ injectables?: IInjectablesConfig;
14
16
  }
15
17
  export interface WebPubNavigatorListeners {
16
18
  frameLoaded: (wnd: Window) => void;
@@ -35,6 +37,7 @@ export declare class WebPubNavigator extends VisualNavigator implements Configur
35
37
  private _settings;
36
38
  private _css;
37
39
  private _preferencesEditor;
40
+ private readonly _injector;
38
41
  private webViewport;
39
42
  constructor(container: HTMLElement, pub: Publication, listeners: WebPubNavigatorListeners, initialPosition?: Locator | undefined, configuration?: WebPubNavigatorConfiguration);
40
43
  load(): Promise<void>;