@asteasolutions/epub-reader 1.0.0

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 (98) hide show
  1. package/.prettierrc.js +6 -0
  2. package/README.md +104 -0
  3. package/dist/array.d.ts +1 -0
  4. package/dist/array.js +19 -0
  5. package/dist/array.js.map +1 -0
  6. package/dist/audio-player.d.ts +28 -0
  7. package/dist/audio-player.js +77 -0
  8. package/dist/audio-player.js.map +1 -0
  9. package/dist/book-loaders/ajax-unpacked.d.ts +12 -0
  10. package/dist/book-loaders/ajax-unpacked.js +46 -0
  11. package/dist/book-loaders/ajax-unpacked.js.map +1 -0
  12. package/dist/book-loaders/index.d.ts +13 -0
  13. package/dist/book-loaders/index.js +15 -0
  14. package/dist/book-loaders/index.js.map +1 -0
  15. package/dist/book-loaders/zip.d.ts +12 -0
  16. package/dist/book-loaders/zip.js +67 -0
  17. package/dist/book-loaders/zip.js.map +1 -0
  18. package/dist/book.d.ts +16 -0
  19. package/dist/book.js +60 -0
  20. package/dist/book.js.map +1 -0
  21. package/dist/content-controller/reflowable-content.d.ts +24 -0
  22. package/dist/content-controller/reflowable-content.js +115 -0
  23. package/dist/content-controller/reflowable-content.js.map +1 -0
  24. package/dist/content-controller.d.ts +10 -0
  25. package/dist/content-controller.js +2 -0
  26. package/dist/content-controller.js.map +1 -0
  27. package/dist/epub-types/container.d.ts +19 -0
  28. package/dist/epub-types/container.js +2 -0
  29. package/dist/epub-types/container.js.map +1 -0
  30. package/dist/epub-types/package/collection.d.ts +13 -0
  31. package/dist/epub-types/package/collection.js +2 -0
  32. package/dist/epub-types/package/collection.js.map +1 -0
  33. package/dist/epub-types/package/index.d.ts +18 -0
  34. package/dist/epub-types/package/index.js +2 -0
  35. package/dist/epub-types/package/index.js.map +1 -0
  36. package/dist/epub-types/package/manifest.d.ts +12 -0
  37. package/dist/epub-types/package/manifest.js +2 -0
  38. package/dist/epub-types/package/manifest.js.map +1 -0
  39. package/dist/epub-types/package/metadata.d.ts +44 -0
  40. package/dist/epub-types/package/metadata.js +2 -0
  41. package/dist/epub-types/package/metadata.js.map +1 -0
  42. package/dist/epub-types/package/spine.d.ts +11 -0
  43. package/dist/epub-types/package/spine.js +2 -0
  44. package/dist/epub-types/package/spine.js.map +1 -0
  45. package/dist/epub-types/smil.d.ts +97 -0
  46. package/dist/epub-types/smil.js +2 -0
  47. package/dist/epub-types/smil.js.map +1 -0
  48. package/dist/epub-types/xml.d.ts +9 -0
  49. package/dist/epub-types/xml.js +2 -0
  50. package/dist/epub-types/xml.js.map +1 -0
  51. package/dist/index.d.ts +6 -0
  52. package/dist/index.js +4 -0
  53. package/dist/index.js.map +1 -0
  54. package/dist/media-overlay.d.ts +32 -0
  55. package/dist/media-overlay.js +177 -0
  56. package/dist/media-overlay.js.map +1 -0
  57. package/dist/package-parser/index.d.ts +27 -0
  58. package/dist/package-parser/index.js +72 -0
  59. package/dist/package-parser/index.js.map +1 -0
  60. package/dist/package-parser/nav-parser.d.ts +17 -0
  61. package/dist/package-parser/nav-parser.js +30 -0
  62. package/dist/package-parser/nav-parser.js.map +1 -0
  63. package/dist/package-parser/overlay-parser.d.ts +10 -0
  64. package/dist/package-parser/overlay-parser.js +35 -0
  65. package/dist/package-parser/overlay-parser.js.map +1 -0
  66. package/dist/plugin.d.ts +7 -0
  67. package/dist/plugin.js +2 -0
  68. package/dist/plugin.js.map +1 -0
  69. package/dist/plugins/chapter-links-plugin.d.ts +11 -0
  70. package/dist/plugins/chapter-links-plugin.js +36 -0
  71. package/dist/plugins/chapter-links-plugin.js.map +1 -0
  72. package/dist/plugins/reader-events-plugin.d.ts +14 -0
  73. package/dist/plugins/reader-events-plugin.js +32 -0
  74. package/dist/plugins/reader-events-plugin.js.map +1 -0
  75. package/dist/plugins/text-highlighter-plugin.d.ts +11 -0
  76. package/dist/plugins/text-highlighter-plugin.js +32 -0
  77. package/dist/plugins/text-highlighter-plugin.js.map +1 -0
  78. package/dist/reader-events-listener.d.ts +4 -0
  79. package/dist/reader-events-listener.js +2 -0
  80. package/dist/reader-events-listener.js.map +1 -0
  81. package/dist/reader.d.ts +51 -0
  82. package/dist/reader.js +179 -0
  83. package/dist/reader.js.map +1 -0
  84. package/dist/smil/helper.d.ts +25 -0
  85. package/dist/smil/helper.js +71 -0
  86. package/dist/smil/helper.js.map +1 -0
  87. package/dist/smil/index.d.ts +21 -0
  88. package/dist/smil/index.js +105 -0
  89. package/dist/smil/index.js.map +1 -0
  90. package/dist/styles.d.ts +2 -0
  91. package/dist/styles.js +6 -0
  92. package/dist/styles.js.map +1 -0
  93. package/dist/uri.d.ts +5 -0
  94. package/dist/uri.js +19 -0
  95. package/dist/uri.js.map +1 -0
  96. package/eslint.config.mjs +31 -0
  97. package/package.json +32 -0
  98. package/tsconfig.json +19 -0
