@readium/shared 2.2.2 → 2.3.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 (174) 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 -4972
  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 +26 -19
  106. package/src/locales/publication-metadata/ar.json +402 -0
  107. package/src/locales/publication-metadata/brh.json +1 -0
  108. package/src/locales/publication-metadata/da.json +310 -0
  109. package/src/locales/publication-metadata/el.json +310 -0
  110. package/src/locales/publication-metadata/en.json +310 -0
  111. package/src/locales/publication-metadata/es.json +333 -0
  112. package/src/locales/publication-metadata/et.json +310 -0
  113. package/src/locales/publication-metadata/fi.json +310 -0
  114. package/src/locales/publication-metadata/fr.json +333 -0
  115. package/src/locales/publication-metadata/he.json +9 -0
  116. package/src/locales/publication-metadata/it.json +333 -0
  117. package/src/locales/publication-metadata/lt.json +8 -0
  118. package/src/locales/publication-metadata/pl.json +333 -0
  119. package/src/locales/publication-metadata/pt_PT.json +329 -0
  120. package/src/locales/publication-metadata/sv.json +310 -0
  121. package/src/locales/publication-metadata/tr.json +51 -0
  122. package/src/locales/publication-metadata/uk.json +1 -0
  123. package/src/opds/Acquisition.ts +1 -1
  124. package/src/opds/Availability.ts +1 -1
  125. package/src/opds/Copies.ts +1 -1
  126. package/src/opds/Holds.ts +1 -1
  127. package/src/opds/Price.ts +1 -1
  128. package/src/publication/Link.ts +2 -6
  129. package/src/publication/Locator.ts +21 -3
  130. package/src/publication/Manifest.ts +5 -7
  131. package/src/publication/Publication.ts +2 -1
  132. package/src/publication/accessibility/Localization.ts +12 -14
  133. package/src/publication/accessibility/SupportedLanguages.ts +1 -1
  134. package/src/publication/encryption/Properties.ts +3 -15
  135. package/src/publication/epub/Metadata.ts +6 -12
  136. package/src/publication/epub/Properties.ts +3 -13
  137. package/src/publication/epub/Publication.ts +18 -39
  138. package/src/publication/html/Locations.ts +57 -104
  139. package/src/publication/opds/Properties.ts +22 -67
  140. package/src/publication/opds/Publication.ts +3 -9
  141. package/src/publication/services/content/iterators/HTMLResourceContentIterator.ts +3 -1
  142. package/src/publication/services/timeline/Timeline.ts +274 -65
  143. package/src/publication/services/timeline/TimelineItem.ts +3 -3
  144. package/src/publication/services/timeline/audio.ts +31 -0
  145. package/src/publication/services/timeline/html.ts +5 -0
  146. package/src/publication/services/timeline/index.ts +12 -0
  147. package/src/util/index.ts +1 -0
  148. package/src/util/npt.ts +70 -0
  149. package/types/src/opds/Acquisition.d.ts +1 -1
  150. package/types/src/opds/Availability.d.ts +1 -1
  151. package/types/src/opds/Copies.d.ts +1 -1
  152. package/types/src/opds/Holds.d.ts +1 -1
  153. package/types/src/opds/Price.d.ts +1 -1
  154. package/types/src/publication/encryption/Properties.d.ts +2 -9
  155. package/types/src/publication/epub/Metadata.d.ts +3 -6
  156. package/types/src/publication/epub/Properties.d.ts +2 -10
  157. package/types/src/publication/epub/Publication.d.ts +7 -18
  158. package/types/src/publication/html/Locations.d.ts +15 -44
  159. package/types/src/publication/opds/Properties.d.ts +8 -36
  160. package/types/src/publication/opds/Publication.d.ts +2 -5
  161. package/types/src/publication/services/timeline/Timeline.d.ts +80 -15
  162. package/types/src/publication/services/timeline/TimelineItem.d.ts +3 -3
  163. package/types/src/publication/services/timeline/audio.d.ts +4 -0
  164. package/types/src/publication/services/timeline/html.d.ts +4 -0
  165. package/types/src/publication/services/timeline/index.d.ts +6 -0
  166. package/types/src/util/index.d.ts +1 -0
  167. package/types/src/util/npt.d.ts +30 -0
  168. package/dist/ar-DyHX_uy2.js +0 -7
  169. package/dist/da-Dct0PS3E.js +0 -7
  170. package/dist/fr-C5HEel98.js +0 -7
  171. package/dist/index.umd.cjs +0 -3
  172. package/dist/it-DFOBoXGy.js +0 -7
  173. package/dist/pt_PT-Di3sVjze.js +0 -7
  174. 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
