@readium/shared 2.4.0-alpha.1 → 2.5.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 (166) hide show
  1. package/README.MD +8 -7
  2. package/dist/_virtual/preload-helper.js +1 -0
  3. package/dist/fetcher/Fetcher.js +1 -0
  4. package/dist/fetcher/HttpFetcher.js +1 -0
  5. package/dist/fetcher/Resource.js +1 -0
  6. package/dist/index.js +1 -4993
  7. package/dist/locales/publication-metadata/ar.json.js +1 -0
  8. package/dist/locales/publication-metadata/da.json.js +1 -0
  9. package/dist/locales/publication-metadata/el.json.js +1 -0
  10. package/dist/locales/publication-metadata/en.json.js +1 -0
  11. package/dist/locales/publication-metadata/es.json.js +1 -0
  12. package/dist/locales/publication-metadata/et.json.js +1 -0
  13. package/dist/locales/publication-metadata/fi.json.js +1 -0
  14. package/dist/locales/publication-metadata/fr.json.js +1 -0
  15. package/dist/locales/publication-metadata/it.json.js +1 -0
  16. package/dist/locales/publication-metadata/pl.json.js +1 -0
  17. package/dist/locales/publication-metadata/pt_PT.json.js +1 -0
  18. package/dist/locales/publication-metadata/sv.json.js +1 -0
  19. package/dist/node_modules/.pnpm/css-selector-generator@3.8.0/node_modules/css-selector-generator/esm/constants.js +1 -0
  20. package/dist/node_modules/.pnpm/css-selector-generator@3.8.0/node_modules/css-selector-generator/esm/index.js +1 -0
  21. package/dist/node_modules/.pnpm/css-selector-generator@3.8.0/node_modules/css-selector-generator/esm/selector-attribute.js +1 -0
  22. package/dist/node_modules/.pnpm/css-selector-generator@3.8.0/node_modules/css-selector-generator/esm/selector-class.js +1 -0
  23. package/dist/node_modules/.pnpm/css-selector-generator@3.8.0/node_modules/css-selector-generator/esm/selector-fallback.js +1 -0
  24. package/dist/node_modules/.pnpm/css-selector-generator@3.8.0/node_modules/css-selector-generator/esm/selector-id.js +1 -0
  25. package/dist/node_modules/.pnpm/css-selector-generator@3.8.0/node_modules/css-selector-generator/esm/selector-nth-child.js +1 -0
  26. package/dist/node_modules/.pnpm/css-selector-generator@3.8.0/node_modules/css-selector-generator/esm/selector-nth-of-type.js +1 -0
  27. package/dist/node_modules/.pnpm/css-selector-generator@3.8.0/node_modules/css-selector-generator/esm/selector-tag.js +1 -0
  28. package/dist/node_modules/.pnpm/css-selector-generator@3.8.0/node_modules/css-selector-generator/esm/types.js +1 -0
  29. package/dist/node_modules/.pnpm/css-selector-generator@3.8.0/node_modules/css-selector-generator/esm/utilities-cartesian.js +1 -0
  30. package/dist/node_modules/.pnpm/css-selector-generator@3.8.0/node_modules/css-selector-generator/esm/utilities-data.js +1 -0
  31. package/dist/node_modules/.pnpm/css-selector-generator@3.8.0/node_modules/css-selector-generator/esm/utilities-dom.js +1 -0
  32. package/dist/node_modules/.pnpm/css-selector-generator@3.8.0/node_modules/css-selector-generator/esm/utilities-element-data.js +1 -0
  33. package/dist/node_modules/.pnpm/css-selector-generator@3.8.0/node_modules/css-selector-generator/esm/utilities-iselement.js +1 -0
  34. package/dist/node_modules/.pnpm/css-selector-generator@3.8.0/node_modules/css-selector-generator/esm/utilities-messages.js +1 -0
  35. package/dist/node_modules/.pnpm/css-selector-generator@3.8.0/node_modules/css-selector-generator/esm/utilities-options.js +1 -0
  36. package/dist/node_modules/.pnpm/css-selector-generator@3.8.0/node_modules/css-selector-generator/esm/utilities-powerset.js +1 -0
  37. package/dist/node_modules/.pnpm/css-selector-generator@3.8.0/node_modules/css-selector-generator/esm/utilities-selectors.js +1 -0
  38. package/dist/node_modules/.pnpm/css-selector-generator@3.8.0/node_modules/css-selector-generator/esm/utilities-typescript.js +1 -0
  39. package/dist/opds/Acquisition.js +1 -0
  40. package/dist/opds/Availability.js +1 -0
  41. package/dist/opds/Copies.js +1 -0
  42. package/dist/opds/Holds.js +1 -0
  43. package/dist/opds/Price.js +1 -0
  44. package/dist/publication/AltIdentifier.js +1 -0
  45. package/dist/publication/BelongsTo.js +1 -0
  46. package/dist/publication/Contributor.js +1 -0
  47. package/dist/publication/GuidedNavigation.js +1 -0
  48. package/dist/publication/Layout.js +1 -0
  49. package/dist/publication/Link.js +1 -0
  50. package/dist/publication/LocalizedString.js +1 -0
  51. package/dist/publication/Locator.js +1 -0
  52. package/dist/publication/LocatorCollection.js +1 -0
  53. package/dist/publication/Manifest.js +1 -0
  54. package/dist/publication/Metadata.js +1 -0
  55. package/dist/publication/Profiles.js +1 -0
  56. package/dist/publication/Properties.js +1 -0
  57. package/dist/publication/Publication.js +1 -0
  58. package/dist/publication/PublicationCollection.js +1 -0
  59. package/dist/publication/ReadingProgression.js +1 -0
  60. package/dist/publication/Subject.js +1 -0
  61. package/dist/publication/TDM.js +1 -0
  62. package/dist/publication/accessibility/Accessibility.js +1 -0
  63. package/dist/publication/accessibility/AccessibilityMetadataDisplayGuide.js +1 -0
  64. package/dist/publication/accessibility/Localization.js +1 -0
  65. package/dist/publication/accessibility/SupportedLanguages.js +1 -0
  66. package/dist/publication/encryption/Encryption.js +1 -0
  67. package/dist/publication/encryption/Properties.js +1 -0
  68. package/dist/publication/encryption/index.js +1 -0
  69. package/dist/publication/epub/MediaOverlay.js +1 -0
  70. package/dist/publication/epub/Metadata.js +1 -0
  71. package/dist/publication/epub/Properties.js +1 -0
  72. package/dist/publication/epub/Publication.js +1 -0
  73. package/dist/publication/epub/index.js +1 -0
  74. package/dist/publication/html/DomRange.js +1 -0
  75. package/dist/publication/html/DomRangePoint.js +1 -0
  76. package/dist/publication/html/Locations.js +1 -0
  77. package/dist/publication/html/index.js +1 -0
  78. package/dist/publication/opds/Properties.js +1 -0
  79. package/dist/publication/opds/Publication.js +1 -0
  80. package/dist/publication/opds/index.js +1 -0
  81. package/dist/publication/services/content/Content.js +2 -0
  82. package/dist/publication/services/content/ContentTokenizer.js +1 -0
  83. package/dist/publication/services/content/Iterator.js +1 -0
  84. package/dist/publication/services/content/element/attributes.js +1 -0
  85. package/dist/publication/services/content/element/element.js +1 -0
  86. package/dist/publication/services/content/element/text_role.js +1 -0
  87. package/dist/publication/services/content/iterators/HTMLResourceContentIterator.js +1 -0
  88. package/dist/publication/services/content/iterators/PDFTextContentIterator.js +1 -0
  89. package/dist/publication/services/content/iterators/PublicationContentIterator.js +1 -0
  90. package/dist/publication/services/content/iterators/helpers.js +1 -0
  91. package/dist/publication/services/timeline/Timeline.js +1 -0
  92. package/dist/publication/services/timeline/audio.js +1 -0
  93. package/dist/publication/services/timeline/html.js +1 -0
  94. package/dist/publication/services/timeline/index.js +1 -0
  95. package/dist/util/JSONParse.js +1 -0
  96. package/dist/util/URITemplate.js +1 -0
  97. package/dist/util/mediatype/MediaType.js +1 -0
  98. package/dist/util/npt.js +1 -0
  99. package/dist/util/tokenizer/TextTokenizer.js +1 -0
  100. package/dist/util/tokenizer/tokenize-english/abbreviations.js +1 -0
  101. package/dist/util/tokenizer/tokenize-english/index.js +2 -0
  102. package/dist/util/tokenizer/tokenize-english/utils.js +1 -0
  103. package/dist/util/tokenizer/tokenize-text/index.js +1 -0
  104. package/dist/util/tokenizer/tokenize-text/tokens.js +1 -0
  105. package/package.json +29 -19
  106. package/src/fetcher/HttpFetcher.ts +5 -5
  107. package/src/fetcher/Resource.ts +5 -10
  108. package/src/locales/publication-metadata/ar.json +402 -0
  109. package/src/locales/publication-metadata/brh.json +1 -0
  110. package/src/locales/publication-metadata/da.json +310 -0
  111. package/src/locales/publication-metadata/el.json +310 -0
  112. package/src/locales/publication-metadata/en.json +310 -0
  113. package/src/locales/publication-metadata/es.json +333 -0
  114. package/src/locales/publication-metadata/et.json +310 -0
  115. package/src/locales/publication-metadata/fi.json +310 -0
  116. package/src/locales/publication-metadata/fr.json +333 -0
  117. package/src/locales/publication-metadata/he.json +9 -0
  118. package/src/locales/publication-metadata/it.json +333 -0
  119. package/src/locales/publication-metadata/lt.json +8 -0
  120. package/src/locales/publication-metadata/pl.json +333 -0
  121. package/src/locales/publication-metadata/pt_PT.json +329 -0
  122. package/src/locales/publication-metadata/sv.json +310 -0
  123. package/src/locales/publication-metadata/tr.json +51 -0
  124. package/src/locales/publication-metadata/uk.json +1 -0
  125. package/src/publication/Link.ts +2 -6
  126. package/src/publication/Locator.ts +21 -3
  127. package/src/publication/Manifest.ts +10 -10
  128. package/src/publication/Publication.ts +2 -1
  129. package/src/publication/accessibility/Localization.ts +12 -14
  130. package/src/publication/accessibility/SupportedLanguages.ts +1 -1
  131. package/src/publication/encryption/Properties.ts +3 -15
  132. package/src/publication/epub/Metadata.ts +6 -12
  133. package/src/publication/epub/Properties.ts +3 -13
  134. package/src/publication/epub/Publication.ts +18 -39
  135. package/src/publication/html/Locations.ts +63 -99
  136. package/src/publication/opds/Properties.ts +21 -66
  137. package/src/publication/opds/Publication.ts +3 -9
  138. package/src/publication/services/content/iterators/HTMLResourceContentIterator.ts +3 -1
  139. package/src/publication/services/timeline/Timeline.ts +311 -60
  140. package/src/publication/services/timeline/TimelineItem.ts +3 -3
  141. package/src/publication/services/timeline/audio.ts +31 -0
  142. package/src/publication/services/timeline/html.ts +5 -0
  143. package/src/publication/services/timeline/index.ts +12 -0
  144. package/src/util/npt.ts +19 -0
  145. package/types/src/fetcher/HttpFetcher.d.ts +3 -3
  146. package/types/src/fetcher/Resource.d.ts +2 -6
  147. package/types/src/publication/encryption/Properties.d.ts +2 -9
  148. package/types/src/publication/epub/Metadata.d.ts +3 -6
  149. package/types/src/publication/epub/Properties.d.ts +2 -10
  150. package/types/src/publication/epub/Publication.d.ts +7 -18
  151. package/types/src/publication/html/Locations.d.ts +17 -44
  152. package/types/src/publication/opds/Properties.d.ts +8 -36
  153. package/types/src/publication/opds/Publication.d.ts +2 -5
  154. package/types/src/publication/services/timeline/Timeline.d.ts +93 -13
  155. package/types/src/publication/services/timeline/TimelineItem.d.ts +3 -3
  156. package/types/src/publication/services/timeline/audio.d.ts +4 -0
  157. package/types/src/publication/services/timeline/html.d.ts +4 -0
  158. package/types/src/publication/services/timeline/index.d.ts +6 -0
  159. package/types/src/util/npt.d.ts +10 -0
  160. package/dist/ar-DyHX_uy2.js +0 -7
  161. package/dist/da-Dct0PS3E.js +0 -7
  162. package/dist/fr-C5HEel98.js +0 -7
  163. package/dist/index.umd.cjs +0 -3
  164. package/dist/it-DFOBoXGy.js +0 -7
  165. package/dist/pt_PT-Di3sVjze.js +0 -7
  166. package/dist/sv-BfzAFsVN.js +0 -7