@@ -0,0 +1,115 @@
1
+ export const DOCUMENT_CSS = `
2
+ html, body {
3
+ margin: 0;
4
+ padding: 0;
5
+
6
+ position: relative;
7
+ }
8
+
9
+ html {
10
+ height: 100%;
11
+
12
+ box-sizing: border-box;
13
+
14
+ column-fill: auto;
15
+
16
+ overflow: hidden;
17
+ }
18
+ `;
19
+ const ONE_PAGE_THRESHOLD = 600;
20
+ export class ReflowableContent {
21
+ constructor(iframe) {
22
+ this.iframe = iframe;
23
+ this.document = this.iframe.contentDocument;
24
+ this.page = 0;
25
+ this.columns = 2;
26
+ this.htmlPadding = 20;
27
+ this.columnGap = 20;
28
+ this.resizeObserver = new ResizeObserver(() => {
29
+ if (this.columns === 2 && this.iframe.clientWidth <= ONE_PAGE_THRESHOLD) {
30
+ this.setColumnCount(1);
31
+ }
32
+ else if (this.columns === 1 && this.iframe.clientWidth > ONE_PAGE_THRESHOLD) {
33
+ this.setColumnCount(2);
34
+ }
35
+ else {
36
+ this.updatePageOffset();
37
+ }
38
+ if (this.page > this.totalPages - 1) {
39
+ this.goToPage(this.totalPages - 1);
40
+ }
41
+ });
42
+ }
43
+ get currentPage() {
44
+ return this.page;
45
+ }
46
+ get totalPages() {
47
+ const htmlElement = this.document.documentElement;
48
+ return Math.ceil(htmlElement.scrollWidth / htmlElement.offsetWidth);
49
+ }
50
+ attach() {
51
+ this.resizeObserver.observe(this.iframe);
52
+ }
53
+ detach() {
54
+ this.resizeObserver.disconnect();
55
+ }
56
+ prepareChapter() {
57
+ this.page = 0;
58
+ const style = this.document.createElement('style');
59
+ style.appendChild(this.document.createTextNode(DOCUMENT_CSS));
60
+ this.document.head.appendChild(style);
61
+ this.updateStyles();
62
+ }
63
+ setColumnCount(columns) {
64
+ this.columns = columns;
65
+ this.updateStyles();
66
+ this.updatePageOffset();
67
+ }
68
+ goToPage(page) {
69
+ this.page = page;
70
+ this.updatePageOffset();
71
+ }
72
+ ensureVisible(elem) {
73
+ const elemPage = this.currentPage +
74
+ Math.floor(elem.getBoundingClientRect().left / this.document.documentElement.getBoundingClientRect().width);
75
+ if (this.currentPage !== elemPage) {
76
+ this.goToPage(elemPage);
77
+ }
78
+ }
79
+ getFirstVisibleElement() {
80
+ const htmlRect = this.document.documentElement.getBoundingClientRect();
81
+ const left = htmlRect.left + this.offset;
82
+ const right = left + htmlRect.width;
83
+ const top = htmlRect.top;
84
+ const bottom = top + htmlRect.height;
85
+ const nodeIt = this.document.createNodeIterator(this.document.body, NodeFilter.SHOW_TEXT);
86
+ let textNode, res;
87
+ while ((textNode = nodeIt.nextNode())) {
88
+ const elem = textNode.parentElement;
89
+ if (!elem) {
90
+ continue;
91
+ }
92
+ const rect = elem.getBoundingClientRect();
93
+ if (left <= rect.left && right >= rect.right && top <= rect.top && bottom >= rect.bottom) {
94
+ if (!res || (res.rect.top > rect.top && res.rect.left > rect.left)) {
95
+ res = { rect, elem };
96
+ }
97
+ }
98
+ }
99
+ return res?.elem ?? null;
100
+ }
101
+ updatePageOffset() {
102
+ this.document.documentElement.style.left = `-${this.offset}px`;
103
+ }
104
+ get offset() {
105
+ const htmlWidth = this.document.documentElement.offsetWidth;
106
+ return (htmlWidth - this.htmlPadding * 2 + this.columnGap) * this.page;
107
+ }
108
+ updateStyles() {
109
+ const htmlElement = this.document.documentElement;
110
+ htmlElement.style.padding = `${this.htmlPadding}px`;
111
+ htmlElement.style.columns = `auto ${this.columns}`;
112
+ htmlElement.style.columnGap = `${this.columnGap}px`;
113
+ }
114
+ }
115
+ //# sourceMappingURL=reflowable-content.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reflowable-content.js","sourceRoot":"","sources":["../../lib/content-controller/reflowable-content.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ export interface ContentController {
2
+ currentPage: number;
3
+ totalPages: number;
4
+ attach(): void;
5
+ detach(): void;
6
+ prepareChapter(): void;
7
+ goToPage(page: number): void;
8
+ ensureVisible(elem: Element): void;
9
+ getFirstVisibleElement(): Element | null;
10
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=content-controller.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"content-controller.js","sourceRoot":"","sources":["../lib/content-controller.ts"],"names":[],"mappings":""}
@@ -0,0 +1,19 @@
1
+ export interface ContainerNode {
2
+ container: {
3
+ rootfiles: {
4
+ rootfile: RootfileNode[];
5
+ };
6
+ links?: {
7
+ link: LinkNode[];
8
+ };
9
+ };
10
+ }
11
+ export interface RootfileNode {
12
+ '@_full-path': string;
13
+ '@_media-type': string;
14
+ }
15
+ export interface LinkNode {
16
+ '@_href': string;
17
+ '@_media-type'?: string;
18
+ '@_rel': string;
19
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=container.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"container.js","sourceRoot":"","sources":["../../lib/epub-types/container.ts"],"names":[],"mappings":""}
@@ -0,0 +1,13 @@
1
+ import { MetadataNode } from './metadata';
2
+ export interface CollectionNode {
3
+ '@_dir'?: string;
4
+ '@_id'?: string;
5
+ '@_role': string;
6
+ '@_xml:lang'?: string;
7
+ metadata?: MetadataNode;
8
+ collection?: CollectionNode[];
9
+ link?: LinkNode[];
10
+ }
11
+ export interface LinkNode {
12
+ '@_href': string;
13
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=collection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"collection.js","sourceRoot":"","sources":["../../../lib/epub-types/package/collection.ts"],"names":[],"mappings":""}
@@ -0,0 +1,18 @@
1
+ import { CollectionNode } from './collection';
2
+ import { ManifestNode } from './manifest';
3
+ import { MetadataNode } from './metadata';
4
+ import { SpineNode } from './spine';
5
+ export interface PackageNode {
6
+ package: {
7
+ '@_dir'?: string;
8
+ '@_id'?: string;
9
+ '@_prefix'?: string;
10
+ '@_xml:lang'?: string;
11
+ '@_unique-identifier': string;
12
+ '@_version': string;
13
+ metadata: MetadataNode;
14
+ manifest: ManifestNode;
15
+ spine: SpineNode;
16
+ collection?: CollectionNode[];
17
+ };
18
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../lib/epub-types/package/index.ts"],"names":[],"mappings":""}
@@ -0,0 +1,12 @@
1
+ export interface ManifestNode {
2
+ '@_id'?: string;
3
+ item: ItemNode[];
4
+ }
5
+ export interface ItemNode {
6
+ '@_fallback'?: string;
7
+ '@_href': string;
8
+ '@_id': string;
9
+ '@_media-overlay'?: string;
10
+ '@_media-type': string;
11
+ '@_properties'?: string;
12
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=manifest.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manifest.js","sourceRoot":"","sources":["../../../lib/epub-types/package/manifest.ts"],"names":[],"mappings":""}
@@ -0,0 +1,44 @@
1
+ export interface MetadataNode {
2
+ 'dc:identifier': DCIdentifierNode[];
3
+ 'dc:title': DCTitle[];
4
+ 'dc:language': DCLanguage[];
5
+ 'dc:creator'?: DCCreator[];
6
+ meta?: MetaNode[];
7
+ link: LinkNode[];
8
+ }
9
+ export interface DCIdentifierNode {
10
+ '@_id'?: string;
11
+ '#text': string;
12
+ }
13
+ export interface DCTitle {
14
+ '@_dir'?: string;
15
+ '@_id'?: string;
16
+ '@_xml:lang'?: string;
17
+ '#text': string;
18
+ }
19
+ export interface DCLanguage {
20
+ '@_id'?: string;
21
+ '#text': string;
22
+ }
23
+ export interface DCCreator {
24
+ '@_id'?: string;
25
+ '#text': string;
26
+ }
27
+ export interface MetaNode {
28
+ '@_dir'?: string;
29
+ '@_id'?: string;
30
+ '@_property': string;
31
+ '@_refines'?: string;
32
+ '@_scheme'?: string;
33
+ '@_xml:lang'?: string;
34
+ '#text': string;
35
+ }
36
+ export interface LinkNode {
37
+ '@_href': string;
38
+ '@_hreflang'?: string;
39
+ '@_id'?: string;
40
+ '@_media-type'?: string;
41
+ '@_properties': string;
42
+ '@_refines'?: string;
43
+ '@_rel': string;
44
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=metadata.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metadata.js","sourceRoot":"","sources":["../../../lib/epub-types/package/metadata.ts"],"names":[],"mappings":""}
@@ -0,0 +1,11 @@
1
+ export interface SpineNode {
2
+ '@_id'?: string;
3
+ '@_page-progression-direction'?: string;
4
+ itemref: ItemRefNode[];
5
+ }
6
+ export interface ItemRefNode {
7
+ '@_id'?: string;
8
+ '@_idref': string;
9
+ '@_linear'?: 'yes' | 'no';
10
+ '@_properties'?: string;
11
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=spine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spine.js","sourceRoot":"","sources":["../../../lib/epub-types/package/spine.ts"],"names":[],"mappings":""}
@@ -0,0 +1,97 @@
1
+ import { OrderedXMLNode } from './xml';
2
+ export interface SmilNode {
3
+ smil: {
4
+ '@_version': string;
5
+ '@_id'?: string;
6
+ '@_epub:prefix'?: string;
7
+ head?: HeadNode;
8
+ body: BodyNode;
9
+ };
10
+ }
11
+ export interface HeadNode {
12
+ metadata?: Record<string, unknown[]>;
13
+ }
14
+ export interface BodyNode {
15
+ '@_epub:type'?: string;
16
+ '@_id'?: string;
17
+ '@_epub:textref'?: string;
18
+ seq?: SeqNode[];
19
+ par?: ParNode[];
20
+ }
21
+ export interface SeqNode {
22
+ '@_epub:type'?: string;
23
+ '@_id'?: string;
24
+ '@_epub:textref': string;
25
+ seq?: SeqNode[];
26
+ par?: ParNode[];
27
+ }
28
+ export interface ParNode {
29
+ '@_epub:type'?: string;
30
+ '@_id'?: string;
31
+ text: TextNode;
32
+ audio?: AudioNode;
33
+ }
34
+ export interface TextNode {
35
+ '@_id'?: string;
36
+ '@_src': string;
37
+ }
38
+ export type ClockValue = string;
39
+ export interface AudioNode {
40
+ '@_id'?: string;
41
+ '@_src': string;
42
+ '@_clipBegin'?: ClockValue;
43
+ '@_clipEnd'?: ClockValue;
44
+ }
45
+ export type OrderedSMIL = [OrderedSMILNode | OrderedXMLNode];
46
+ export interface OrderedSMILNode {
47
+ ':@': {
48
+ version: string;
49
+ id?: string;
50
+ 'epub:prefix'?: string;
51
+ };
52
+ smil: [OrderedHeadNode | OrderedBodyNode];
53
+ }
54
+ export interface OrderedHeadNode {
55
+ head: [{
56
+ metadata: [Record<string, unknown>];
57
+ }];
58
+ }
59
+ export interface OrderedBodyNode {
60
+ ':@': {
61
+ 'epub:type'?: string;
62
+ id?: string;
63
+ 'epub:textref'?: string;
64
+ };
65
+ body: [OrderedSeqNode | OrderedParNode];
66
+ }
67
+ export interface OrderedSeqNode {
68
+ ':@': {
69
+ 'epub:type'?: string;
70
+ id?: string;
71
+ 'epub:textref': string;
72
+ };
73
+ seq: [OrderedSeqNode | OrderedParNode];
74
+ }
75
+ export interface OrderedParNode {
76
+ ':@': {
77
+ 'epub:type'?: string;
78
+ id?: string;
79
+ };
80
+ par: [OrderedTextNode | OrderedAudioNode];
81
+ }
82
+ export interface OrderedTextNode {
83
+ ':@': {
84
+ id?: string;
85
+ src: string;
86
+ };
87
+ text: [];
88
+ }
89
+ export interface OrderedAudioNode {
90
+ ':@': {
91
+ id?: string;
92
+ src: string;
93
+ clipBegin?: ClockValue;
94
+ clipEnd?: ClockValue;
95
+ };
96
+ audio: [];
97
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=smil.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"smil.js","sourceRoot":"","sources":["../../lib/epub-types/smil.ts"],"names":[],"mappings":""}
@@ -0,0 +1,9 @@
1
+ export interface OrderedXMLNode {
2
+ ':@': {
3
+ version: string;
4
+ encoding: string;
5
+ };
6
+ '?xml': {
7
+ '#text': string;
8
+ }[];
9
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=xml.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"xml.js","sourceRoot":"","sources":["../../lib/epub-types/xml.ts"],"names":[],"mappings":""}
@@ -0,0 +1,6 @@
1
+ export { Book } from './book';
2
+ export * from './book-loaders';
3
+ export { ContentController } from './content-controller';
4
+ export { Reader } from './reader';
5
+ export { TableOfContent, TocEntry, PageList, PageEntry, Navigation } from './package-parser/nav-parser';
6
+ export { OverlayMetadata } from './package-parser/overlay-parser';
package/dist/index.js ADDED
@@ -0,0 +1,4 @@
1
+ export { Book } from './book';
2
+ export * from './book-loaders';
3
+ export { Reader } from './reader';
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../lib/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAA;AAC7B,cAAc,gBAAgB,CAAA;AAE9B,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAA"}
@@ -0,0 +1,32 @@
1
+ import { Reader, Book } from '.';
2
+ import { TextHighlighterPlugin } from './plugins/text-highlighter-plugin';
3
+ export declare class MediaOverlay {
4
+ private book;
5
+ private reader;
6
+ private highlighter;
7
+ private smilState?;
8
+ private overlayMetadata;
9
+ private audioPlayer;
10
+ private audioSrc?;
11
+ private currentAudioPar?;
12
+ private globalPositionChangedSubject;
13
+ events: {
14
+ onGlobalPositionChanged: import("rxjs").Observable<number>;
15
+ };
16
+ constructor(book: Book, reader: Reader, highlighter: TextHighlighterPlugin | null);
17
+ load(chapterId: string): void;
18
+ get playing(): boolean;
19
+ togglePlayback(): void;
20
+ goToTime(time: number): void;
21
+ get audioEvents(): {
22
+ onPlaybackStateChanged: import("rxjs").Observable<boolean>;
23
+ onPositionChanged: import("rxjs").Observable<number>;
24
+ onAudioEnded: import("rxjs").Observable<void>;
25
+ };
26
+ playAt(el: Element | null): void;
27
+ destroy(): void;
28
+ private getChapterData;
29
+ private onAudioPositionChanged;
30
+ private onAudioEnded;
31
+ private goTo;
32
+ }
@@ -0,0 +1,177 @@
1
+ import { SMIL } from './smil';
2
+ import AudioPlayer from './audio-player';
3
+ import { absoluteOrPrefixed, lastURISegment, parentURI } from './uri';
4
+ import { Subject } from 'rxjs';
5
+ import { getTextSrcInOrderedPar } from './smil/helper';
6
+ export class MediaOverlay {
7
+ constructor(book, reader, highlighter) {
8
+ this.book = book;
9
+ this.reader = reader;
10
+ this.highlighter = highlighter;
11
+ this.globalPositionChangedSubject = new Subject();
12
+ this.events = {
13
+ onGlobalPositionChanged: this.globalPositionChangedSubject.asObservable(),
14
+ };
15
+ this.audioPlayer = new AudioPlayer();
16
+ this.audioPlayer.events.onAudioEnded.subscribe(this.onAudioEnded.bind(this));
17
+ this.audioPlayer.events.onPositionChanged.subscribe(this.onAudioPositionChanged.bind(this));
18
+ this.overlayMetadata = book.overlayMetadata;
19
+ }
20
+ load(chapterId) {
21
+ const chapterData = this.getChapterData(chapterId);
22
+ if (!chapterData) {
23
+ this.smilState = null;
24
+ return;
25
+ }
26
+ const smilPath = this.book.packageParser.getManifestItemPath(chapterData.overlay);
27
+ this.book.loader.fetch(smilPath).subscribe((smilContent) => {
28
+ this.smilState = {
29
+ smil: new SMIL(smilContent),
30
+ smilPath,
31
+ chapterFilename: chapterData.chapterFile,
32
+ };
33
+ });
34
+ }
35
+ get playing() {
36
+ return this.audioPlayer.playing;
37
+ }
38
+ togglePlayback() {
39
+ if (!this.audioSrc) {
40
+ this.playAt(this.reader.firstElement);
41
+ }
42
+ else {
43
+ this.audioPlayer.togglePlayback();
44
+ }
45
+ }
46
+ goToTime(time) {
47
+ const duration = this.overlayMetadata?.durations.find(({ start, end }) => start <= time && time <= end);
48
+ if (!duration) {
49
+ console.warn(`No smil for time ${time}`);
50
+ return;
51
+ }
52
+ const { smilId } = duration;
53
+ const targetSmilPath = this.book.packageParser.getManifestItemPath(smilId);
54
+ const localTime = time - duration.start;
55
+ if (targetSmilPath && targetSmilPath !== this.smilState?.smilPath) {
56
+ this.book.loader.fetch(targetSmilPath).subscribe((smilContent) => {
57
+ const elem = new SMIL(smilContent).getElemForGlobalPosition(localTime);
58
+ if (!elem) {
59
+ console.warn(`No elem for time ${time} in smil ${targetSmilPath}`);
60
+ return;
61
+ }
62
+ const src = elem.par[0][':@'].src;
63
+ const [chapter, anchor] = src.split('#');
64
+ const item = this.book.packageParser.getManifestItem((i) => i['@_href'].endsWith(chapter));
65
+ this.reader.loadChapter(item['@_id'], anchor).subscribe();
66
+ });
67
+ }
68
+ else if (this.smilState) {
69
+ const elem = this.smilState.smil.getElemForGlobalPosition(localTime);
70
+ if (!elem) {
71
+ console.warn(`No element found for ${localTime}`);
72
+ return;
73
+ }
74
+ this.goTo(elem.audio[':@'].src, elem.start + localTime - elem.offset);
75
+ }
76
+ else {
77
+ console.warn(`SMIL not loaded`);
78
+ }
79
+ }
80
+ get audioEvents() {
81
+ return this.audioPlayer.events;
82
+ }
83
+ playAt(el) {
84
+ if (!this.smilState) {
85
+ return;
86
+ }
87
+ const audioData = this.smilState.smil.getAudioForElem(this.smilState.chapterFilename, el);
88
+ if (audioData) {
89
+ this.goTo(audioData.src, audioData.offset);
90
+ this.audioPlayer.play();
91
+ }
92
+ }
93
+ destroy() {
94
+ this.audioPlayer.destroy();
95
+ }
96
+ getChapterData(id) {
97
+ const chapterItem = this.book.packageParser.getManifestItem(id);
98
+ if (!chapterItem) {
99
+ console.warn(`No chapter with ${id}`);
100
+ return null;
101
+ }
102
+ const overlayId = chapterItem['@_media-overlay'];
103
+ if (!overlayId) {
104
+ return null;
105
+ }
106
+ const overlay = this.book.packageParser.getManifestItem(overlayId);
107
+ if (!overlay) {
108
+ console.warn(`No overlay found for item with id ${id} and overlay ref id ${overlayId}`);
109
+ return null;
110
+ }
111
+ const overlayMediaType = overlay['@_media-type'];
112
+ if (overlayMediaType !== 'application/smil+xml') {
113
+ console.warn(`Overlay with id ${overlayId} has incompatible media type "${overlayMediaType}"`);
114
+ return null;
115
+ }
116
+ return { overlay, chapterFile: lastURISegment(chapterItem['@_href']) };
117
+ }
118
+ onAudioPositionChanged(position) {
119
+ if (!this.smilState) {
120
+ console.warn(`Smil not available while audio position changed ${position}`);
121
+ return;
122
+ }
123
+ if (!this.audioSrc) {
124
+ console.warn(`No audio src while audio position changed ${position}`);
125
+ return;
126
+ }
127
+ const audioPar = this.smilState.smil.parForTime(this.audioSrc, position * 1000);
128
+ if (!audioPar) {
129
+ console.warn(`No element for position ${position} from src ${this.audioSrc}`);
130
+ return;
131
+ }
132
+ this.currentAudioPar = audioPar;
133
+ if (this.highlighter) {
134
+ const id = getTextSrcInOrderedPar(audioPar).split('#')[1];
135
+ if (id) {
136
+ const newElem = this.highlighter.highlightElement(id);
137
+ if (newElem) {
138
+ this.reader.goToElement(newElem);
139
+ }
140
+ }
141
+ }
142
+ const { smilPath } = this.smilState;
143
+ const duration = this.overlayMetadata?.durations.find((d) => this.book.packageParser.getManifestItemPath(d.smilId) === smilPath);
144
+ if (!duration) {
145
+ console.warn(`Duration for current smil not found (${smilPath})`);
146
+ return;
147
+ }
148
+ this.globalPositionChangedSubject.next(duration.start + audioPar.offset + position * 1000 - audioPar.start);
149
+ }
150
+ onAudioEnded() {
151
+ if (!this.smilState) {
152
+ console.warn('Smil not available when audio ended');
153
+ return;
154
+ }
155
+ const par = this.currentAudioPar;
156
+ const audioData = this.smilState.smil.getNextAudio(par ? getTextSrcInOrderedPar(par) : undefined);
157
+ if (audioData) {
158
+ this.goTo(audioData.src, audioData.offset);
159
+ }
160
+ else {
161
+ this.reader.nextPage();
162
+ }
163
+ }
164
+ goTo(src, offset) {
165
+ if (!this.smilState) {
166
+ return;
167
+ }
168
+ this.book.loader.fetch(absoluteOrPrefixed(src, parentURI(this.smilState.smilPath)), true).subscribe((blob) => {
169
+ this.audioSrc = src;
170
+ this.audioPlayer.seekTo({
171
+ offset,
172
+ src: blob,
173
+ });
174
+ });
175
+ }
176
+ }
177
+ //# sourceMappingURL=media-overlay.js.map