+ }
@@ -6,7 +6,7 @@
6
6
  /**
7
7
  * OPDS Acquisition Object.
8
8
  *
9
- * https://drafts.opds.io/schema/acquisition-object.schema.json
9
+ * https://specs.opds.io/schema/acquisition-object.schema.json
10
10
  */
11
11
  export class Acquisition {
12
12
  /** Currency for the price, eg. EUR. */
@@ -14,7 +14,7 @@ export enum AvailabilityStatus {
14
14
  /**
15
15
  * Indicated the availability of a given resource.
16
16
  *
17
- * https://drafts.opds.io/schema/properties.schema.json
17
+ * https://specs.opds.io/schema/properties.schema.json
18
18
  *
19
19
  */
20
20
  export class Availability {
@@ -8,7 +8,7 @@ import { positiveNumberfromJSON } from '../util/JSONParse.ts';
8
8
  /**
9
9
  * Library-specific feature that contains information about the copies that a library has acquired.
10
10
  *
11
- * https://drafts.opds.io/schema/properties.schema.json
11
+ * https://specs.opds.io/schema/properties.schema.json
12
12
  */
13
13
  export class Copies {
14
14
  public total?: number;
package/src/opds/Holds.ts CHANGED
@@ -8,7 +8,7 @@ import { positiveNumberfromJSON } from '../util/JSONParse.ts';
8
8
  /**
9
9
  * Library-specific features when a specific book is unavailable but provides a hold list.
10
10
  *
11
- * https://drafts.opds.io/schema/properties.schema.json
11
+ * https://specs.opds.io/schema/properties.schema.json
12
12
  */
13
13
  export class Holds {
14
14
  public total?: number;
package/src/opds/Price.ts CHANGED
@@ -8,7 +8,7 @@ import { positiveNumberfromJSON } from '../util/JSONParse.ts';
8
8
  /**
9
9
  * The price of a publication in an OPDS link.
10
10
  *
11
- * https://drafts.opds.io/schema/properties.schema.json
11
+ * https://specs.opds.io/schema/properties.schema.json
12
12
  *
13
13
  * currency Currency for the price, eg. EUR.
14
14
  * value Price value, should only be used for display purposes, because of precision issues
@@ -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
 
@@ -145,21 +145,19 @@ export class Manifest {
145
145
  * Returns null if the resource is not found in this manifest.
146
146
  */
147
147
  public locatorFromLink(link: Link): Locator | undefined {
148
- const components = link.href.split("#");
149
- const href = components.length == 2 ? components[0] : link.href;
150
- const resourceLink = this.linkWithHref(href);
148
+ const bare = link.href.split("#")[0];
149
+ const resourceLink = this.linkWithHref(bare);
151
150
  if(!resourceLink) return undefined;
152
151
  const type = resourceLink.type;
153
152
  if(!type) return undefined;
154
- const fragment = components.length == 2 ? components[1] : undefined;
153
+ const hasFragment = link.href.includes("#");
155
154
 
156
155
  return new Locator({
157
- href,
156
+ href: link.href,
158
157
  type,
159
158
  title: resourceLink.title ?? link.title,
160
159
  locations: new LocatorLocations({
161
- fragments: fragment ? [fragment] : undefined,
162
- progression: fragment ? undefined : 0.0,
160
+ progression: hasFragment ? undefined : 0.0,
163
161
  })
164
162
  });
165
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,82 @@
1
1
  import { LocatorLocations } from '../Locator.ts';
2
2
  import { DomRange } from './DomRange.ts';
3
+ import { parseNptTime } from '../../util/npt.ts';
3
4
 
4
- // HTML extensions for [Locations].
5
+ // HTML extensions for LocatorLocations.
5
6
  // https://github.com/readium/architecture/blob/master/models/locators/extensions/html.md
6
7
 
7
- declare module '../Locator' {
8
- export interface LocatorLocations {
9
- /**
10
- * A CSS Selector.
11
- */
12
- getCssSelector(): string | undefined;
13
-
14
- /**
15
- * [partialCfi] is an expression conforming to the "right-hand" side of the EPUB CFI syntax, that is
16
- * to say: without the EPUB-specific OPF spine item reference that precedes the first ! exclamation
17
- * mark (which denotes the "step indirection" into a publication document). Note that the wrapping
18
- * epubcfi(***) syntax is not used for the [partialCfi] string, i.e. the "fragment" part of the CFI
19
- * grammar is ignored.
20
- */
21
- getPartialCfi(): string | undefined;
22
-
23
- /**
24
- * An HTML DOM range.
25
- */
26
- getDomRange(): DomRange | undefined;
27
-
28
- /**
29
- * All named parameters found in the fragments, such as `p=5`.
30
- */
31
- fragmentParameters(): Map<string, string>;
32
-
33
- /**
34
- * HTML ID fragment identifier.
35
- */
36
- htmlId(): string | undefined;
37
-
38
- /**
39
- * Page fragment identifier, used for example in PDF.
40
- */
41
- page(): number | undefined;
42
-
43
- /**
44
- * Temporal Dimension media fragment, used for example in audiobooks.
45
- *
46
- * https://www.w3.org/TR/media-frags/
47
- */
48
- time(): number | undefined;
49
-
50
- /**
51
- * Spatial Dimension media fragment, used for example in audiobooks.
52
- *
53
- * https://www.w3.org/TR/media-frags/
54
- */
55
- space(): [number, number, number, number] | undefined;
56
- }
8
+ export function getCssSelector(loc: LocatorLocations): string | undefined {
9
+ return loc.otherLocations?.get('cssSelector');
57
10
  }
58
11
 
59
- LocatorLocations.prototype.getCssSelector = function(): string | undefined {
60
- return this.otherLocations?.get('cssSelector');
61
- };
62
-
63
- LocatorLocations.prototype.getPartialCfi = function(): string | undefined {
64
- return this.otherLocations?.get('partialCfi');
65
- };
66
-
67
- LocatorLocations.prototype.getDomRange = function(): DomRange | undefined {
68
- return DomRange.deserialize(this.otherLocations?.get('domRange'));
69
- };
12
+ export function getPartialCfi(loc: LocatorLocations): string | undefined {
13
+ return loc.otherLocations?.get('partialCfi');
14
+ }
70
15
 
71
- // Below is technically part of the Navigator's Locator extensions, we're putting it here for now
16
+ export function getDomRange(loc: LocatorLocations): DomRange | undefined {
17
+ return DomRange.deserialize(loc.otherLocations?.get('domRange'));
18
+ }
72
19
 
73
- // Reference: https://www.w3.org/TR/fragid-best-practices
74
- LocatorLocations.prototype.fragmentParameters = function(): Map<string, string> {
20
+ export function getFragmentParameters(loc: LocatorLocations): Map<string, string> {
75
21
  return new Map(
76
- this.fragments
77
- // Concatenates fragments together, after dropping any #
78
- .map(f => f.startsWith("#") ? f.slice(1) : f)
79
- .join("&")
80
- // Splits parameters
81
- .split("&")
82
- .filter(f => !f.startsWith("#"))
83
- .map(f => f.split("="))
84
- // Only keep named parameters
22
+ loc.fragments
23
+ .map(f => f.startsWith('#') ? f.slice(1) : f)
24
+ .join('&')
25
+ .split('&')
26
+ .filter(f => !f.startsWith('#'))
27
+ .map(f => f.split('='))
85
28
  .filter(f => f.length === 2)
86
- .map(f => [
87
- f[0].trim().toLowerCase(),
88
- f[1].trim()
89
- ])
29
+ .map(f => [f[0].trim().toLowerCase(), f[1].trim()])
90
30
  );
91
- };
31
+ }
92
32
 
93
- LocatorLocations.prototype.htmlId = function(): string | undefined {
33
+ export function getHtmlId(loc: LocatorLocations): string | undefined {
94
34
  /*
95
35
  The HTML 5 specification (used for WebPub) allows any character in an HTML ID, except spaces.
96
36
  This is an issue to differentiate with named parameters, so we ignore any ID containing `=`.
97
37
  */
98
- if(!this.fragments.length) return;
99
- let f = this.fragments.find(f => f.length && !f.includes("="));
100
- if(!f) {
101
- const fp = this.fragmentParameters();
102
- if(fp.has("id")) f = fp.get("id");
103
- else if(fp.has("name")) f = fp.get("name");
38
+ if (!loc.fragments.length) return;
39
+ let f = loc.fragments.find(f => f.length && !f.includes('='));
40
+ if (!f) {
41
+ const fp = getFragmentParameters(loc);
42
+ if (fp.has('id')) f = fp.get('id');
43
+ else if (fp.has('name')) f = fp.get('name');
104
44
  }
105
- return f?.startsWith("#") ? f.slice(1) : f;
106
- };
45
+ return f?.startsWith('#') ? f.slice(1) : f;
46
+ }
107
47
 
108
- LocatorLocations.prototype.page = function(): number | undefined {
109
- const i = parseInt(this.fragmentParameters().get("page")!);
110
- if(!isNaN(i) && i >= 0) return i;
48
+ export function getPage(loc: LocatorLocations): number | undefined {
49
+ const i = parseInt(getFragmentParameters(loc).get('page')!);
50
+ if (!isNaN(i) && i >= 0) return i;
111
51
  return undefined;
112
52
  }
113
53
 
114
- LocatorLocations.prototype.time = function(): number | undefined {
115
- // TODO more sophiticated parsing
116
- const i = parseInt(this.fragmentParameters().get("t")!);
117
- if(!isNaN(i)) return i;
118
- return undefined;
54
+ export function getTime(loc: LocatorLocations): number | undefined {
55
+ const raw = getFragmentParameters(loc).get('t');
56
+ if (!raw) return undefined;
57
+ return parseNptTime(raw);
119
58
  }
120
59
 
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];
60
+ export function getSpace(loc: LocatorLocations): { unit: "pixel" | "percent"; x: number; y: number; width: number; height: number } | undefined {
61
+ const fp = getFragmentParameters(loc);
62
+ if (!fp.has('xywh')) return;
63
+
64
+ const raw = fp.get('xywh')!;
65
+ let unit: "pixel" | "percent" = "pixel";
66
+ let coords = raw;
67
+
68
+ const normalizedRaw = raw.toLowerCase();
69
+ if (normalizedRaw.startsWith("pixel:")) {
70
+ coords = raw.slice(6);
71
+ } else if (normalizedRaw.startsWith("percent:")) {
72
+ unit = "percent";
73
+ coords = raw.slice(8);
74
+ }
75
+
76
+ const parse = unit === "percent" ? parseFloat : (s: string) => parseInt(s, 10);
77
+ const parts = coords.split(",").map(parse);
78
+ if (parts.length !== 4 || parts.some(isNaN)) return;
79
+
80
+ const [x, y, width, height] = parts;
81
+ return { unit, x, y, width, height };
129
82
  }