@readium/shared 2.2.1 → 2.2.3

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@readium/shared",
3
- "version": "2.2.1",
3
+ "version": "2.2.3",
4
4
  "type": "module",
5
5
  "description": "Shared models to be used across other Readium projects and implementations in Typescript",
6
6
  "author": "readium",
@@ -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
@@ -14,8 +14,6 @@ import { GuidedNavigationDocument } from "./GuidedNavigation.ts";
14
14
  import { MediaType, URITemplate } from "../util/index.ts";
15
15
  import { Timeline } from './services/timeline/Timeline.ts';
16
16
 
17
- export type ServiceFactory = () => null;
18
-
19
17
  /** Shared model for a Readium Publication. */
20
18
  export class Publication {
21
19
  /** The manifest holding the publication metadata extracted from the publication file */
@@ -1,5 +1,6 @@
1
1
  import { LocatorLocations } from '../Locator.ts';
2
2
  import { DomRange } from './DomRange.ts';
3
+ import { parseNptTime } from '../../util/npt.ts';
3
4
 
4
5
  // HTML extensions for [Locations].
5
6
  // https://github.com/readium/architecture/blob/master/models/locators/extensions/html.md
@@ -112,10 +113,9 @@ LocatorLocations.prototype.page = function(): number | undefined {
112
113
  }
113
114
 
114
115
  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;
116
+ const raw = this.fragmentParameters().get("t");
117
+ if (!raw) return undefined;
118
+ return parseNptTime(raw);
119
119
  }
120
120
 