@@ -0,0 +1,51 @@
1
+ {
2
+ "publication": {
3
+ "format": {
4
+ "audiobook": "Sesli Kitap",
5
+ "audiobookJSON": "Sesli Kitap Manifest Dosyası",
6
+ "cbz": "Çizgi Roman Arşivi",
7
+ "divina": "Divina Yayını",
8
+ "divinaJSON": "Divina Yayını Manifest Dosyası",
9
+ "epub": "EPUB",
10
+ "lcpa": "LCP Korumalı Sesli Kitap",
11
+ "lcpdf": "LCP Korumalı PDF",
12
+ "lcpl": "LCP Lisans Belgesi",
13
+ "pdf": "PDF",
14
+ "rwp": "Readium Web Yayını",
15
+ "rwpm": "Readium Web Yayını Manifest Dosyası",
16
+ "zab": "Sesli Kitap Arşivi",
17
+ "zip": "ZIP Arşivi"
18
+ },
19
+ "kind": {
20
+ "audiobook_one": "Sesli Kitap",
21
+ "audiobook_other": "Sesli Kitaplar",
22
+ "book_one": "kitap",
23
+ "book_other": "kitaplar",
24
+ "comic_one": "çizgi roman",
25
+ "comic_other": "çizgi romanlar",
26
+ "document_one": "belge",
27
+ "document_other": "belgeler"
28
+ },
29
+ "metadata": {
30
+ "accessibility": {
31
+ "display-guide": {
32
+ "accessibility-summary": {
33
+ "no-metadata": "Bilgi mevcut değil",
34
+ "publisher-contact": "Bu ürünün erişilebilirliği hakkında daha fazla bilgi için lütfen yayıncıyla bağlantı kurun: ",
35
+ "title": "Erişilebilirlik özeti"
36
+ },
37
+ "additional-accessibility-information": {
38
+ "aria": {
39
+ "compact": "ARIA rolleri dahildir",
40
+ "descriptive": "İçerik, düzeni en iyi hale getirmek ve gezinmeyi kolaylaştırmak için ARIA rolleriyle iyileştirilmiştir"
41
+ },
42
+ "audio-descriptions": "Sesli betimlemeler",
43
+ "braille": "Braille",
44
+ "color-not-sole-means-of-conveying-information": "Renk, bilgi aktarmanın tek yolu değildir",
45
+ "dyslexia-readability": "Okuma güçlüğü olanlar için uyarlanmış okunabilirlik"
46
+ }
47
+ }
48
+ }
49
+ }
50
+ }
51
+ }
@@ -11,7 +11,7 @@ import {
11
11
  positiveNumberfromJSON,
12
12
  setToArray,
13
13
  } from '../util/JSONParse.ts';
