@readium/shared 2.3.1 → 2.4.0-alpha.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.
- package/README.MD +7 -8
- package/dist/ar-DyHX_uy2.js +7 -0
- package/dist/da-Dct0PS3E.js +7 -0
- package/dist/fr-C5HEel98.js +7 -0
- package/dist/index.js +4993 -1
- package/dist/index.umd.cjs +3 -0
- package/dist/it-DFOBoXGy.js +7 -0
- package/dist/pt_PT-Di3sVjze.js +7 -0
- package/dist/sv-BfzAFsVN.js +7 -0
- package/package.json +19 -26
- package/src/fetcher/HttpFetcher.ts +5 -5
- package/src/fetcher/Resource.ts +10 -5
- package/src/publication/Link.ts +6 -2
- package/src/publication/Locator.ts +3 -21
- package/src/publication/Manifest.ts +10 -10
- package/src/publication/Publication.ts +1 -2
- package/src/publication/accessibility/Localization.ts +14 -12
- package/src/publication/accessibility/SupportedLanguages.ts +1 -1
- package/src/publication/encryption/Properties.ts +15 -3
- package/src/publication/epub/Metadata.ts +12 -6
- package/src/publication/epub/Properties.ts +13 -3
- package/src/publication/epub/Publication.ts +39 -18
- package/src/publication/html/Locations.ts +101 -54
- package/src/publication/opds/Properties.ts +66 -21
- package/src/publication/opds/Publication.ts +9 -3
- package/src/publication/services/content/iterators/HTMLResourceContentIterator.ts +1 -3
- package/src/publication/services/timeline/Timeline.ts +59 -305
- package/src/publication/services/timeline/TimelineItem.ts +3 -3
- package/src/publication/services/timeline/index.ts +0 -12
- package/src/util/npt.ts +0 -19
- package/types/src/fetcher/HttpFetcher.d.ts +3 -3
- package/types/src/fetcher/Resource.d.ts +6 -2
- package/types/src/publication/encryption/Properties.d.ts +9 -2
- package/types/src/publication/epub/Metadata.d.ts +6 -3
- package/types/src/publication/epub/Properties.d.ts +10 -2
- package/types/src/publication/epub/Publication.d.ts +18 -7
- package/types/src/publication/html/Locations.d.ts +44 -15
- package/types/src/publication/opds/Properties.d.ts +36 -8
- package/types/src/publication/opds/Publication.d.ts +5 -2
- package/types/src/publication/services/timeline/Timeline.d.ts +12 -91
- package/types/src/publication/services/timeline/TimelineItem.d.ts +3 -3
- package/types/src/publication/services/timeline/index.d.ts +0 -6
- package/types/src/util/npt.d.ts +0 -10
- package/dist/_virtual/preload-helper.js +0 -1
- package/dist/fetcher/Fetcher.js +0 -1
- package/dist/fetcher/HttpFetcher.js +0 -1
- package/dist/fetcher/Resource.js +0 -1
- package/dist/locales/publication-metadata/ar.json.js +0 -1
- package/dist/locales/publication-metadata/da.json.js +0 -1
- package/dist/locales/publication-metadata/el.json.js +0 -1
- package/dist/locales/publication-metadata/en.json.js +0 -1
- package/dist/locales/publication-metadata/es.json.js +0 -1
- package/dist/locales/publication-metadata/et.json.js +0 -1
- package/dist/locales/publication-metadata/fi.json.js +0 -1
- package/dist/locales/publication-metadata/fr.json.js +0 -1
- package/dist/locales/publication-metadata/it.json.js +0 -1
- package/dist/locales/publication-metadata/pl.json.js +0 -1
- package/dist/locales/publication-metadata/pt_PT.json.js +0 -1
- package/dist/locales/publication-metadata/sv.json.js +0 -1
- package/dist/node_modules/.pnpm/css-selector-generator@3.8.0/node_modules/css-selector-generator/esm/constants.js +0 -1
- package/dist/node_modules/.pnpm/css-selector-generator@3.8.0/node_modules/css-selector-generator/esm/index.js +0 -1
- package/dist/node_modules/.pnpm/css-selector-generator@3.8.0/node_modules/css-selector-generator/esm/selector-attribute.js +0 -1
- package/dist/node_modules/.pnpm/css-selector-generator@3.8.0/node_modules/css-selector-generator/esm/selector-class.js +0 -1
- package/dist/node_modules/.pnpm/css-selector-generator@3.8.0/node_modules/css-selector-generator/esm/selector-fallback.js +0 -1
- package/dist/node_modules/.pnpm/css-selector-generator@3.8.0/node_modules/css-selector-generator/esm/selector-id.js +0 -1
- package/dist/node_modules/.pnpm/css-selector-generator@3.8.0/node_modules/css-selector-generator/esm/selector-nth-child.js +0 -1
- package/dist/node_modules/.pnpm/css-selector-generator@3.8.0/node_modules/css-selector-generator/esm/selector-nth-of-type.js +0 -1
- package/dist/node_modules/.pnpm/css-selector-generator@3.8.0/node_modules/css-selector-generator/esm/selector-tag.js +0 -1
- package/dist/node_modules/.pnpm/css-selector-generator@3.8.0/node_modules/css-selector-generator/esm/types.js +0 -1
- package/dist/node_modules/.pnpm/css-selector-generator@3.8.0/node_modules/css-selector-generator/esm/utilities-cartesian.js +0 -1
- package/dist/node_modules/.pnpm/css-selector-generator@3.8.0/node_modules/css-selector-generator/esm/utilities-data.js +0 -1
- package/dist/node_modules/.pnpm/css-selector-generator@3.8.0/node_modules/css-selector-generator/esm/utilities-dom.js +0 -1
- package/dist/node_modules/.pnpm/css-selector-generator@3.8.0/node_modules/css-selector-generator/esm/utilities-element-data.js +0 -1
- package/dist/node_modules/.pnpm/css-selector-generator@3.8.0/node_modules/css-selector-generator/esm/utilities-iselement.js +0 -1
- package/dist/node_modules/.pnpm/css-selector-generator@3.8.0/node_modules/css-selector-generator/esm/utilities-messages.js +0 -1
- package/dist/node_modules/.pnpm/css-selector-generator@3.8.0/node_modules/css-selector-generator/esm/utilities-options.js +0 -1
- package/dist/node_modules/.pnpm/css-selector-generator@3.8.0/node_modules/css-selector-generator/esm/utilities-powerset.js +0 -1
- package/dist/node_modules/.pnpm/css-selector-generator@3.8.0/node_modules/css-selector-generator/esm/utilities-selectors.js +0 -1
- package/dist/node_modules/.pnpm/css-selector-generator@3.8.0/node_modules/css-selector-generator/esm/utilities-typescript.js +0 -1
- package/dist/opds/Acquisition.js +0 -1
- package/dist/opds/Availability.js +0 -1
- package/dist/opds/Copies.js +0 -1
- package/dist/opds/Holds.js +0 -1
- package/dist/opds/Price.js +0 -1
- package/dist/publication/AltIdentifier.js +0 -1
- package/dist/publication/BelongsTo.js +0 -1
- package/dist/publication/Contributor.js +0 -1
- package/dist/publication/GuidedNavigation.js +0 -1
- package/dist/publication/Layout.js +0 -1
- package/dist/publication/Link.js +0 -1
- package/dist/publication/LocalizedString.js +0 -1
- package/dist/publication/Locator.js +0 -1
- package/dist/publication/LocatorCollection.js +0 -1
- package/dist/publication/Manifest.js +0 -1
- package/dist/publication/Metadata.js +0 -1
- package/dist/publication/Profiles.js +0 -1
- package/dist/publication/Properties.js +0 -1
- package/dist/publication/Publication.js +0 -1
- package/dist/publication/PublicationCollection.js +0 -1
- package/dist/publication/ReadingProgression.js +0 -1
- package/dist/publication/Subject.js +0 -1
- package/dist/publication/TDM.js +0 -1
- package/dist/publication/accessibility/Accessibility.js +0 -1
- package/dist/publication/accessibility/AccessibilityMetadataDisplayGuide.js +0 -1
- package/dist/publication/accessibility/Localization.js +0 -1
- package/dist/publication/accessibility/SupportedLanguages.js +0 -1
- package/dist/publication/encryption/Encryption.js +0 -1
- package/dist/publication/encryption/Properties.js +0 -1
- package/dist/publication/encryption/index.js +0 -1
- package/dist/publication/epub/MediaOverlay.js +0 -1
- package/dist/publication/epub/Metadata.js +0 -1
- package/dist/publication/epub/Properties.js +0 -1
- package/dist/publication/epub/Publication.js +0 -1
- package/dist/publication/epub/index.js +0 -1
- package/dist/publication/html/DomRange.js +0 -1
- package/dist/publication/html/DomRangePoint.js +0 -1
- package/dist/publication/html/Locations.js +0 -1
- package/dist/publication/html/index.js +0 -1
- package/dist/publication/opds/Properties.js +0 -1
- package/dist/publication/opds/Publication.js +0 -1
- package/dist/publication/opds/index.js +0 -1
- package/dist/publication/services/content/Content.js +0 -2
- package/dist/publication/services/content/ContentTokenizer.js +0 -1
- package/dist/publication/services/content/Iterator.js +0 -1
- package/dist/publication/services/content/element/attributes.js +0 -1
- package/dist/publication/services/content/element/element.js +0 -1
- package/dist/publication/services/content/element/text_role.js +0 -1
- package/dist/publication/services/content/iterators/HTMLResourceContentIterator.js +0 -1
- package/dist/publication/services/content/iterators/PDFTextContentIterator.js +0 -1
- package/dist/publication/services/content/iterators/PublicationContentIterator.js +0 -1
- package/dist/publication/services/content/iterators/helpers.js +0 -1
- package/dist/publication/services/timeline/Timeline.js +0 -1
- package/dist/publication/services/timeline/audio.js +0 -1
- package/dist/publication/services/timeline/html.js +0 -1
- package/dist/publication/services/timeline/index.js +0 -1
- package/dist/util/JSONParse.js +0 -1
- package/dist/util/URITemplate.js +0 -1
- package/dist/util/mediatype/MediaType.js +0 -1
- package/dist/util/npt.js +0 -1
- package/dist/util/tokenizer/TextTokenizer.js +0 -1
- package/dist/util/tokenizer/tokenize-english/abbreviations.js +0 -1
- package/dist/util/tokenizer/tokenize-english/index.js +0 -2
- package/dist/util/tokenizer/tokenize-english/utils.js +0 -1
- package/dist/util/tokenizer/tokenize-text/index.js +0 -1
- package/dist/util/tokenizer/tokenize-text/tokens.js +0 -1
- package/src/locales/publication-metadata/ar.json +0 -402
- package/src/locales/publication-metadata/brh.json +0 -1
- package/src/locales/publication-metadata/da.json +0 -310
- package/src/locales/publication-metadata/el.json +0 -310
- package/src/locales/publication-metadata/en.json +0 -310
- package/src/locales/publication-metadata/es.json +0 -333
- package/src/locales/publication-metadata/et.json +0 -310
- package/src/locales/publication-metadata/fi.json +0 -310
- package/src/locales/publication-metadata/fr.json +0 -333
- package/src/locales/publication-metadata/he.json +0 -9
- package/src/locales/publication-metadata/it.json +0 -333
- package/src/locales/publication-metadata/lt.json +0 -8
- package/src/locales/publication-metadata/pl.json +0 -333
- package/src/locales/publication-metadata/pt_PT.json +0 -329
- package/src/locales/publication-metadata/sv.json +0 -310
- package/src/locales/publication-metadata/tr.json +0 -51
- package/src/locales/publication-metadata/uk.json +0 -1
- package/src/publication/services/timeline/audio.ts +0 -31
- package/src/publication/services/timeline/html.ts +0 -5
- package/types/src/publication/services/timeline/audio.d.ts +0 -4
- package/types/src/publication/services/timeline/html.d.ts +0 -4
|
@@ -1,31 +1,11 @@
|
|
|
1
1
|
import { Link, Links } from "../../Link.ts";
|
|
2
2
|
import { Locator } from "../../Locator.ts";
|
|
3
|
-
import { getHtmlId, getTime } from "../../html/Locations.ts";
|
|
4
|
-
import { Profile } from "../../Profiles.ts";
|
|
5
|
-
import { formatNptTime, isNptStartOfResource, parseNptTime } from "../../../util/npt.ts";
|
|
6
3
|
import { TimelineItem } from "./TimelineItem.ts";
|
|
4
|
+
import { isNptStartOfResource, parseNptTime } from "../../../util/npt.ts";
|
|
7
5
|
|
|
8
|
-
|
|
6
|
+
interface PublicationLike {
|
|
9
7
|
toc?: Links;
|
|
10
8
|
readingOrder: Links;
|
|
11
|
-
metadata?: { conformsTo?: Profile[] };
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* A TOC entry, mirroring `publication.toc`'s authored hierarchy and
|
|
16
|
-
* contextualized with display-ready progression. When a publication has no
|
|
17
|
-
* `toc` at all, falls back to one flat entry per reading-order item.
|
|
18
|
-
*
|
|
19
|
-
* Exactly one of `position`/`timestamp` is populated, depending on the
|
|
20
|
-
* publication's profile.
|
|
21
|
-
*/
|
|
22
|
-
export interface ContextualizedTocEntry {
|
|
23
|
-
link: Link;
|
|
24
|
-
/** Display-ready label for non-audio profiles: a Positions List position for EPUB, a page number for PDF (e.g. "42"). */
|
|
25
|
-
position?: string;
|
|
26
|
-
/** Display-ready formatted time for audiobooks (e.g. "27:27"). */
|
|
27
|
-
timestamp?: string;
|
|
28
|
-
children?: ContextualizedTocEntry[];
|
|
29
9
|
}
|
|
30
10
|
|
|
31
11
|
/**
|
|
@@ -37,61 +17,32 @@ export interface ContextualizedTocEntry {
|
|
|
37
17
|
* 2. Populate flat children — all TOC fragment entries that reference the
|
|
38
18
|
* resource, collected depth-first in TOC declaration order.
|
|
39
19
|
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
* `locate()`) back to its entry in that hierarchy. TOC entries whose href
|
|
44
|
-
* does not match any reading order item are ignored.
|
|
20
|
+
* No TOC hierarchy is reconstructed; that requires role context and is not yet
|
|
21
|
+
* implemented. TOC entries whose href does not match any reading order item
|
|
22
|
+
* are ignored.
|
|
45
23
|
*
|
|
46
|
-
* The `depth` build option limits how many levels deep into the TOC tree
|
|
47
|
-
* title resolution
|
|
48
|
-
*
|
|
49
|
-
* `undefined` means no limit.
|
|
24
|
+
* The `depth` build option limits how many levels deep into the TOC tree both
|
|
25
|
+
* title resolution and child collection may look. Level 1 = top-level TOC
|
|
26
|
+
* entries; level 2 = their children; etc. `undefined` means no limit.
|
|
50
27
|
*/
|
|
51
28
|
export class Timeline {
|
|
52
29
|
private readonly _allItems: TimelineItem[];
|
|
53
30
|
private readonly linkMap: Map<TimelineItem, Link>;
|
|
54
|
-
private readonly _conformsTo: readonly Profile[];
|
|
55
|
-
private readonly tocLinks: Link[];
|
|
56
31
|
private _depth: number | undefined;
|
|
57
|
-
/**
|
|
58
|
-
* Depth used for `contextualizedToc` traversal. Tracks `_depth`, but is
|
|
59
|
-
* seeded independently from `Timeline.build()`'s `depth` option: unlike
|
|
60
|
-
* `_depth`, which only ever triggers `items`/`flat` re-trimming via the
|
|
61
|
-
* runtime `depth` setter, the TOC tree is walked fresh from `tocLinks`
|
|
62
|
-
* every time, so there's no equivalent "already baked in, don't reapply"
|
|
63
|
-
* hazard to avoid.
|
|
64
|
-
*/
|
|
65
|
-
private _tocDepth: number | undefined;
|
|
66
32
|
private _items: TimelineItem[] | undefined;
|
|
67
33
|
private _flat: TimelineItem[] | undefined;
|
|
68
|
-
private _toc: ContextualizedTocEntry[] | undefined;
|
|
69
|
-
private _linkToItem: Map<Link, TimelineItem> | undefined;
|
|
70
34
|
/** Populated when depth is set; maps cloned items from trimToDepth back to their Links. */
|
|
71
35
|
private _trimmedLinkMap: Map<TimelineItem, Link> = new Map();
|
|
72
36
|
|
|
73
|
-
constructor(
|
|
74
|
-
items: TimelineItem[],
|
|
75
|
-
linkMap: Map<TimelineItem, Link>,
|
|
76
|
-
conformsTo: readonly Profile[] = [],
|
|
77
|
-
tocLinks: Link[] = [],
|
|
78
|
-
tocDepth: number | undefined = undefined,
|
|
79
|
-
) {
|
|
37
|
+
constructor(items: TimelineItem[], linkMap: Map<TimelineItem, Link>) {
|
|
80
38
|
this._allItems = items;
|
|
81
39
|
this.linkMap = linkMap;
|
|
82
|
-
this._conformsTo = conformsTo;
|
|
83
|
-
this.tocLinks = tocLinks;
|
|
84
|
-
this._tocDepth = tocDepth;
|
|
85
40
|
}
|
|
86
41
|
|
|
87
|
-
static build(
|
|
88
|
-
publication: PublicationLike,
|
|
89
|
-
options: { depth?: number } = {},
|
|
90
|
-
): Timeline {
|
|
42
|
+
static build(publication: PublicationLike, options: { depth?: number } = {}): Timeline {
|
|
91
43
|
const tocLinks = publication.toc?.items ?? [];
|
|
92
44
|
const roLinks = publication.readingOrder.items;
|
|
93
45
|
const { depth } = options;
|
|
94
|
-
const conformsTo = publication.metadata?.conformsTo ?? [];
|
|
95
46
|
const linkMap = new Map<TimelineItem, Link>();
|
|
96
47
|
const items: TimelineItem[] = [];
|
|
97
48
|
|
|
@@ -101,7 +52,8 @@ export class Timeline {
|
|
|
101
52
|
|
|
102
53
|
const title =
|
|
103
54
|
ro.title ??
|
|
104
|
-
Timeline.findTitleInToc(tocLinks, bare, depth)
|
|
55
|
+
Timeline.findTitleInToc(tocLinks, bare, depth) ??
|
|
56
|
+
`Resource ${i + 1}`;
|
|
105
57
|
|
|
106
58
|
const tocChildren = Timeline.collectChildrenFromToc(tocLinks, bare, depth, 1, linkMap);
|
|
107
59
|
|
|
@@ -115,25 +67,7 @@ export class Timeline {
|
|
|
115
67
|
items.push(item);
|
|
116
68
|
}
|
|
117
69
|
|
|
118
|
-
return new Timeline(items, linkMap
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
/**
|
|
122
|
-
* Augments all items in the timeline by applying the mapper's returned patch.
|
|
123
|
-
* The mapper receives the item and its original manifest Link, and returns
|
|
124
|
-
* a partial TimelineItem — any fields it sets will overwrite the item's
|
|
125
|
-
* current value. Use this to populate `position`, `scroll`, `role`, or any
|
|
126
|
-
* future TimelineItem fields from format-specific data.
|
|
127
|
-
*/
|
|
128
|
-
augment(mapper: (item: TimelineItem, link: Link) => Partial<TimelineItem>): void {
|
|
129
|
-
for (const item of this.flatAll) {
|
|
130
|
-
const link = this.linkFor(item);
|
|
131
|
-
if (!link) continue;
|
|
132
|
-
const patch = mapper(item, link);
|
|
133
|
-
if (patch.position !== undefined) item.position = patch.position;
|
|
134
|
-
if (patch.scroll !== undefined) item.scroll = patch.scroll;
|
|
135
|
-
if (patch.role !== undefined) item.role = patch.role;
|
|
136
|
-
}
|
|
70
|
+
return new Timeline(items, linkMap);
|
|
137
71
|
}
|
|
138
72
|
|
|
139
73
|
/**
|
|
@@ -148,10 +82,8 @@ export class Timeline {
|
|
|
148
82
|
set depth(value: number | undefined) {
|
|
149
83
|
if (this._depth === value) return;
|
|
150
84
|
this._depth = value;
|
|
151
|
-
this._tocDepth = value;
|
|
152
85
|
this._items = undefined;
|
|
153
86
|
this._flat = undefined;
|
|
154
|
-
this._toc = undefined;
|
|
155
87
|
}
|
|
156
88
|
|
|
157
89
|
/** Top-level timeline items. Cached; invalidated when `depth` changes. */
|
|
@@ -169,63 +101,26 @@ export class Timeline {
|
|
|
169
101
|
|
|
170
102
|
locate(locator: Locator): TimelineItem | undefined {
|
|
171
103
|
const href = locator.href.split("#")[0];
|
|
172
|
-
const time =
|
|
173
|
-
|
|
174
|
-
|
|
104
|
+
const time = locator.locations?.time();
|
|
105
|
+
|
|
106
|
+
let match: TimelineItem | undefined;
|
|
175
107
|
|
|
176
|
-
// Audio: best-match on t= start time.
|
|
177
108
|
if (time !== undefined) {
|
|
178
109
|
let bestTime = -Infinity;
|
|
179
|
-
let match: TimelineItem | undefined;
|
|
180
110
|
for (const item of this.flat) {
|
|
181
|
-
if (!this.itemMatchesHref(item, href)) continue;
|
|
182
111
|
const t = this.itemStartTime(item, href);
|
|
183
112
|
if (t !== undefined && t <= time && t > bestTime) {
|
|
184
113
|
bestTime = t;
|
|
185
114
|
match = item;
|
|
186
115
|
}
|
|
187
116
|
}
|
|
188
|
-
if (match) return match;
|
|
189
117
|
}
|
|
190
118
|
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
const match = this.flat.find(item => {
|
|
194
|
-
if (!this.itemMatchesHref(item, href)) return false;
|
|
195
|
-
return item.references.some(ref => ref.split("#")[1] === htmlId);
|
|
196
|
-
});
|
|
197
|
-
if (match) return match;
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
// EPUB: best-match on scroll progression.
|
|
201
|
-
if (progression !== undefined) {
|
|
202
|
-
let bestScroll = -Infinity;
|
|
203
|
-
let match: TimelineItem | undefined;
|
|
204
|
-
for (const item of this.flat) {
|
|
205
|
-
if (!this.itemMatchesHref(item, href)) continue;
|
|
206
|
-
const s = this.itemScrollPosition(item);
|
|
207
|
-
if (s !== undefined && s <= progression && s > bestScroll) {
|
|
208
|
-
bestScroll = s;
|
|
209
|
-
match = item;
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
if (match) return match;
|
|
213
|
-
|
|
214
|
-
// No scroll data resolved anywhere in this resource yet: guess a
|
|
215
|
-
// child by evenly dividing the fraction across its children,
|
|
216
|
-
// rather than naming the whole resource.
|
|
217
|
-
const container = this.items.find(i => this.itemMatchesHref(i, href));
|
|
218
|
-
if (container?.children?.length && !container.children.some(c => c.scroll !== undefined)) {
|
|
219
|
-
const index = Math.min(
|
|
220
|
-
Math.floor(progression * container.children.length),
|
|
221
|
-
container.children.length - 1,
|
|
222
|
-
);
|
|
223
|
-
return container.children[index];
|
|
224
|
-
}
|
|
119
|
+
if (!match) {
|
|
120
|
+
match = this.flat.find(item => this.bareHrefFromItem(item) === href);
|
|
225
121
|
}
|
|
226
122
|
|
|
227
|
-
|
|
228
|
-
return this.flat.find(item => this.itemMatchesHref(item, href));
|
|
123
|
+
return match;
|
|
229
124
|
}
|
|
230
125
|
|
|
231
126
|
adjacentTo(item: TimelineItem): { previous: TimelineItem | undefined; next: TimelineItem | undefined } {
|
|
@@ -238,11 +133,35 @@ export class Timeline {
|
|
|
238
133
|
|
|
239
134
|
segmentsForHref(href: string): TimelineItem[] {
|
|
240
135
|
const bare = href.split("#")[0];
|
|
241
|
-
const item = this.items.find(i => this.
|
|
136
|
+
const item = this.items.find(i => this.bareHrefFromItem(i) === bare);
|
|
242
137
|
if (!item) return [];
|
|
243
138
|
return item.children?.length ? item.children : [item];
|
|
244
139
|
}
|
|
245
140
|
|
|
141
|
+
itemAtProgression(href: string, progression: number, duration?: number): TimelineItem | undefined {
|
|
142
|
+
const bare = href.split("#")[0];
|
|
143
|
+
const item = this.items.find(i => this.bareHrefFromItem(i) === bare);
|
|
144
|
+
if (!item) return undefined;
|
|
145
|
+
if (!item.children?.length) return item;
|
|
146
|
+
|
|
147
|
+
if (duration !== undefined) {
|
|
148
|
+
const time = progression * duration;
|
|
149
|
+
let match: TimelineItem = item;
|
|
150
|
+
let bestTime = -Infinity;
|
|
151
|
+
for (const child of item.children) {
|
|
152
|
+
const t = this.timeFromItem(child);
|
|
153
|
+
if (t !== undefined && t <= time && t > bestTime) {
|
|
154
|
+
bestTime = t;
|
|
155
|
+
match = child;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
return match;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
const index = Math.min(Math.floor(progression * item.children.length), item.children.length - 1);
|
|
162
|
+
return item.children[index];
|
|
163
|
+
}
|
|
164
|
+
|
|
246
165
|
ancestors(item: TimelineItem): TimelineItem[] {
|
|
247
166
|
return this.ancestorPath(this.items, item) ?? [];
|
|
248
167
|
}
|
|
@@ -251,52 +170,11 @@ export class Timeline {
|
|
|
251
170
|
return this.linkMap.get(item) ?? this._trimmedLinkMap.get(item);
|
|
252
171
|
}
|
|
253
172
|
|
|
254
|
-
/**
|
|
255
|
-
* The authored TOC, contextualized with display-ready progression. Mirrors
|
|
256
|
-
* `publication.toc`'s authored hierarchy (respecting `depth`), falling
|
|
257
|
-
* back to one flat entry per reading-order item when there's no toc at
|
|
258
|
-
* all. Cached; invalidated when `depth` changes.
|
|
259
|
-
*/
|
|
260
|
-
get contextualizedToc(): ContextualizedTocEntry[] {
|
|
261
|
-
if (!this._toc) {
|
|
262
|
-
this._toc = this.tocLinks.length > 0
|
|
263
|
-
? this.buildTocEntries(this.tocLinks, this._tocDepth, 1)
|
|
264
|
-
: this._allItems.map(item => this.entryFor(this.linkFor(item)!, item));
|
|
265
|
-
}
|
|
266
|
-
return this._toc;
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
/**
|
|
270
|
-
* Maps a `TimelineItem` (typically from `locate()`) to its `ContextualizedTocEntry`,
|
|
271
|
-
* trying three fallbacks in order:
|
|
272
|
-
* 1. A direct match on `current`'s own link.
|
|
273
|
-
* 2. The nearest preceding toc entry within the same resource.
|
|
274
|
-
* 3. When no toc entry references the resource at all, the nearest
|
|
275
|
-
* preceding resource's toc entry.
|
|
276
|
-
*/
|
|
277
|
-
tocEntryFor(current: TimelineItem): ContextualizedTocEntry | undefined {
|
|
278
|
-
const link = this.linkFor(current);
|
|
279
|
-
if (!link) return undefined;
|
|
280
|
-
|
|
281
|
-
const direct = this.findTocEntryByLink(this.contextualizedToc, link);
|
|
282
|
-
if (direct) return direct;
|
|
283
|
-
|
|
284
|
-
const nearest = this.nearestTocEntryForResource(link.href, current);
|
|
285
|
-
if (nearest) return nearest;
|
|
286
|
-
|
|
287
|
-
return this.previousResolvedTocEntry(link);
|
|
288
|
-
}
|
|
289
|
-
|
|
290
173
|
private get flat(): TimelineItem[] {
|
|
291
174
|
if (!this._flat) this._flat = this.flattenItems(this.items);
|
|
292
175
|
return this._flat;
|
|
293
176
|
}
|
|
294
177
|
|
|
295
|
-
/** All items flattened from _allItems, depth-independent — used by augment(). */
|
|
296
|
-
private get flatAll(): TimelineItem[] {
|
|
297
|
-
return this.flattenItems(this._allItems);
|
|
298
|
-
}
|
|
299
|
-
|
|
300
178
|
// -------------------------------------------------------------------------
|
|
301
179
|
// TOC title resolution
|
|
302
180
|
// -------------------------------------------------------------------------
|
|
@@ -337,17 +215,8 @@ export class Timeline {
|
|
|
337
215
|
const result: TimelineItem[] = [];
|
|
338
216
|
|
|
339
217
|
for (const link of tocLinks) {
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
// so they are associated with the current resource.
|
|
343
|
-
const matchesBare = linkBare === bare || linkBare === '';
|
|
344
|
-
if (matchesBare && link.title && !Timeline.isStartOfResource(link.href)) {
|
|
345
|
-
// Prepend the resource href when the link uses a fragment-only reference.
|
|
346
|
-
const ref = linkBare === '' ? bare + link.href : link.href;
|
|
347
|
-
const child: TimelineItem = {
|
|
348
|
-
title: link.title,
|
|
349
|
-
references: [ref],
|
|
350
|
-
};
|
|
218
|
+
if (Timeline.bareHref(link.href) === bare && link.title && !Timeline.isStartOfResource(link.href)) {
|
|
219
|
+
const child: TimelineItem = { title: link.title, references: [link.href] };
|
|
351
220
|
linkMap.set(child, link);
|
|
352
221
|
result.push(child);
|
|
353
222
|
}
|
|
@@ -381,8 +250,7 @@ export class Timeline {
|
|
|
381
250
|
const fragments: Link[] = [];
|
|
382
251
|
|
|
383
252
|
for (const link of tocLinks) {
|
|
384
|
-
|
|
385
|
-
if ((linkBare === bare || linkBare === '') && link.title) {
|
|
253
|
+
if (Timeline.bareHref(link.href) === bare && link.title) {
|
|
386
254
|
if (Timeline.isStartOfResource(link.href)) {
|
|
387
255
|
atStart.push(link);
|
|
388
256
|
} else {
|
|
@@ -414,120 +282,6 @@ export class Timeline {
|
|
|
414
282
|
return match !== null && isNptStartOfResource(match[1]);
|
|
415
283
|
}
|
|
416
284
|
|
|
417
|
-
// -------------------------------------------------------------------------
|
|
418
|
-
// Contextualized TOC
|
|
419
|
-
// -------------------------------------------------------------------------
|
|
420
|
-
|
|
421
|
-
private get linkToItem(): Map<Link, TimelineItem> {
|
|
422
|
-
if (!this._linkToItem) {
|
|
423
|
-
this._linkToItem = new Map();
|
|
424
|
-
for (const [item, link] of this.linkMap) this._linkToItem.set(link, item);
|
|
425
|
-
}
|
|
426
|
-
return this._linkToItem;
|
|
427
|
-
}
|
|
428
|
-
|
|
429
|
-
private buildTocEntries(links: Link[], maxDepth: number | undefined, currentDepth: number): ContextualizedTocEntry[] {
|
|
430
|
-
if (maxDepth !== undefined && currentDepth > maxDepth) return [];
|
|
431
|
-
return links.map(link => {
|
|
432
|
-
const item = this.linkToItem.get(link) ?? this.resourceStartItem(link.href);
|
|
433
|
-
const kids = link.children?.items?.length
|
|
434
|
-
? this.buildTocEntries(link.children.items, maxDepth, currentDepth + 1)
|
|
435
|
-
: [];
|
|
436
|
-
return { ...this.entryFor(link, item), children: kids.length > 0 ? kids : undefined };
|
|
437
|
-
});
|
|
438
|
-
}
|
|
439
|
-
|
|
440
|
-
/** All toc Links flattened, respecting the same depth limit as `buildTocEntries`. */
|
|
441
|
-
private tocLinksFlat(links: Link[], maxDepth: number | undefined, currentDepth: number): Link[] {
|
|
442
|
-
if (maxDepth !== undefined && currentDepth > maxDepth) return [];
|
|
443
|
-
const result: Link[] = [];
|
|
444
|
-
for (const link of links) {
|
|
445
|
-
result.push(link);
|
|
446
|
-
if (link.children?.items?.length) {
|
|
447
|
-
result.push(...this.tocLinksFlat(link.children.items, maxDepth, currentDepth + 1));
|
|
448
|
-
}
|
|
449
|
-
}
|
|
450
|
-
return result;
|
|
451
|
-
}
|
|
452
|
-
|
|
453
|
-
private entryFor(link: Link, item: TimelineItem | undefined): ContextualizedTocEntry {
|
|
454
|
-
const isAudio = this._conformsTo.includes(Profile.AUDIOBOOK);
|
|
455
|
-
return {
|
|
456
|
-
link,
|
|
457
|
-
position: !isAudio && item?.position !== undefined ? String(item.position) : undefined,
|
|
458
|
-
timestamp: isAudio && item?.position !== undefined ? formatNptTime(item.position) : undefined,
|
|
459
|
-
};
|
|
460
|
-
}
|
|
461
|
-
|
|
462
|
-
private resourceStartItem(href: string): TimelineItem | undefined {
|
|
463
|
-
const bare = Timeline.bareHref(href);
|
|
464
|
-
return this._allItems.find(i => this.itemMatchesHref(i, bare));
|
|
465
|
-
}
|
|
466
|
-
|
|
467
|
-
private findTocEntryByLink(entries: ContextualizedTocEntry[], link: Link): ContextualizedTocEntry | undefined {
|
|
468
|
-
for (const entry of entries) {
|
|
469
|
-
if (entry.link === link) return entry;
|
|
470
|
-
if (entry.children) {
|
|
471
|
-
const found = this.findTocEntryByLink(entry.children, link);
|
|
472
|
-
if (found) return found;
|
|
473
|
-
}
|
|
474
|
-
}
|
|
475
|
-
return undefined;
|
|
476
|
-
}
|
|
477
|
-
|
|
478
|
-
/**
|
|
479
|
-
* Tier-2 fallback for `tocEntryFor`: among the toc entries that reference
|
|
480
|
-
* `href`'s own resource (e.g. chapter markers within one audio file),
|
|
481
|
-
* return the nearest one at or before `current`'s position/scroll.
|
|
482
|
-
*/
|
|
483
|
-
private nearestTocEntryForResource(href: string, current: TimelineItem): ContextualizedTocEntry | undefined {
|
|
484
|
-
const bare = Timeline.bareHref(href);
|
|
485
|
-
// Re-walk with raw items (not the display-formatted TocEntry tree) so we can compare
|
|
486
|
-
// current.position/current.scroll directly against each candidate's source TimelineItem.
|
|
487
|
-
const candidates = this.tocLinksFlat(this.tocLinks, this._tocDepth, 1)
|
|
488
|
-
.filter(link => Timeline.bareHref(link.href) === bare)
|
|
489
|
-
.map(link => ({ link, item: this.linkToItem.get(link) ?? this.resourceStartItem(link.href) }));
|
|
490
|
-
if (candidates.length === 0) return undefined;
|
|
491
|
-
|
|
492
|
-
const isAudio = this._conformsTo.includes(Profile.AUDIOBOOK);
|
|
493
|
-
const currentValue = isAudio ? (current.position ?? 0) : (current.scroll ?? 0);
|
|
494
|
-
let best: { link: Link; item: TimelineItem | undefined } | undefined;
|
|
495
|
-
let bestValue = -Infinity;
|
|
496
|
-
for (const c of candidates) {
|
|
497
|
-
const v = isAudio ? (c.item?.position ?? 0) : (c.item?.scroll ?? 0);
|
|
498
|
-
if (v <= currentValue && v > bestValue) { bestValue = v; best = c; }
|
|
499
|
-
}
|
|
500
|
-
const chosen = best ?? candidates[0];
|
|
501
|
-
return this.findTocEntryByLink(this.contextualizedToc, chosen.link);
|
|
502
|
-
}
|
|
503
|
-
|
|
504
|
-
/**
|
|
505
|
-
* Tier-3 fallback for `tocEntryFor`: when no toc entry references
|
|
506
|
-
* `href`'s resource at all, walk backward through the reading order and
|
|
507
|
-
* return the nearest preceding resource's toc entry.
|
|
508
|
-
*/
|
|
509
|
-
private previousResolvedTocEntry(link: Link): ContextualizedTocEntry | undefined {
|
|
510
|
-
const index = this._allItems.findIndex(item => this.linkFor(item) === link);
|
|
511
|
-
if (index === -1) return undefined;
|
|
512
|
-
|
|
513
|
-
for (let i = index - 1; i >= 0; i--) {
|
|
514
|
-
const precedingLink = this.linkFor(this._allItems[i]);
|
|
515
|
-
if (!precedingLink) continue;
|
|
516
|
-
const precedingBare = Timeline.bareHref(precedingLink.href);
|
|
517
|
-
const { atStart, fragments } = Timeline.collectTocCandidates(this.tocLinks, precedingBare, this._tocDepth, 1);
|
|
518
|
-
// Exclude fragment-only entries (bareHref "") — collectTocCandidates
|
|
519
|
-
// treats them as matching any bare href for single-track audio, but
|
|
520
|
-
// here they must belong to this specific preceding resource.
|
|
521
|
-
const ownAtStart = atStart.filter(l => Timeline.bareHref(l.href) === precedingBare);
|
|
522
|
-
const ownFragments = fragments.filter(l => Timeline.bareHref(l.href) === precedingBare);
|
|
523
|
-
const chosen = ownAtStart[0] ?? (ownFragments.length > 0 ? ownFragments[ownFragments.length - 1] : undefined);
|
|
524
|
-
if (!chosen) continue;
|
|
525
|
-
const entry = this.findTocEntryByLink(this.contextualizedToc, chosen);
|
|
526
|
-
if (entry) return entry;
|
|
527
|
-
}
|
|
528
|
-
return undefined;
|
|
529
|
-
}
|
|
530
|
-
|
|
531
285
|
// -------------------------------------------------------------------------
|
|
532
286
|
// Shared utilities
|
|
533
287
|
// -------------------------------------------------------------------------
|
|
@@ -565,8 +319,7 @@ export class Timeline {
|
|
|
565
319
|
const hashIndex = ref.indexOf("#");
|
|
566
320
|
const refHref = hashIndex >= 0 ? ref.slice(0, hashIndex) : ref;
|
|
567
321
|
const refFragment = hashIndex >= 0 ? ref.slice(hashIndex + 1) : undefined;
|
|
568
|
-
|
|
569
|
-
const effectiveHref = refHref || href;
|
|
322
|
+
const effectiveHref = refHref || this.bareHrefFromItem(item);
|
|
570
323
|
if (effectiveHref !== href) continue;
|
|
571
324
|
if (!refFragment) return undefined;
|
|
572
325
|
const match = refFragment.match(/(?:^|&)t=([^&]+)/);
|
|
@@ -575,12 +328,17 @@ export class Timeline {
|
|
|
575
328
|
return undefined;
|
|
576
329
|
}
|
|
577
330
|
|
|
578
|
-
private
|
|
579
|
-
return item.references.
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
331
|
+
private bareHrefFromItem(item: TimelineItem): string {
|
|
332
|
+
return (item.references[0] ?? "").split("#")[0];
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
private timeFromItem(item: TimelineItem): number | undefined {
|
|
336
|
+
const ref = item.references[0];
|
|
337
|
+
if (!ref) return undefined;
|
|
338
|
+
const fragment = ref.split("#")[1];
|
|
339
|
+
if (!fragment) return undefined;
|
|
340
|
+
const match = fragment.match(/(?:^|&)t=([^&]+)/);
|
|
341
|
+
return match ? parseNptTime(match[1]) : undefined;
|
|
584
342
|
}
|
|
585
343
|
|
|
586
344
|
private ancestorPath(items: TimelineItem[], target: TimelineItem): TimelineItem[] | null {
|
|
@@ -594,10 +352,6 @@ export class Timeline {
|
|
|
594
352
|
return null;
|
|
595
353
|
}
|
|
596
354
|
|
|
597
|
-
private itemScrollPosition(item: TimelineItem): number | undefined {
|
|
598
|
-
return item.scroll;
|
|
599
|
-
}
|
|
600
|
-
|
|
601
355
|
private static bareHref(href: string): string {
|
|
602
356
|
return href.split("#")[0];
|
|
603
357
|
}
|
|
@@ -6,8 +6,8 @@
|
|
|
6
6
|
* show previous/next as chapter titles, group search results by chapter, etc.
|
|
7
7
|
*/
|
|
8
8
|
export interface TimelineItem {
|
|
9
|
-
/** Display title of this entry
|
|
10
|
-
title
|
|
9
|
+
/** Display title of this entry. */
|
|
10
|
+
title: string;
|
|
11
11
|
/**
|
|
12
12
|
* References as hrefs with optional fragments.
|
|
13
13
|
* e.g. ["track1.mp3#t=60"] for audio, ["chapter1.html"] for EPUB, ["#page=6"] for PDF.
|
|
@@ -15,7 +15,7 @@ export interface TimelineItem {
|
|
|
15
15
|
references: string[];
|
|
16
16
|
/** Structural roles of this entry, e.g. ["chapter"], ["part"]. */
|
|
17
17
|
role?: string[];
|
|
18
|
-
/**
|
|
18
|
+
/** Position number in the reading order context. */
|
|
19
19
|
position?: number;
|
|
20
20
|
/** Scroll progression within the resource (0 to 1), for entries that start mid-way in a resource. */
|
|
21
21
|
scroll?: number;
|
|
@@ -1,14 +1,2 @@
|
|
|
1
|
-
import { Profile } from "../../Profiles.ts";
|
|
2
|
-
import { PublicationLike, Timeline } from "./Timeline.ts";
|
|
3
|
-
import { buildAudioTimeline } from "./audio.ts";
|
|
4
|
-
import { buildHtmlTimeline } from "./html.ts";
|
|
5
|
-
|
|
6
1
|
export * from './Timeline.ts';
|
|
7
2
|
export * from './TimelineItem.ts';
|
|
8
|
-
export { buildHtmlTimeline } from './html.ts';
|
|
9
|
-
export { buildAudioTimeline } from './audio.ts';
|
|
10
|
-
|
|
11
|
-
export function buildTimeline(pub: PublicationLike, options?: { depth?: number }): Timeline {
|
|
12
|
-
const isAudio = pub.metadata?.conformsTo?.includes(Profile.AUDIOBOOK) ?? false;
|
|
13
|
-
return isAudio ? buildAudioTimeline(pub, options) : buildHtmlTimeline(pub, options);
|
|
14
|
-
}
|
package/src/util/npt.ts
CHANGED
|
@@ -49,22 +49,3 @@ export function isNptStartOfResource(raw: string): boolean {
|
|
|
49
49
|
const t = parseNptTime(raw);
|
|
50
50
|
return t !== undefined && t === 0;
|
|
51
51
|
}
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* Formats a duration in seconds as a human-readable string suitable for
|
|
55
|
-
* display in a Table of Contents or progress indicator.
|
|
56
|
-
*
|
|
57
|
-
* Outputs "H:MM:SS" when hours > 0, otherwise "M:SS".
|
|
58
|
-
* Minutes and seconds are always zero-padded to two digits.
|
|
59
|
-
*
|
|
60
|
-
* Examples: 0 → "0:00", 90 → "1:30", 3661 → "1:01:01"
|
|
61
|
-
*/
|
|
62
|
-
export function formatNptTime(seconds: number): string {
|
|
63
|
-
const totalSeconds = Math.floor(seconds);
|
|
64
|
-
const h = Math.floor(totalSeconds / 3600);
|
|
65
|
-
const m = Math.floor((totalSeconds % 3600) / 60);
|
|
66
|
-
const s = totalSeconds % 60;
|
|
67
|
-
const mm = String(m).padStart(2, "0");
|
|
68
|
-
const ss = String(s).padStart(2, "0");
|
|
69
|
-
return h > 0 ? `${h}:${mm}:${ss}` : `${m}:${ss}`;
|
|
70
|
-
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Link } from '../publication/Link.ts';
|
|
2
2
|
import { Fetcher } from './Fetcher.ts';
|
|
3
|
-
import { NumberRange, Resource } from './Resource.ts';
|
|
3
|
+
import { NumberRange, Resource, ResourceReadOptions } from './Resource.ts';
|
|
4
4
|
export type FetchImplementation = (input: RequestInfo | URL, init?: RequestInit | undefined) => Promise<Response>;
|
|
5
5
|
export declare class HttpFetcher implements Fetcher {
|
|
6
6
|
private readonly baseUrl?;
|
|
@@ -20,9 +20,9 @@ export declare class HttpResource implements Resource {
|
|
|
20
20
|
private headResponse;
|
|
21
21
|
close(): void;
|
|
22
22
|
link(): Promise<Link>;
|
|
23
|
-
read(range?: NumberRange): Promise<Uint8Array | undefined>;
|
|
23
|
+
read(range?: NumberRange, options?: ResourceReadOptions): Promise<Uint8Array | undefined>;
|
|
24
24
|
length(): Promise<number>;
|
|
25
25
|
readAsJSON(): Promise<unknown>;
|
|
26
26
|
readAsString(): Promise<string>;
|
|
27
|
-
readAsXML(): Promise<
|
|
27
|
+
readAsXML(): Promise<Document>;
|
|
28
28
|
}
|
|
@@ -4,12 +4,16 @@ export declare class NumberRange {
|
|
|
4
4
|
readonly endInclusive: number;
|
|
5
5
|
constructor(start: number, endInclusive: number);
|
|
6
6
|
}
|
|
7
|
+
export interface ResourceReadOptions {
|
|
8
|
+
/** Aborts the underlying request, e.g. when a prefetched resource is no longer needed */
|
|
9
|
+
signal?: AbortSignal;
|
|
10
|
+
}
|
|
7
11
|
export declare abstract class Resource {
|
|
8
12
|
abstract link(): Promise<Link>;
|
|
9
13
|
abstract length(): Promise<number | undefined>;
|
|
10
|
-
abstract read(range?: NumberRange): Promise<Uint8Array | undefined>;
|
|
14
|
+
abstract read(range?: NumberRange, options?: ResourceReadOptions): Promise<Uint8Array | undefined>;
|
|
11
15
|
readAsString(): Promise<string | undefined>;
|
|
12
16
|
readAsJSON(): Promise<unknown | undefined>;
|
|
13
|
-
readAsXML(): Promise<
|
|
17
|
+
readAsXML(): Promise<Document | undefined>;
|
|
14
18
|
abstract close(): void;
|
|
15
19
|
}
|
|
@@ -1,3 +1,10 @@
|
|
|
1
|
-
import { Properties } from '../Properties.ts';
|
|
2
1
|
import { Encryption } from './Encryption.ts';
|
|
3
|
-
|
|
2
|
+
declare module '../Properties' {
|
|
3
|
+
interface Properties {
|
|
4
|
+
/**
|
|
5
|
+
* Indicates that a resource is encrypted/obfuscated and provides relevant information for
|
|
6
|
+
* decryption.
|
|
7
|
+
*/
|
|
8
|
+
encryption: Encryption | undefined;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import { MediaOverlay } from "./MediaOverlay.ts";
|
|
2
|
+
declare module '../Metadata' {
|
|
3
|
+
interface Metadata {
|
|
4
|
+
getMediaOverlay(): MediaOverlay | undefined;
|
|
5
|
+
}
|
|
6
|
+
}
|
|
@@ -1,2 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
declare module '../Properties' {
|
|
2
|
+
interface Properties {
|
|
3
|
+
/**
|
|
4
|
+
* Identifies content contained in the linked resource, that cannot be strictly identified using a
|
|
5
|
+
* media type.
|
|
6
|
+
*/
|
|
7
|
+
getContains(): Set<string> | undefined;
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
export {};
|
|
@@ -1,8 +1,19 @@
|
|
|
1
1
|
import { Links } from '../Link.ts';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
2
|
+
declare module '../Publication' {
|
|
3
|
+
interface Publication {
|
|
4
|
+
/**
|
|
5
|
+
* Provides navigation to positions in the Publication content that correspond to the locations of
|
|
6
|
+
* page boundaries present in a print source being represented by this EPUB Publication.
|
|
7
|
+
*/
|
|
8
|
+
getPageList(): Links | undefined;
|
|
9
|
+
/**
|
|
10
|
+
* Identifies fundamental structural components of the publication in order to enable Reading
|
|
11
|
+
* Systems to provide the User efficient access to them.
|
|
12
|
+
*/
|
|
13
|
+
getLandmarks(): Links | undefined;
|
|
14
|
+
getListOfAudioClips(): Links | undefined;
|
|
15
|
+
getListOfIllustrations(): Links | undefined;
|
|
16
|
+
getListOfTables(): Links | undefined;
|
|
17
|
+
getListOfVideoClips(): Links | undefined;
|
|
18
|
+
}
|
|
19
|
+
}
|