121
121
  LocatorLocations.prototype.space = function(): [number, number, number, number] | undefined {
@@ -4,7 +4,7 @@ import { Link } from '../Link.ts';
4
4
  import { Properties } from '../Properties.ts';
5
5
 
6
6
  // OPDS extensions for link [Properties].
7
- // https://drafts.opds.io/schema/properties.schema.json
7
+ // https://specs.opds.io/schema/properties.schema.json
8
8
 
9
9
  declare module '../Properties' {
10
10
  export interface Properties {
@@ -43,7 +43,7 @@ declare module '../Properties' {
43
43
  * Indicates that the linked resource supports authentication with the associated Authentication
44
44
  * Document.
45
45
  *
46
- * See https://drafts.opds.io/authentication-for-opds-1.0.html
46
+ * See https://specs.opds.io/authentication-for-opds-1.0.html
47
47
  */
48
48
  getAuthenticate(): Link | undefined;
49
49
  }
@@ -1,6 +1,7 @@
1
1
  import { Link, Links } from "../../Link.ts";
2
2
  import { Locator } from "../../Locator.ts";
3
3
  import { TimelineItem } from "./TimelineItem.ts";
4
+ import { isNptStartOfResource, parseNptTime } from "../../../util/npt.ts";
4
5
 
5
6
  interface PublicationLike {
6
7
  toc?: Links;
@@ -271,15 +272,14 @@ export class Timeline {
271
272
 
272
273
  /**
273
274
  * A TOC href points to the start of its resource when it has no fragment,
274
- * or when the fragment contains a parsable `t=` value of 0 (audio: explicit
275
- * beginning of the file). Accepts decimals and extra params, e.g. `t=0.0`
276
- * or `foo=bar&t=0`.
275
+ * or when the fragment contains a parsable NPT `t=` value of 0 (audio:
276
+ * explicit beginning of the file).
277
277
  */
278
278
  private static isStartOfResource(href: string): boolean {
279
279
  const fragment = href.split("#")[1];
280
280
  if (!fragment) return true;
281
- const match = fragment.match(/(?:^|&)t=(\d+(?:\.\d+)?)/);
282
- return match !== null && parseFloat(match[1]) === 0;
281
+ const match = fragment.match(/(?:^|&)t=([^&]+)/);
282
+ return match !== null && isNptStartOfResource(match[1]);
283
283
  }
284
284
 
285
285
  // -------------------------------------------------------------------------
@@ -322,8 +322,8 @@ export class Timeline {
322
322
  const effectiveHref = refHref || this.bareHrefFromItem(item);
323
323
  if (effectiveHref !== href) continue;
324
324
  if (!refFragment) return undefined;
325
- const match = refFragment.match(/(?:^|&)t=(\d+(?:\.\d+)?)/);
326
- return match ? parseFloat(match[1]) : undefined;
325
+ const match = refFragment.match(/(?:^|&)t=([^&]+)/);
326
+ return match ? parseNptTime(match[1]) : undefined;
327
327
  }
328
328
  return undefined;
329
329
  }
@@ -337,8 +337,8 @@ export class Timeline {
337
337
  if (!ref) return undefined;
338
338
  const fragment = ref.split("#")[1];
339
339
  if (!fragment) return undefined;
340
- const match = fragment.match(/(?:^|&)t=(\d+(?:\.\d+)?)/);
341
- return match ? parseFloat(match[1]) : undefined;
340
+ const match = fragment.match(/(?:^|&)t=([^&]+)/);
341
+ return match ? parseNptTime(match[1]) : undefined;
342
342
  }
343
343
 
344
344
  private ancestorPath(items: TimelineItem[], target: TimelineItem): TimelineItem[] | null {
package/src/util/index.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  export * from './mediatype/index.ts';
2
2
  export * from './JSONParse.ts';
3
+ export * from './npt.ts';
3
4
  export * from './URITemplate.ts';
4
5
  export * from './Language.ts';
5
6
  export * from './tokenizer/index.ts';
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Parses a W3C Media Fragments NPT (Normal Play Time) temporal value and
3
+ * returns the corresponding time in seconds.
4
+ *
5
+ * Accepts the start of a range expression (e.g. "10,20" → 10).
6
+ * Handles the optional "npt:" prefix and all three clock formats:
7
+ * - Seconds: "1647.202" or "npt:1647.202"
8
+ * - MM:SS: "27:27.2" or "npt:27:27.2"
9
+ * - HH:MM:SS: "0:27:27.2" or "npt:0:27:27.202"
10
+ *
11
+ * Returns `undefined` for any value that cannot be parsed.
12
+ *
13
+ * https://www.w3.org/TR/media-frags/#naming-time
14
+ */
15
+ export function parseNptTime(raw: string): number | undefined {
16
+ const start = raw.split(",")[0].trim();
17
+ const normalizedStart = start.toLowerCase();
18
+ const s = normalizedStart.startsWith("npt:") ? start.slice(4) : start;
19
+ const parts = s.split(":");
20
+
21
+ if (parts.length === 1) {
22
+ const sec = parseFloat(parts[0]);
23
+ return isNaN(sec) ? undefined : sec;
24
+ }
25
+
26
+ if (parts.length === 2) {
27
+ const min = parseInt(parts[0], 10);
28
+ const sec = parseFloat(parts[1]);
29
+ if (isNaN(min) || isNaN(sec)) return undefined;
30
+ return min * 60 + sec;
31
+ }
32
+
33
+ if (parts.length === 3) {
34
+ const hr = parseInt(parts[0], 10);
35
+ const min = parseInt(parts[1], 10);
36
+ const sec = parseFloat(parts[2]);
37
+ if (isNaN(hr) || isNaN(min) || isNaN(sec)) return undefined;
38
+ return hr * 3600 + min * 60 + sec;
39
+ }
40
+
41
+ return undefined;
42
+ }
43
+
44
+ /**
45
+ * Returns true when the NPT time value represents the start of a resource
46
+ * (t=0, t=0.0, t=npt:0, t=npt:0:0:0, etc.).
47
+ */
48
+ export function isNptStartOfResource(raw: string): boolean {
49
+ const t = parseNptTime(raw);
50
+ return t !== undefined && t === 0;
51
+ }
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * OPDS Acquisition Object.
3
3
  *
4
- * https://drafts.opds.io/schema/acquisition-object.schema.json
4
+ * https://specs.opds.io/schema/acquisition-object.schema.json
5
5
  */
6
6
  export declare class Acquisition {
7
7
  /** Currency for the price, eg. EUR. */
@@ -6,7 +6,7 @@ export declare enum AvailabilityStatus {
6
6
  /**
7
7
  * Indicated the availability of a given resource.
8
8
  *
9
- * https://drafts.opds.io/schema/properties.schema.json
9
+ * https://specs.opds.io/schema/properties.schema.json
10
10
  *
11
11
  */
12
12
  export declare class Availability {
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Library-specific feature that contains information about the copies that a library has acquired.
3
3
  *
4
- * https://drafts.opds.io/schema/properties.schema.json
4
+ * https://specs.opds.io/schema/properties.schema.json
5
5
  */
6
6
  export declare class Copies {
7
7
  total?: number;
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Library-specific features when a specific book is unavailable but provides a hold list.
3
3
  *
4
- * https://drafts.opds.io/schema/properties.schema.json
4
+ * https://specs.opds.io/schema/properties.schema.json
5
5
  */
6
6
  export declare class Holds {
7
7
  total?: number;
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * The price of a publication in an OPDS link.
3
3
  *
4
- * https://drafts.opds.io/schema/properties.schema.json
4
+ * https://specs.opds.io/schema/properties.schema.json
5
5
  *
6
6
  * currency Currency for the price, eg. EUR.
7
7
  * value Price value, should only be used for display purposes, because of precision issues
@@ -7,7 +7,6 @@ import { PublicationCollection } from './PublicationCollection.ts';
7
7
  import { Resource } from '../fetcher/Resource.ts';
8
8
  import { GuidedNavigationDocument } from "./GuidedNavigation.ts";
9
9
  import { Timeline } from './services/timeline/Timeline.ts';
10
- export type ServiceFactory = () => null;
11
10
  /** Shared model for a Readium Publication. */
12
11
  export declare class Publication {
13
12
  /** The manifest holding the publication metadata extracted from the publication file */
@@ -31,7 +31,7 @@ declare module '../Properties' {
31
31
  * Indicates that the linked resource supports authentication with the associated Authentication
32
32
  * Document.
33
33
  *
34
- * See https://drafts.opds.io/authentication-for-opds-1.0.html
34
+ * See https://specs.opds.io/authentication-for-opds-1.0.html
35
35
  */
36
36
  getAuthenticate(): Link | undefined;
37
37
  }
@@ -76,9 +76,8 @@ export declare class Timeline {
76
76
  private static collectTocCandidates;
77
77
  /**
78
78
  * A TOC href points to the start of its resource when it has no fragment,
79
- * or when the fragment contains a parsable `t=` value of 0 (audio: explicit
80
- * beginning of the file). Accepts decimals and extra params, e.g. `t=0.0`
81
- * or `foo=bar&t=0`.
79
+ * or when the fragment contains a parsable NPT `t=` value of 0 (audio:
80
+ * explicit beginning of the file).
82
81
  */
83
82
  private static isStartOfResource;
84
83
  private static trimToDepth;
@@ -1,5 +1,6 @@
1
1
  export * from './mediatype/index.ts';
2
2
  export * from './JSONParse.ts';
3
+ export * from './npt.ts';
3
4
  export * from './URITemplate.ts';
4
5
  export * from './Language.ts';
5
6
  export * from './tokenizer/index.ts';
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Parses a W3C Media Fragments NPT (Normal Play Time) temporal value and
3
+ * returns the corresponding time in seconds.
4
+ *
5
+ * Accepts the start of a range expression (e.g. "10,20" → 10).
6
+ * Handles the optional "npt:" prefix and all three clock formats:
7
+ * - Seconds: "1647.202" or "npt:1647.202"
8
+ * - MM:SS: "27:27.2" or "npt:27:27.2"
9
+ * - HH:MM:SS: "0:27:27.2" or "npt:0:27:27.202"
10
+ *
11
+ * Returns `undefined` for any value that cannot be parsed.
12
+ *
13
+ * https://www.w3.org/TR/media-frags/#naming-time
14
+ */
15
+ export declare function parseNptTime(raw: string): number | undefined;
16
+ /**
17
+ * Returns true when the NPT time value represents the start of a resource
18
+ * (t=0, t=0.0, t=npt:0, t=npt:0:0:0, etc.).
19
+ */
20
+ export declare function isNptStartOfResource(raw: string): boolean;