14
- import { LocatorLocations, Locator } from './Locator.ts';
14
+ import { Locator } from './Locator.ts';
15
15
 
16
16
  /**
17
17
  * Link Object for the Readium Web Publication Manifest.
@@ -197,14 +197,10 @@ export class Link {
197
197
  * Creates a [Locator] from a reading order [Link].
198
198
  */
199
199
  public get locator(): Locator {
200
- let parts = this.href.split('#');
201
200
  return new Locator({
202
- href: parts.length > 0 && parts[0] !== undefined ? parts[0] : this.href,
201
+ href: this.href,
203
202
  type: this.type ?? '',
204
203
  title: this.title,
205
- locations: new LocatorLocations({
206
- fragments: parts.length > 1 && parts[1] !== undefined ? [parts[1]] : [],
207
- }),
208
204
  });
209
205
  }
210
206
  }
@@ -59,12 +59,20 @@ export class LocatorLocations {
59
59
  'progression',
60
60
  'totalProgression',
61
61
  'position',
62
+ 'otherLocations',
62
63
  ]);
63
64
  Object.entries(json).forEach(([key, value]) => {
64
65
  if (!reservedKeys.has(key)) {
65
66
  otherLocations.set(key, value);
66
67
  }
67
68
  });
69
+ // json may be a live LocatorLocations instance (e.g. passed through in-memory
70
+ // rather than round-tripped as RWPM JSON) — its otherLocations is a Map, not
71
+ // flattened keys, and must be merged in directly rather than treated as an
72
+ // extension entry itself.
73
+ if (json.otherLocations instanceof Map) {
74
+ json.otherLocations.forEach((value: any, key: string) => otherLocations.set(key, value));
75
+ }
68
76
 
