@readium/shared 1.2.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.
- package/LICENSE +28 -0
- package/README.MD +27 -0
- package/dist/index.js +2536 -0
- package/dist/index.umd.cjs +2 -0
- package/package.json +73 -0
- package/src/fetcher/Fetcher.ts +37 -0
- package/src/fetcher/HttpFetcher.ts +122 -0
- package/src/fetcher/Resource.ts +37 -0
- package/src/fetcher/index.ts +2 -0
- package/src/index.ts +4 -0
- package/src/opds/Acquisition.ts +54 -0
- package/src/opds/Availability.ts +61 -0
- package/src/opds/Copies.ts +43 -0
- package/src/opds/Holds.ts +43 -0
- package/src/opds/Price.ts +51 -0
- package/src/opds/index.ts +5 -0
- package/src/publication/BelongsTo.ts +51 -0
- package/src/publication/Contributor.ts +129 -0
- package/src/publication/GuidedNavigation.ts +176 -0
- package/src/publication/Link.ts +332 -0
- package/src/publication/LocalizedString.ts +74 -0
- package/src/publication/Locator.ts +225 -0
- package/src/publication/LocatorCollection.ts +133 -0
- package/src/publication/Manifest.ts +256 -0
- package/src/publication/Metadata.ts +329 -0
- package/src/publication/Properties.ts +44 -0
- package/src/publication/Publication.ts +148 -0
- package/src/publication/PublicationCollection.ts +144 -0
- package/src/publication/ReadingProgression.ts +28 -0
- package/src/publication/Subject.ts +115 -0
- package/src/publication/encryption/Encryption.ts +68 -0
- package/src/publication/encryption/Properties.ts +20 -0
- package/src/publication/encryption/index.ts +2 -0
- package/src/publication/epub/EPUBLayout.ts +10 -0
- package/src/publication/epub/Presentation.ts +16 -0
- package/src/publication/epub/Properties.ts +28 -0
- package/src/publication/epub/Publication.ts +51 -0
- package/src/publication/epub/index.ts +4 -0
- package/src/publication/html/DomRange.ts +63 -0
- package/src/publication/html/DomRangePoint.ts +64 -0
- package/src/publication/html/Locations.ts +129 -0
- package/src/publication/html/index.ts +3 -0
- package/src/publication/index.ts +19 -0
- package/src/publication/opds/Properties.ts +84 -0
- package/src/publication/opds/Publication.ts +14 -0
- package/src/publication/opds/index.ts +2 -0
- package/src/publication/presentation/Metadata.ts +19 -0
- package/src/publication/presentation/Presentation.ts +155 -0
- package/src/publication/presentation/Properties.ts +70 -0
- package/src/publication/presentation/index.ts +3 -0
- package/src/publication/services/content/Content.ts +36 -0
- package/src/publication/services/content/ContentTokenizer.ts +62 -0
- package/src/publication/services/content/Iterator.ts +46 -0
- package/src/publication/services/content/element/attributes.ts +44 -0
- package/src/publication/services/content/element/element.ts +118 -0
- package/src/publication/services/content/element/index.ts +3 -0
- package/src/publication/services/content/element/text_role.ts +60 -0
- package/src/publication/services/content/index.ts +5 -0
- package/src/publication/services/content/iterators/HTMLResourceContentIterator.ts +571 -0
- package/src/publication/services/content/iterators/PDFTextContentIterator.ts +184 -0
- package/src/publication/services/content/iterators/PublicationContentIterator.ts +144 -0
- package/src/publication/services/content/iterators/helpers.ts +146 -0
- package/src/publication/services/content/iterators/index.ts +3 -0
- package/src/publication/services/index.ts +1 -0
- package/src/util/JSONParse.ts +31 -0
- package/src/util/Language.ts +5 -0
- package/src/util/URITemplate.ts +83 -0
- package/src/util/index.ts +5 -0
- package/src/util/mediatype/MediaType.ts +563 -0
- package/src/util/mediatype/index.ts +1 -0
- package/src/util/tokenizer/TextTokenizer.ts +126 -0
- package/src/util/tokenizer/Tokenizer.ts +8 -0
- package/src/util/tokenizer/index.ts +2 -0
- package/src/util/tokenizer/tokenize-english/README.md +7 -0
- package/src/util/tokenizer/tokenize-english/abbreviations.js +52 -0
- package/src/util/tokenizer/tokenize-english/index.d.ts +3 -0
- package/src/util/tokenizer/tokenize-english/index.js +243 -0
- package/src/util/tokenizer/tokenize-english/utils.js +16 -0
- package/src/util/tokenizer/tokenize-text/README.MD +6 -0
- package/src/util/tokenizer/tokenize-text/index.d.ts +52 -0
- package/src/util/tokenizer/tokenize-text/index.js +256 -0
- package/src/util/tokenizer/tokenize-text/tokens.js +100 -0
- package/types/src/fetcher/Fetcher.d.ts +27 -0
- package/types/src/fetcher/HttpFetcher.d.ts +28 -0
- package/types/src/fetcher/Resource.d.ts +15 -0
- package/types/src/fetcher/index.d.ts +2 -0
- package/types/src/index.d.ts +4 -0
- package/types/src/opds/Acquisition.d.ts +26 -0
- package/types/src/opds/Availability.d.ts +32 -0
- package/types/src/opds/Copies.d.ts +22 -0
- package/types/src/opds/Holds.d.ts +22 -0
- package/types/src/opds/Price.d.ts +29 -0
- package/types/src/opds/index.d.ts +5 -0
- package/types/src/publication/BelongsTo.d.ts +23 -0
- package/types/src/publication/Contributor.d.ts +60 -0
- package/types/src/publication/GuidedNavigation.d.ts +70 -0
- package/types/src/publication/Link.d.ts +128 -0
- package/types/src/publication/LocalizedString.d.ts +48 -0
- package/types/src/publication/Locator.d.ts +101 -0
- package/types/src/publication/LocatorCollection.d.ts +54 -0
- package/types/src/publication/Manifest.d.ts +59 -0
- package/types/src/publication/Metadata.d.ts +101 -0
- package/types/src/publication/Properties.d.ts +28 -0
- package/types/src/publication/Publication.d.ts +53 -0
- package/types/src/publication/PublicationCollection.d.ts +34 -0
- package/types/src/publication/ReadingProgression.d.ts +9 -0
- package/types/src/publication/Subject.d.ts +56 -0
- package/types/src/publication/encryption/Encryption.d.ts +33 -0
- package/types/src/publication/encryption/Properties.d.ts +10 -0
- package/types/src/publication/encryption/index.d.ts +2 -0
- package/types/src/publication/epub/EPUBLayout.d.ts +5 -0
- package/types/src/publication/epub/Presentation.d.ts +7 -0
- package/types/src/publication/epub/Properties.d.ts +14 -0
- package/types/src/publication/epub/Publication.d.ts +19 -0
- package/types/src/publication/epub/index.d.ts +4 -0
- package/types/src/publication/html/DomRange.d.ts +40 -0
- package/types/src/publication/html/DomRangePoint.d.ts +36 -0
- package/types/src/publication/html/Locations.d.ts +45 -0
- package/types/src/publication/html/index.d.ts +3 -0
- package/types/src/publication/index.d.ts +19 -0
- package/types/src/publication/opds/Properties.d.ts +38 -0
- package/types/src/publication/opds/Publication.d.ts +6 -0
- package/types/src/publication/opds/index.d.ts +2 -0
- package/types/src/publication/presentation/Metadata.d.ts +6 -0
- package/types/src/publication/presentation/Presentation.d.ts +95 -0
- package/types/src/publication/presentation/Properties.d.ts +32 -0
- package/types/src/publication/presentation/index.d.ts +3 -0
- package/types/src/publication/services/content/Content.d.ts +20 -0
- package/types/src/publication/services/content/ContentTokenizer.d.ts +19 -0
- package/types/src/publication/services/content/Iterator.d.ts +38 -0
- package/types/src/publication/services/content/element/attributes.d.ts +31 -0
- package/types/src/publication/services/content/element/element.d.ts +107 -0
- package/types/src/publication/services/content/element/index.d.ts +3 -0
- package/types/src/publication/services/content/element/text_role.d.ts +53 -0
- package/types/src/publication/services/content/index.d.ts +5 -0
- package/types/src/publication/services/content/iterators/HTMLResourceContentIterator.d.ts +30 -0
- package/types/src/publication/services/content/iterators/PDFTextContentIterator.d.ts +60 -0
- package/types/src/publication/services/content/iterators/PublicationContentIterator.d.ts +59 -0
- package/types/src/publication/services/content/iterators/helpers.d.ts +10 -0
- package/types/src/publication/services/content/iterators/index.d.ts +3 -0
- package/types/src/publication/services/index.d.ts +1 -0
- package/types/src/util/JSONParse.d.ts +11 -0
- package/types/src/util/Language.d.ts +1 -0
- package/types/src/util/URITemplate.d.ts +24 -0
- package/types/src/util/index.d.ts +5 -0
- package/types/src/util/mediatype/MediaType.d.ts +148 -0
- package/types/src/util/mediatype/index.d.ts +1 -0
- package/types/src/util/tokenizer/TextTokenizer.d.ts +39 -0
- package/types/src/util/tokenizer/Tokenizer.d.ts +6 -0
- package/types/src/util/tokenizer/index.d.ts +2 -0
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { Copies, Acquisition, Holds, Price, Availability } from '../../opds';
|
|
2
|
+
import { positiveNumberfromJSON } from '../../util/JSONParse';
|
|
3
|
+
import { Link } from '../Link';
|
|
4
|
+
import { Properties } from '../Properties';
|
|
5
|
+
|
|
6
|
+
// OPDS extensions for link [Properties].
|
|
7
|
+
// https://drafts.opds.io/schema/properties.schema.json
|
|
8
|
+
|
|
9
|
+
declare module '../Properties' {
|
|
10
|
+
export interface Properties {
|
|
11
|
+
/**
|
|
12
|
+
* Provides a hint about the expected number of items returned.
|
|
13
|
+
*/
|
|
14
|
+
getNumberOfItems(): number | undefined;
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* The price of a publication is tied to its acquisition link.
|
|
18
|
+
*/
|
|
19
|
+
getPrice(): Price | undefined;
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Indirect acquisition provides a hint for the expected media type that will be acquired after
|
|
23
|
+
* additional steps.
|
|
24
|
+
*/
|
|
25
|
+
getIndirectAcquisitions(): Array<Acquisition> | undefined;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Library-specific features when a specific book is unavailable but provides a hold list.
|
|
29
|
+
*/
|
|
30
|
+
getHolds(): Holds | undefined;
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Library-specific feature that contains information about the copies that a library has acquired.
|
|
34
|
+
*/
|
|
35
|
+
getCopies(): Copies | undefined;
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Indicated the availability of a given resource.
|
|
39
|
+
*/
|
|
40
|
+
getAvailability(): Availability | undefined;
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Indicates that the linked resource supports authentication with the associated Authentication
|
|
44
|
+
* Document.
|
|
45
|
+
*
|
|
46
|
+
* See https://drafts.opds.io/authentication-for-opds-1.0.html
|
|
47
|
+
*/
|
|
48
|
+
getAuthenticate(): Link | undefined;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
Properties.prototype.getNumberOfItems = function(): number | undefined {
|
|
53
|
+
return positiveNumberfromJSON(this.otherProperties['numberOfItems']);
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
Properties.prototype.getPrice = function(): Price | undefined {
|
|
57
|
+
return Price.deserialize(this.otherProperties['price']);
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
Properties.prototype.getIndirectAcquisitions = function():
|
|
61
|
+
| Array<Acquisition>
|
|
62
|
+
| undefined {
|
|
63
|
+
const json = this.otherProperties['indirectAcquisition'];
|
|
64
|
+
if (!(json && json instanceof Array)) return;
|
|
65
|
+
return json
|
|
66
|
+
.map<Acquisition>(item => Acquisition.deserialize(item) as Acquisition)
|
|
67
|
+
.filter(x => x !== undefined);
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
Properties.prototype.getHolds = function(): Holds | undefined {
|
|
71
|
+
return Holds.deserialize(this.otherProperties['holds']);
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
Properties.prototype.getCopies = function(): Copies | undefined {
|
|
75
|
+
return Copies.deserialize(this.otherProperties['copies']);
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
Properties.prototype.getAvailability = function(): Availability | undefined {
|
|
79
|
+
return Availability.deserialize(this.otherProperties['availability']);
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
Properties.prototype.getAuthenticate = function(): Link | undefined {
|
|
83
|
+
return Link.deserialize(this.otherProperties['authenticate']);
|
|
84
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Links } from '../Link';
|
|
2
|
+
import { Publication } from '../Publication';
|
|
3
|
+
|
|
4
|
+
// OPDS extensions for [Publication]
|
|
5
|
+
|
|
6
|
+
declare module '../Publication' {
|
|
7
|
+
export interface Publication {
|
|
8
|
+
getImages(): Links | undefined;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
Publication.prototype.getImages = function(): Links | undefined {
|
|
13
|
+
return this.linksWithRole('images');
|
|
14
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { Metadata } from '../Metadata';
|
|
2
|
+
import { Presentation } from './Presentation';
|
|
3
|
+
|
|
4
|
+
// Presentation extensions for [Metadata]
|
|
5
|
+
|
|
6
|
+
declare module '../Metadata' {
|
|
7
|
+
export interface Metadata {
|
|
8
|
+
getPresentation(): Presentation | undefined;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
Metadata.prototype.getPresentation = function(): Presentation | undefined {
|
|
13
|
+
const presentation =
|
|
14
|
+
this.otherMetadata?.['presentation'] || this.otherMetadata?.['rendition'];
|
|
15
|
+
|
|
16
|
+
if (!presentation) return;
|
|
17
|
+
|
|
18
|
+
return Presentation.deserialize(presentation);
|
|
19
|
+
};
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
/* Copyright 2021 Readium Foundation. All rights reserved.
|
|
2
|
+
* Use of this source code is governed by a BSD-style license,
|
|
3
|
+
* available in the LICENSE file present in the Github repository of the project.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { EPUBLayout } from '../epub/EPUBLayout';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Suggested orientation for the device when displaying the linked resource.
|
|
10
|
+
*/
|
|
11
|
+
export enum Orientation {
|
|
12
|
+
auto = 'auto',
|
|
13
|
+
landscape = 'landscape',
|
|
14
|
+
portrait = 'portrait',
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Suggested method for handling overflow while displaying the linked resource.
|
|
19
|
+
*/
|
|
20
|
+
export enum Overflow {
|
|
21
|
+
auto = 'auto',
|
|
22
|
+
clipped = 'clipped',
|
|
23
|
+
paginated = 'paginated',
|
|
24
|
+
scrolled = 'scrolled',
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Indicates how the linked resource should be displayed in a reading environment that displays
|
|
29
|
+
* synthetic spreads.
|
|
30
|
+
*/
|
|
31
|
+
export enum Page {
|
|
32
|
+
left = 'left',
|
|
33
|
+
right = 'right',
|
|
34
|
+
center = 'center',
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Indicates the condition to be met for the linked resource to be rendered within a synthetic
|
|
39
|
+
* spread.
|
|
40
|
+
*/
|
|
41
|
+
export enum Spread {
|
|
42
|
+
auto = 'auto',
|
|
43
|
+
both = 'both',
|
|
44
|
+
none = 'none',
|
|
45
|
+
landscape = 'landscape',
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Suggested method for constraining a resource inside the viewport.
|
|
50
|
+
*/
|
|
51
|
+
export enum Fit {
|
|
52
|
+
contain = 'contain',
|
|
53
|
+
cover = 'cover',
|
|
54
|
+
width = 'width',
|
|
55
|
+
height = 'height',
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// export interface IPresentationMetadata {
|
|
59
|
+
// clipped?: boolean;
|
|
60
|
+
// continuous?: boolean;
|
|
61
|
+
// fit?: Fit;
|
|
62
|
+
// orientation?: Orientation;
|
|
63
|
+
// overflow?: Overflow;
|
|
64
|
+
// spread?: Spread;
|
|
65
|
+
// layout?: EpubLayout;
|
|
66
|
+
// }
|
|
67
|
+
|
|
68
|
+
/** The Presentation Hints extension defines a number of hints for User Agents about the way content
|
|
69
|
+
* should be presented to the user.
|
|
70
|
+
*
|
|
71
|
+
* https://readium.org/webpub-manifest/extensions/presentation.html
|
|
72
|
+
* https://readium.org/webpub-manifest/schema/extensions/presentation/metadata.schema.json
|
|
73
|
+
*
|
|
74
|
+
* These properties can be undefined to avoid having default values when it doesn't make sense for a
|
|
75
|
+
* given `Publication`. If a navigator needs a default value when not specified,
|
|
76
|
+
* `Presentation.defaultX` and `Presentation.X.default` can be used.
|
|
77
|
+
*/
|
|
78
|
+
export class Presentation {
|
|
79
|
+
/** Specifies whether or not the parts of a linked resource that flow out of the viewport are clipped */
|
|
80
|
+
public clipped?: boolean;
|
|
81
|
+
|
|
82
|
+
/** Suggested method for constraining a resource inside the viewport. */
|
|
83
|
+
public fit?: Fit;
|
|
84
|
+
|
|
85
|
+
/** Suggested orientation for the device when displaying the linked resource. */
|
|
86
|
+
public orientation?: Orientation;
|
|
87
|
+
|
|
88
|
+
/** Indicates the condition to be met for the linked resource to be rendered
|
|
89
|
+
* within a synthetic spread
|
|
90
|
+
*/
|
|
91
|
+
public spread?: Spread;
|
|
92
|
+
|
|
93
|
+
/** Hint about the nature of the layout for the linked resources (EPUB extension). */
|
|
94
|
+
public layout?: EPUBLayout;
|
|
95
|
+
|
|
96
|
+
/** Indicates how the progression between resources from the [readingOrder] should be handled */
|
|
97
|
+
public continuous?: boolean;
|
|
98
|
+
|
|
99
|
+
/** Indicates if the overflow of linked resources from the `readingOrder` or `resources` should
|
|
100
|
+
* be handled using dynamic pagination or scrolling.
|
|
101
|
+
*/
|
|
102
|
+
public overflow?: Overflow;
|
|
103
|
+
|
|
104
|
+
/** Creates a [Presentation]. */
|
|
105
|
+
constructor(values: {
|
|
106
|
+
clipped?: boolean;
|
|
107
|
+
continuous?: boolean;
|
|
108
|
+
fit?: Fit;
|
|
109
|
+
orientation?: Orientation;
|
|
110
|
+
overflow?: Overflow;
|
|
111
|
+
spread?: Spread;
|
|
112
|
+
layout?: EPUBLayout;
|
|
113
|
+
}) {
|
|
114
|
+
this.clipped = values.clipped;
|
|
115
|
+
this.fit = values.fit;
|
|
116
|
+
this.orientation = values.orientation;
|
|
117
|
+
this.spread = values.spread;
|
|
118
|
+
this.layout = values.layout;
|
|
119
|
+
this.continuous = values.continuous;
|
|
120
|
+
this.overflow = values.overflow;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Parses a [Presentation] from its RWPM JSON representation.
|
|
125
|
+
*
|
|
126
|
+
*/
|
|
127
|
+
public static deserialize(json: any): Presentation | undefined {
|
|
128
|
+
if (!json) return;
|
|
129
|
+
|
|
130
|
+
return new Presentation({
|
|
131
|
+
clipped: json.clipped,
|
|
132
|
+
continuous: json.continuous,
|
|
133
|
+
fit: json.fit,
|
|
134
|
+
orientation: json.orientation,
|
|
135
|
+
overflow: json.overflow,
|
|
136
|
+
spread: json.spread,
|
|
137
|
+
layout: json.layout,
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Serializes a [Presentation] to its RWPM JSON representation.
|
|
143
|
+
*/
|
|
144
|
+
public serialize(): any {
|
|
145
|
+
const json: any = {};
|
|
146
|
+
if (this.clipped !== undefined) json.clipped = this.clipped;
|
|
147
|
+
if (this.continuous !== undefined) json.continuous = this.continuous;
|
|
148
|
+
if (this.fit !== undefined) json.fit = this.fit;
|
|
149
|
+
if (this.orientation !== undefined) json.orientation = this.orientation;
|
|
150
|
+
if (this.overflow !== undefined) json.overflow = this.overflow;
|
|
151
|
+
if (this.spread !== undefined) json.spread = this.spread;
|
|
152
|
+
if (this.layout !== undefined) json.layout = this.layout;
|
|
153
|
+
return json;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/* Copyright 2021 Readium Foundation. All rights reserved.
|
|
2
|
+
* Use of this source code is governed by a BSD-style license,
|
|
3
|
+
* available in the LICENSE file present in the Github repository of the project.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
// Presentation extensions for link [Properties]
|
|
7
|
+
|
|
8
|
+
import { Properties } from '../Properties';
|
|
9
|
+
import { Fit, Orientation, Overflow, Page, Spread } from './Presentation';
|
|
10
|
+
|
|
11
|
+
declare module '../Properties' {
|
|
12
|
+
export interface Properties {
|
|
13
|
+
/**
|
|
14
|
+
* Specifies whether or not the parts of a linked resource that flow out of the viewport are
|
|
15
|
+
* clipped.
|
|
16
|
+
*/
|
|
17
|
+
getClipped(): boolean | undefined;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Suggested method for constraining a resource inside the viewport.
|
|
21
|
+
*/
|
|
22
|
+
getFit(): Fit | undefined;
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Suggested orientation for the device when displaying the linked resource.
|
|
26
|
+
*/
|
|
27
|
+
getOrientation(): Orientation | undefined;
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Suggested method for handling overflow while displaying the linked resource.
|
|
31
|
+
*/
|
|
32
|
+
getOverflow(): Overflow | undefined;
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Indicates how the linked resource should be displayed in a reading environment that displays
|
|
36
|
+
* synthetic spreads.
|
|
37
|
+
*/
|
|
38
|
+
getPage(): Page | undefined;
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Indicates the condition to be met for the linked resource to be rendered within a synthetic
|
|
42
|
+
* spread.
|
|
43
|
+
*/
|
|
44
|
+
getSpread(): Spread | undefined;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
Properties.prototype.getClipped = function(): boolean | undefined {
|
|
49
|
+
return this.otherProperties['clipped'];
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
Properties.prototype.getFit = function(): Fit | undefined {
|
|
53
|
+
return this.otherProperties['fit'];
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
Properties.prototype.getOrientation = function(): Orientation | undefined {
|
|
57
|
+
return this.otherProperties['orientation'];
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
Properties.prototype.getOverflow = function(): Overflow | undefined {
|
|
61
|
+
return this.otherProperties['overflow'];
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
Properties.prototype.getPage = function(): Page | undefined {
|
|
65
|
+
return this.otherProperties['page'] || undefined;
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
Properties.prototype.getSpread = function(): Spread | undefined {
|
|
69
|
+
return this.otherProperties['spread'] || undefined;
|
|
70
|
+
};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { Iterator } from "./Iterator";
|
|
2
|
+
import { ContentElement, TextualElement } from "./element";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Provides an iterable list of content [Element]s.
|
|
6
|
+
*/
|
|
7
|
+
export abstract class Content {
|
|
8
|
+
/**
|
|
9
|
+
* Extracts the full raw text, or returns null if no text content can be found.
|
|
10
|
+
* @param separator Separator to use between individual elements. Defaults to newline.
|
|
11
|
+
*/
|
|
12
|
+
text(separator: string = "\n"): string | null {
|
|
13
|
+
return this.elements()
|
|
14
|
+
.map(element => (element as TextualElement)?.text)
|
|
15
|
+
.filter(text => text !== undefined && text.length > 0)
|
|
16
|
+
.join(separator);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Creates a new iterator for this content.
|
|
21
|
+
*/
|
|
22
|
+
abstract iterator(): Iterator;
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Returns all the elements as a list.
|
|
26
|
+
*/
|
|
27
|
+
elements(): ContentElement[] {
|
|
28
|
+
const list: ContentElement[] = [];
|
|
29
|
+
const iterator = this.iterator();
|
|
30
|
+
while (true) {
|
|
31
|
+
if(!iterator.hasNext()) break;
|
|
32
|
+
list.push(iterator.next());
|
|
33
|
+
}
|
|
34
|
+
return list;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { DefaultTextContentTokenizer, Range, TextTokenizer, TextUnit, Tokenizer } from "../../../util";
|
|
2
|
+
import { Locator, LocatorText } from "../../Locator";
|
|
3
|
+
import { ContentElement, TextElement, TextSegment } from "./element";
|
|
4
|
+
|
|
5
|
+
// A tokenizer splitting a [Content.Element] into smaller pieces.
|
|
6
|
+
export type ContentTokenizer = Tokenizer<ContentElement, ContentElement>;
|
|
7
|
+
|
|
8
|
+
export class TextContentTokenizer implements ContentTokenizer {
|
|
9
|
+
/**
|
|
10
|
+
*
|
|
11
|
+
* @param defaultLanguage The default assumed language
|
|
12
|
+
* @param unit The unit of the produced [Locator]s.
|
|
13
|
+
* @param contextSnippetLength Length of `before` and `after` snippets in the produced [Locator]s.
|
|
14
|
+
* @param textTokenizerFactory Factory to create a [TextTokenizer] from, using the specified language and unit.
|
|
15
|
+
*/
|
|
16
|
+
constructor(
|
|
17
|
+
private readonly defaultLanguage: string | null,
|
|
18
|
+
unit: TextUnit,
|
|
19
|
+
private readonly contextSnippetLength = 50,
|
|
20
|
+
private readonly textTokenizerFactory: (language: string | null) => TextTokenizer
|
|
21
|
+
= (language) => DefaultTextContentTokenizer(language, unit)
|
|
22
|
+
) {}
|
|
23
|
+
|
|
24
|
+
tokenize(data: ContentElement): ContentElement[] {
|
|
25
|
+
if(data instanceof TextElement) {
|
|
26
|
+
return [
|
|
27
|
+
new TextElement(
|
|
28
|
+
data.locator,
|
|
29
|
+
data.role,
|
|
30
|
+
data.segments.map(s => this.tokenizeSegment(s)).flat(),
|
|
31
|
+
)
|
|
32
|
+
];
|
|
33
|
+
}
|
|
34
|
+
return [data];
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
private tokenizeSegment(segment: TextSegment): TextSegment[] {
|
|
38
|
+
return this.textTokenizerFactory(segment.language ?? this.defaultLanguage)
|
|
39
|
+
.tokenize(segment.text)
|
|
40
|
+
.map(range => new TextSegment(
|
|
41
|
+
new Locator({
|
|
42
|
+
href: segment.locator.href,
|
|
43
|
+
type: segment.locator.type,
|
|
44
|
+
title: segment.locator.title,
|
|
45
|
+
locations: segment.locator.locations,
|
|
46
|
+
text: this.extractTextContextIn(segment.text, range)
|
|
47
|
+
}),
|
|
48
|
+
segment.text.substring(range[0], range[1]),
|
|
49
|
+
segment._attributes
|
|
50
|
+
));
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
private extractTextContextIn(str: string, range: Range): LocatorText {
|
|
54
|
+
const after = str.substring(range[1], range[1] + this.contextSnippetLength);
|
|
55
|
+
const before = str.substring(range[0] - this.contextSnippetLength, range[0]);
|
|
56
|
+
return new LocatorText({
|
|
57
|
+
after: after.length > 0 ? after : undefined,
|
|
58
|
+
before: before.length > 0 ? before : undefined,
|
|
59
|
+
highlight: str.substring(range[0], range[1]),
|
|
60
|
+
})
|
|
61
|
+
}
|
|
62
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { ContentElement } from "./element";
|
|
2
|
+
|
|
3
|
+
export class IllegalStateError extends Error {
|
|
4
|
+
constructor(message: string) {
|
|
5
|
+
super(message);
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Iterates through a list of [Element] items asynchronously.
|
|
11
|
+
* [hasNext] and [hasPrevious] refer to the last element computed by a previous call to any of both methods.
|
|
12
|
+
*/
|
|
13
|
+
export abstract class Iterator {
|
|
14
|
+
/**
|
|
15
|
+
* Returns true if the iterator has a next element, suspending the caller while processing it.
|
|
16
|
+
*/
|
|
17
|
+
abstract hasNext(): Promise<boolean>;
|
|
18
|
+
/**
|
|
19
|
+
* Retrieves the element computed by a preceding call to [hasNext], or throws an
|
|
20
|
+
* [IllegalStateError] if [hasNext] was not invoked. This method should only be used in
|
|
21
|
+
* pair with [hasNext].
|
|
22
|
+
*/
|
|
23
|
+
abstract next(): ContentElement;
|
|
24
|
+
/**
|
|
25
|
+
* Advances to the next item and returns it, or null if we reached the end.
|
|
26
|
+
*/
|
|
27
|
+
async nextOrNull(): Promise<ContentElement | null> {
|
|
28
|
+
return (await this.hasNext()) ? this.next() : null;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Returns true if the iterator has a previous element, suspending the caller while processing it.
|
|
32
|
+
*/
|
|
33
|
+
abstract hasPrevious(): Promise<boolean>;
|
|
34
|
+
/**
|
|
35
|
+
* Retrieves the element computed by a preceding call to [hasPrevious], or throws an
|
|
36
|
+
* [IllegalStateError] if [hasPrevious] was not invoked. This method should only be used in
|
|
37
|
+
* pair with [hasPrevious].
|
|
38
|
+
*/
|
|
39
|
+
abstract previous(): ContentElement;
|
|
40
|
+
/**
|
|
41
|
+
* Advances to the previous item and returns it, or null if we reached the beginning.
|
|
42
|
+
*/
|
|
43
|
+
async previousOrNull(): Promise<ContentElement | null> {
|
|
44
|
+
return (await this.hasPrevious()) ? this.previous() : null;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { Language } from "../../../../util/Language";
|
|
2
|
+
|
|
3
|
+
export class Attribute<V> {
|
|
4
|
+
constructor(
|
|
5
|
+
public key: AttributeKeys | string,
|
|
6
|
+
public value: V
|
|
7
|
+
) { }
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export enum AttributeKeys {
|
|
11
|
+
ACCESSIBILITY_LABEL = "accessibilityLabel",
|
|
12
|
+
LANGUAGE = "language",
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export abstract class AttributesHolder {
|
|
16
|
+
constructor(
|
|
17
|
+
/**
|
|
18
|
+
* Associated list of attributes.
|
|
19
|
+
*/
|
|
20
|
+
readonly _attributes: Attribute<any>[] = []
|
|
21
|
+
) {}
|
|
22
|
+
|
|
23
|
+
get language(): Language | undefined {
|
|
24
|
+
return this.attribute(AttributeKeys.LANGUAGE);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
get accessibilityLabel(): string | undefined {
|
|
28
|
+
return this.attribute(AttributeKeys.ACCESSIBILITY_LABEL);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Gets the first attribute with the given [key].
|
|
33
|
+
*/
|
|
34
|
+
attribute<V>(key: AttributeKeys | string): V | undefined {
|
|
35
|
+
return this._attributes.find(attribute => attribute.key === key)?.value;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Gets all the attributes with the given [key].
|
|
40
|
+
*/
|
|
41
|
+
attributes<V>(key: AttributeKeys | string): V[] {
|
|
42
|
+
return this._attributes.filter(attribute => attribute.key === key).map(attribute => attribute.value);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { Link } from "../../../Link";
|
|
2
|
+
import { Locator } from "../../../Locator";
|
|
3
|
+
import { AttributesHolder, Attribute } from "./attributes";
|
|
4
|
+
import { TextRole } from "./text_role";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Represents a single semantic content element part of a publication.
|
|
8
|
+
* NOTE: This is named "Element" in other toolkits. This conflicts with the JavaScript `Element` type so it's been renamed.
|
|
9
|
+
*/
|
|
10
|
+
export abstract class ContentElement extends AttributesHolder {
|
|
11
|
+
constructor(public readonly locator: Locator, attributes: Attribute<any>[] = []) {
|
|
12
|
+
super(attributes);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* An element which can be represented as human-readable text.
|
|
18
|
+
* The default implementation returns the first accessibility label associated to the element.
|
|
19
|
+
*/
|
|
20
|
+
export class TextualElement extends ContentElement {
|
|
21
|
+
/**
|
|
22
|
+
* Human-readable text representation for this element.
|
|
23
|
+
*/
|
|
24
|
+
get text(): string | undefined {
|
|
25
|
+
return this.accessibilityLabel;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* An element referencing an embedded external resource.
|
|
31
|
+
*/
|
|
32
|
+
export interface EmbeddedElement extends ContentElement {
|
|
33
|
+
/**
|
|
34
|
+
* Referenced resource in the publication.
|
|
35
|
+
*/
|
|
36
|
+
readonly embeddedLink: Link;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* An audio clip.
|
|
41
|
+
*/
|
|
42
|
+
export class AudioElement extends TextualElement implements EmbeddedElement {
|
|
43
|
+
constructor(
|
|
44
|
+
locator: Locator,
|
|
45
|
+
readonly embeddedLink: Link,
|
|
46
|
+
attributes: Attribute<any>[] = [],
|
|
47
|
+
) { super(locator, attributes); }
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* A video clip.
|
|
52
|
+
*/
|
|
53
|
+
export class VideoElement extends TextualElement implements EmbeddedElement {
|
|
54
|
+
constructor(
|
|
55
|
+
locator: Locator,
|
|
56
|
+
readonly embeddedLink: Link,
|
|
57
|
+
attributes: Attribute<any>[] = [],
|
|
58
|
+
) { super(locator, attributes); }
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* A bitmap image.
|
|
63
|
+
*/
|
|
64
|
+
export class ImageElement extends TextualElement implements EmbeddedElement {
|
|
65
|
+
constructor(
|
|
66
|
+
locator: Locator,
|
|
67
|
+
readonly embeddedLink: Link,
|
|
68
|
+
/**
|
|
69
|
+
* Short piece of text associated with the image.
|
|
70
|
+
*/
|
|
71
|
+
readonly caption?: string,
|
|
72
|
+
attributes: Attribute<any>[] = [],
|
|
73
|
+
) { super(locator, attributes); }
|
|
74
|
+
|
|
75
|
+
get text(): string | undefined {
|
|
76
|
+
// The caption might be a better text description than the accessibility label, when available.
|
|
77
|
+
return (this.caption?.length || 0) > 0 ? this.caption : super.text;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export class TextSegment extends AttributesHolder {
|
|
82
|
+
constructor(
|
|
83
|
+
/**
|
|
84
|
+
* Locator to the segment of text.
|
|
85
|
+
*/
|
|
86
|
+
readonly locator: Locator,
|
|
87
|
+
/**
|
|
88
|
+
* Text in the segment.
|
|
89
|
+
*/
|
|
90
|
+
readonly text: string,
|
|
91
|
+
/**
|
|
92
|
+
* Attributes associated with this segment, e.g. language.
|
|
93
|
+
*/
|
|
94
|
+
attributes: Attribute<any>[] = [],
|
|
95
|
+
) { super(attributes); }
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* A text element.
|
|
100
|
+
*/
|
|
101
|
+
export class TextElement extends TextualElement {
|
|
102
|
+
constructor(
|
|
103
|
+
locator: Locator,
|
|
104
|
+
/**
|
|
105
|
+
* Purpose of this element in the broader context of the document.
|
|
106
|
+
*/
|
|
107
|
+
readonly role: TextRole,
|
|
108
|
+
/**
|
|
109
|
+
* Ranged portions of text with associated attributes.
|
|
110
|
+
*/
|
|
111
|
+
readonly segments: TextSegment[],
|
|
112
|
+
attributes: Attribute<any>[] = [],
|
|
113
|
+
) { super(locator, attributes); }
|
|
114
|
+
|
|
115
|
+
get text(): string | undefined {
|
|
116
|
+
return this.segments.map(segment => segment.text).join("");
|
|
117
|
+
}
|
|
118
|
+
}
|