69
77
  return new LocatorLocations({
70
78
  fragments: arrayfromJSONorString(json.fragments || json.fragment),
@@ -176,12 +184,22 @@ export class Locator {
176
184
  locations?: LocatorLocations;
177
185
  text?: LocatorText;
178
186
  }) {
179
- this.href = values.href;
187
+ const hashIndex = values.href.indexOf("#");
188
+ const hrefFragment = hashIndex >= 0 ? values.href.slice(hashIndex + 1) : undefined;
189
+ this.href = hashIndex >= 0 ? values.href.slice(0, hashIndex) : values.href;
180
190
  this.type = values.type;
181
191
  this.title = values.title;
192
+ // If locations.fragments is already set, it takes precedence over any fragment in the href.
193
+ // We don't merge both because explicit fragments are considered authoritative.
194
+ const existingFragments = values.locations?.fragments;
195
+ const needsFragment = hrefFragment && (!existingFragments || existingFragments.length === 0);
182
196
  this.locations = values.locations
183
- ? values.locations
184
- : new LocatorLocations({});
197
+ ? needsFragment
198
+ ? new LocatorLocations({ ...values.locations, fragments: [hrefFragment!] })
199
+ : values.locations
200
+ : hrefFragment
201
+ ? new LocatorLocations({ fragments: [hrefFragment] })
202
+ : new LocatorLocations({});
185
203
  this.text = values.text;
186
204
  }
187
205
 
@@ -43,7 +43,7 @@ export class Manifest {
43
43
  }) {
44
44
  this.context = values.context;
45
45
  this.metadata = values.metadata;
46
- this.links = values.links || new Links([]);
46
+ this.links = values.links;
47
47
  this.readingOrder = values.readingOrder;
48
48
  this.resources = values.resources;
49
49
  this.toc = values.toc;
@@ -63,6 +63,8 @@ export class Manifest {
63
63
 
64
64
  if (!metadata) return;
65
65
 
66
+ const links = Links.deserialize(json.links);
67
+
66
68
  const readingOrder = Links.deserialize(
67
69
  json.readingOrder ? json.readingOrder : json.spine
68
70
  );
@@ -78,7 +80,7 @@ export class Manifest {
78
80
  return new Manifest({
79
81
  context: arrayfromJSONorString(json['@context']),
80
82
  metadata,
81
- links: Links.deserialize(json.links),
83
+ links,
82
84
  readingOrder,
83
85
  resources: Links.deserialize(json.resources),
84
86
  toc: Links.deserialize(json.toc),
@@ -93,7 +95,7 @@ export class Manifest {
93
95
  const json: any = {};
94
96
  if (this.context !== undefined) json['@context'] = this.context;
95
97
  json.metadata = this.metadata.serialize();
96
- if (this.links && this.links.items.length > 0) json.links = this.links.serialize();
98
+ if (this.links !== undefined) json.links = this.links.serialize();
97
99
  json.readingOrder = this.readingOrder.serialize();
98
100
  if (this.resources) json.resources = this.resources.serialize();
99
101
  if (this.toc) json.toc = this.toc.serialize();
@@ -143,21 +145,19 @@ export class Manifest {
143
145
  * Returns null if the resource is not found in this manifest.
144
146
  */
145
147
  public locatorFromLink(link: Link): Locator | undefined {
146
- const components = link.href.split("#");
147
- const href = components.length == 2 ? components[0] : link.href;
148
- const resourceLink = this.linkWithHref(href);
148
+ const bare = link.href.split("#")[0];
149
+ const resourceLink = this.linkWithHref(bare);
149
150
  if(!resourceLink) return undefined;
150
151
  const type = resourceLink.type;
151
152
  if(!type) return undefined;
152
- const fragment = components.length == 2 ? components[1] : undefined;
153
+ const hasFragment = link.href.includes("#");
153
154
 
154
155
  return new Locator({
155
- href,
156
+ href: link.href,
156
157
  type,
157
158
  title: resourceLink.title ?? link.title,
158
159
  locations: new LocatorLocations({
159
- fragments: fragment ? [fragment] : undefined,
160
- progression: fragment ? undefined : 0.0,
160
+ progression: hasFragment ? undefined : 0.0,
161
161
  })
162
162
  });
163
163
  }
@@ -13,6 +13,7 @@ import { Resource } from '../fetcher/Resource.ts';
13
13
  import { GuidedNavigationDocument } from "./GuidedNavigation.ts";
14
14
  import { MediaType, URITemplate } from "../util/index.ts";
15
15
  import { Timeline } from './services/timeline/Timeline.ts';
16
+ import { buildTimeline } from './services/timeline/index.ts';
16
17
 
17
18
  /** Shared model for a Readium Publication. */
18
19
  export class Publication {
@@ -51,7 +52,7 @@ export class Publication {
51
52
  * The result is cached after the first call.
52
53
  */
53
54
  public get timeline(): Timeline {
54
- if (!this._timeline) this._timeline = Timeline.build(this);
55
+ if (!this._timeline) this._timeline = buildTimeline(this);
55
56
  return this._timeline;
56
57
  }
57
58
 
@@ -1,8 +1,5 @@
1
- // Localization.ts
2
-
3
1
  import { SUPPORTED_LANGUAGES } from './SupportedLanguages.ts';
4
- // Static import for English (default locale)
5
- import enLocale from '@edrlab/thorium-locales/publication-metadata/en.json';
2
+ import enLocale from '../../locales/publication-metadata/en.json';
6
3
 
7
4
  export interface L10nString {
8
5
  compact: string;
@@ -16,16 +13,17 @@ interface LocaleData {
16
13
 
17
14
  // Dynamic imports for non-English locales
18
15
  const jsonLoaders: Record<string, () => Promise<{ default: any }>> = {
19
- 'fr': () => import('@edrlab/thorium-locales/publication-metadata/fr.json'),
20
- 'ar': () => import('@edrlab/thorium-locales/publication-metadata/ar.json'),
21
- 'da': () => import('@edrlab/thorium-locales/publication-metadata/da.json'),
22
- // 'el': () => import('@edrlab/thorium-locales/publication-metadata/el.json'),
23
- // 'et': () => import('@edrlab/thorium-locales/publication-metadata/et.json'),
24
- 'it': () => import('@edrlab/thorium-locales/publication-metadata/it.json'),
25
- 'pt_PT': () => import('@edrlab/thorium-locales/publication-metadata/pt_PT.json'),
26
- 'sv': () => import('@edrlab/thorium-locales/publication-metadata/sv.json'),
27
- // 'tr': () => import('@edrlab/thorium-locales/publication-metadata/tr.json'),
28
- // 'uk': () => import('@edrlab/thorium-locales/publication-metadata/uk.json')
16
+ 'ar': () => import('../../locales/publication-metadata/ar.json'),
17
+ 'da': () => import('../../locales/publication-metadata/da.json'),
18
+ 'el': () => import('../../locales/publication-metadata/el.json'),
19
+ 'es': () => import('../../locales/publication-metadata/es.json'),
20
+ 'et': () => import('../../locales/publication-metadata/et.json'),
21
+ 'fi': () => import('../../locales/publication-metadata/fi.json'),
22
+ 'fr': () => import('../../locales/publication-metadata/fr.json'),
23
+ 'it': () => import('../../locales/publication-metadata/it.json'),
24
+ 'pl': () => import('../../locales/publication-metadata/pl.json'),
25
+ 'pt_PT': () => import('../../locales/publication-metadata/pt_PT.json'),
26
+ 'sv': () => import('../../locales/publication-metadata/sv.json')
29
27
  };
30
28
 
31
29
  // Extract English accessibility data
@@ -1 +1 @@
1
- export const SUPPORTED_LANGUAGES = ['en', 'ar', 'da', 'fr', 'it', 'pt_PT', 'sv'];
1
+ export const SUPPORTED_LANGUAGES = ['en', 'ar', 'da', 'el', 'es', 'et', 'fi', 'fr', 'it', 'pl', 'pt_PT', 'sv'];
@@ -1,20 +1,8 @@
1
1
  import { Properties } from '../Properties.ts';
2
2
  import { Encryption } from './Encryption.ts';
3
3
 
4
- // Encryption extensions for link [Properties].
4
+ // Encryption extensions for link Properties.
5
5
 
6
- declare module '../Properties' {
7
- export interface Properties {
8
- /**
9
- * Indicates that a resource is encrypted/obfuscated and provides relevant information for
10
- * decryption.
11
- */
12
- encryption: Encryption | undefined;
13
- }
6
+ export function getEncryption(properties: Properties): Encryption | undefined {
7
+ return Encryption.deserialize(properties.otherProperties.encrypted);
14
8
  }
15
-
16
- Object.defineProperty(Properties.prototype, 'encryption', {
17
- get: function(): Encryption | undefined {
18
- return Encryption.deserialize(this.otherProperties.encrypted);
19
- },
20
- });
@@ -1,16 +1,10 @@
1
- import { Metadata } from "../Metadata.ts";
2
- import { MediaOverlay } from "./MediaOverlay.ts";
1
+ import { Metadata } from '../Metadata.ts';
2
+ import { MediaOverlay } from './MediaOverlay.ts';
3
3
 
4
- declare module '../Metadata' {
5
- export interface Metadata {
6
- getMediaOverlay(): MediaOverlay | undefined;
7
- }
8
- }
9
-
10
- Metadata.prototype.getMediaOverlay = function(): MediaOverlay | undefined {
11
- const mediaOverlay = this.otherMetadata?.['mediaOverlay'];
4
+ // EPUB extensions for Metadata.
12
5
 
6
+ export function getMediaOverlay(metadata: Metadata): MediaOverlay | undefined {
7
+ const mediaOverlay = metadata.otherMetadata?.['mediaOverlay'];
13
8
  if (!mediaOverlay) return;
14
-
15
9
  return MediaOverlay.deserialize(mediaOverlay);
16
- };
10
+ }
@@ -1,18 +1,8 @@
1
1
  import { Properties } from '../Properties.ts';
2
2
 
3
- // EPUB extensions for link [Properties].
3
+ // EPUB extensions for link Properties.
4
4
  // https://readium.org/webpub-manifest/schema/extensions/epub/properties.schema.json
5
5
 
6
- declare module '../Properties' {
7
- export interface Properties {
8
- /**
9
- * Identifies content contained in the linked resource, that cannot be strictly identified using a
10
- * media type.
11
- */
12
- getContains(): Set<string> | undefined;
13
- }
6
+ export function getContains(properties: Properties): Set<string> {
7
+ return new Set<string>(properties.otherProperties['contains'] || []);
14
8
  }
15
-
16
- Properties.prototype.getContains = function(): Set<string> | undefined {
17
- return new Set<string>(this.otherProperties['contains'] || []);
18
- };
@@ -1,51 +1,30 @@
1
1
  import { Links } from '../Link.ts';
2
2
  import { Publication } from '../Publication.ts';
3
3
 
4
- // EPUB extensions for [Publication].
4
+ // EPUB extensions for Publication.
5
5
  // https://readium.org/webpub-manifest/schema/extensions/epub/subcollections.schema.json
6
6
  // https://idpf.github.io/epub-vocabs/structure/#navigation
7
7
 
8
- declare module '../Publication' {
9
- export interface Publication {
10
- /**
11
- * Provides navigation to positions in the Publication content that correspond to the locations of
12
- * page boundaries present in a print source being represented by this EPUB Publication.
13
- */
14
- getPageList(): Links | undefined;
15
-
16
- /**
17
- * Identifies fundamental structural components of the publication in order to enable Reading
18
- * Systems to provide the User efficient access to them.
19
- */
20
- getLandmarks(): Links | undefined;
21
-
22
- getListOfAudioClips(): Links | undefined;
23
- getListOfIllustrations(): Links | undefined;
24
- getListOfTables(): Links | undefined;
25
- getListOfVideoClips(): Links | undefined;
26
- }
8
+ export function getPageList(pub: Publication): Links | undefined {
9
+ return pub.linksWithRole('pageList');
27
10
  }
28
11
 
29
- Publication.prototype.getPageList = function(): Links | undefined {
30
- return this.linksWithRole('pageList');
31
- };
32
-
33
- Publication.prototype.getLandmarks = function(): Links | undefined {
34
- return this.linksWithRole('landmarks');
35
- };
12
+ export function getLandmarks(pub: Publication): Links | undefined {
13
+ return pub.linksWithRole('landmarks');
14
+ }
36
15
 
37
- Publication.prototype.getListOfAudioClips = function(): Links | undefined {
38
- return this.linksWithRole('loa');
39
- };
16
+ export function getListOfAudioClips(pub: Publication): Links | undefined {
17
+ return pub.linksWithRole('loa');
18
+ }
40
19
 
41
- Publication.prototype.getListOfIllustrations = function(): Links | undefined {
42
- return this.linksWithRole('loi');
43
- };
20
+ export function getListOfIllustrations(pub: Publication): Links | undefined {
21
+ return pub.linksWithRole('loi');
22
+ }
44
23
 
45
- Publication.prototype.getListOfTables = function(): Links | undefined {
46
- return this.linksWithRole('lot');
47
- };
24
+ export function getListOfTables(pub: Publication): Links | undefined {
25
+ return pub.linksWithRole('lot');
26
+ }
48
27
 
49
- Publication.prototype.getListOfVideoClips = function(): Links | undefined {
50
- return this.linksWithRole('lov');
51
- };
28
+ export function getListOfVideoClips(pub: Publication): Links | undefined {
29
+ return pub.linksWithRole('lov');
30
+ }
@@ -1,129 +1,93 @@
1
1
  import { LocatorLocations } from '../Locator.ts';
2
2
  import { DomRange } from './DomRange.ts';
3
3
  import { parseNptTime } from '../../util/npt.ts';
4
+ import { decodeTextFragmentDirective, TextFragmentDirective } from '@readium/helpers';
4
5
 
5
- // HTML extensions for [Locations].
6
+ // HTML extensions for LocatorLocations.
6
7
  // https://github.com/readium/architecture/blob/master/models/locators/extensions/html.md
7
8
 
8
- declare module '../Locator' {
9
- export interface LocatorLocations {
10
- /**
11
- * A CSS Selector.
12
- */
13
- getCssSelector(): string | undefined;
14
-
15
- /**
16
- * [partialCfi] is an expression conforming to the "right-hand" side of the EPUB CFI syntax, that is
17
- * to say: without the EPUB-specific OPF spine item reference that precedes the first ! exclamation
18
- * mark (which denotes the "step indirection" into a publication document). Note that the wrapping
19
- * epubcfi(***) syntax is not used for the [partialCfi] string, i.e. the "fragment" part of the CFI
20
- * grammar is ignored.
21
- */
22
- getPartialCfi(): string | undefined;
23
-
24
- /**
25
- * An HTML DOM range.
26
- */
27
- getDomRange(): DomRange | undefined;
28
-
29
- /**
30
- * All named parameters found in the fragments, such as `p=5`.
31
- */
32
- fragmentParameters(): Map<string, string>;
33
-
34
- /**
35
- * HTML ID fragment identifier.
36
- */
37
- htmlId(): string | undefined;
9
+ export function getCssSelector(loc: LocatorLocations): string | undefined {
10
+ return loc.otherLocations?.get('cssSelector');
11
+ }
38
12
 
39
- /**
40
- * Page fragment identifier, used for example in PDF.
41
- */
42
- page(): number | undefined;
13
+ export function getPartialCfi(loc: LocatorLocations): string | undefined {
14
+ return loc.otherLocations?.get('partialCfi');
15
+ }
43
16
 
44
- /**
45
- * Temporal Dimension media fragment, used for example in audiobooks.
46
- *
47
- * https://www.w3.org/TR/media-frags/
48
- */
49
- time(): number | undefined;
17
+ export function getDomRange(loc: LocatorLocations): DomRange | undefined {
18
+ return DomRange.deserialize(loc.otherLocations?.get('domRange'));
19
+ }
50
20
 
51
- /**
52
- * Spatial Dimension media fragment, used for example in audiobooks.
53
- *
54
- * https://www.w3.org/TR/media-frags/
55
- */
56
- space(): [number, number, number, number] | undefined;
21
+ // A WICG text-fragment directive (":~:text=...") found among fragments, per
22
+ // https://wicg.github.io/scroll-to-text-fragment/.
23
+ export function getTextFragment(loc: LocatorLocations): TextFragmentDirective | undefined {
24
+ for (const fragment of loc.fragments) {
25
+ const directive = decodeTextFragmentDirective(fragment);
26
+ if (directive) return directive;
57
27
  }
28
+ return undefined;
58
29
  }
59
30
 
60
- LocatorLocations.prototype.getCssSelector = function(): string | undefined {
61
- return this.otherLocations?.get('cssSelector');
62
- };
63
-
64
- LocatorLocations.prototype.getPartialCfi = function(): string | undefined {
65
- return this.otherLocations?.get('partialCfi');
66
- };
67
-
68
- LocatorLocations.prototype.getDomRange = function(): DomRange | undefined {
69
- return DomRange.deserialize(this.otherLocations?.get('domRange'));
70
- };
71
-
72
- // Below is technically part of the Navigator's Locator extensions, we're putting it here for now
73
-
74
- // Reference: https://www.w3.org/TR/fragid-best-practices
75
- LocatorLocations.prototype.fragmentParameters = function(): Map<string, string> {
31
+ export function getFragmentParameters(loc: LocatorLocations): Map<string, string> {
76
32
  return new Map(
77
- this.fragments
78
- // Concatenates fragments together, after dropping any #
79
- .map(f => f.startsWith("#") ? f.slice(1) : f)
80
- .join("&")
81
- // Splits parameters
82
- .split("&")
83
- .filter(f => !f.startsWith("#"))
84
- .map(f => f.split("="))
85
- // Only keep named parameters
33
+ loc.fragments
34
+ .map(f => f.startsWith('#') ? f.slice(1) : f)
35
+ .join('&')
36
+ .split('&')
37
+ .filter(f => !f.startsWith('#'))
38
+ .map(f => f.split('='))
86
39
  .filter(f => f.length === 2)
87
- .map(f => [
88
- f[0].trim().toLowerCase(),
89
- f[1].trim()
90
- ])
40
+ .map(f => [f[0].trim().toLowerCase(), f[1].trim()])
91
41
  );
92
- };
42
+ }
93
43
 
94
- LocatorLocations.prototype.htmlId = function(): string | undefined {
44
+ export function getHtmlId(loc: LocatorLocations): string | undefined {
95
45
  /*
96
46
  The HTML 5 specification (used for WebPub) allows any character in an HTML ID, except spaces.
97
47
  This is an issue to differentiate with named parameters, so we ignore any ID containing `=`.
98
48
  */
99
- if(!this.fragments.length) return;
100
- let f = this.fragments.find(f => f.length && !f.includes("="));
101
- if(!f) {
102
- const fp = this.fragmentParameters();
103
- if(fp.has("id")) f = fp.get("id");
104
- else if(fp.has("name")) f = fp.get("name");
49
+ if (!loc.fragments.length) return;
50
+ let f = loc.fragments.find(f => f.length && !f.includes('='));
51
+ if (!f) {
52
+ const fp = getFragmentParameters(loc);
53
+ if (fp.has('id')) f = fp.get('id');
54
+ else if (fp.has('name')) f = fp.get('name');
105
55
  }
106
- return f?.startsWith("#") ? f.slice(1) : f;
107
- };
56
+ return f?.startsWith('#') ? f.slice(1) : f;
57
+ }
108
58
 
109
- LocatorLocations.prototype.page = function(): number | undefined {
110
- const i = parseInt(this.fragmentParameters().get("page")!);
111
- if(!isNaN(i) && i >= 0) return i;
59
+ export function getPage(loc: LocatorLocations): number | undefined {
60
+ const i = parseInt(getFragmentParameters(loc).get('page')!);
61
+ if (!isNaN(i) && i >= 0) return i;
112
62
  return undefined;
113
63
  }
114
64
 
115
- LocatorLocations.prototype.time = function(): number | undefined {
116
- const raw = this.fragmentParameters().get("t");
65
+ export function getTime(loc: LocatorLocations): number | undefined {
66
+ const raw = getFragmentParameters(loc).get('t');
117
67
  if (!raw) return undefined;
118
68
  return parseNptTime(raw);
119
69
  }
120
70
 
121
- LocatorLocations.prototype.space = function(): [number, number, number, number] | undefined {
122
- const fp = this.fragmentParameters();
123
- if(!fp.has("xywh")) return;
124
- // TODO more sophiticated parsing to handle the format
125
- const xywh = fp.get("xywh")!.split(",").map(s => parseInt(s));
126
- if(xywh.length !== 4) return; // Must have four parts
127
- if(xywh.some(isNaN)) return; // All parts must be numbers
128
- return xywh as [number, number, number, number];
71
+ export function getSpace(loc: LocatorLocations): { unit: "pixel" | "percent"; x: number; y: number; width: number; height: number } | undefined {
72
+ const fp = getFragmentParameters(loc);
73
+ if (!fp.has('xywh')) return;
74
+
75
+ const raw = fp.get('xywh')!;
76
+ let unit: "pixel" | "percent" = "pixel";
77
+ let coords = raw;
78
+
79
+ const normalizedRaw = raw.toLowerCase();
80
+ if (normalizedRaw.startsWith("pixel:")) {
81
+ coords = raw.slice(6);
82
+ } else if (normalizedRaw.startsWith("percent:")) {
83
+ unit = "percent";
84
+ coords = raw.slice(8);
85
+ }
86
+
87
+ const parse = unit === "percent" ? parseFloat : (s: string) => parseInt(s, 10);
88
+ const parts = coords.split(",").map(parse);
89
+ if (parts.length !== 4 || parts.some(isNaN)) return;
90
+
91
+ const [x, y, width, height] = parts;
92
+ return { unit, x, y, width, height };
129
93
  }