cozy-iiif 0.2.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +13 -7
- package/dist/core/manifest.d.ts +2 -2
- package/dist/index.js +127 -119
- package/dist/types.d.ts +11 -4
- package/package.json +1 -1
- package/src/core/manifest.ts +45 -8
- package/src/types.ts +29 -6
package/README.md
CHANGED
@@ -7,7 +7,7 @@ A developer-friendly API for working with IIIF resources. Built on top of the II
|
|
7
7
|
- Resource identification for any URL: IIIF collection and presentation manifests, image services, static image, and more.
|
8
8
|
- Developer-friendly TypeScript API for parsing and working with IIIF resources.
|
9
9
|
- Seamless upgrade from IIIF Presentation API v2 to v3 (using `@iiif/parser` under the hood).
|
10
|
-
- Preserves access to underlying `@iiif-
|
10
|
+
- Preserves access to underlying `@iiif/presentation-3` types.
|
11
11
|
- Helpers for stitching thumbnails and cropping regions from IIIF Level 0 tilesets.
|
12
12
|
- Helpers for adding annotations to Canvases and Presentation manifests.
|
13
13
|
|
@@ -69,12 +69,15 @@ console.log(manifest.getLabel('de'));
|
|
69
69
|
|
70
70
|
// Metadata as normalized CozyMetada[]
|
71
71
|
console.log(manifest.getMetadata());
|
72
|
+
|
73
|
+
// The raw source data, @iiif/presentation-3 typed
|
74
|
+
console.log(manifest.source);
|
72
75
|
```
|
73
76
|
|
74
77
|
### Thumbnail Helper
|
75
78
|
|
76
79
|
CozyCanvas has a simple helper for getting a Thumbnail URL. The URL
|
77
|
-
will use the `thumbnail` property if available, or the image service
|
80
|
+
will use the `thumbnail` property of the original resource if available, or the image service
|
78
81
|
otherwise.
|
79
82
|
|
80
83
|
```ts
|
@@ -94,19 +97,19 @@ based on the manifest's `structures` property.
|
|
94
97
|
|
95
98
|
```ts
|
96
99
|
// Returns a list of CozyTOCNode objects.
|
97
|
-
const
|
100
|
+
const toc = manifest.getTableOfContents();
|
98
101
|
|
99
102
|
const logTOCNode = (node: CozyTOCNode) => {
|
100
103
|
console.log(node.getLabel());
|
101
104
|
node.children.forEach(logTOCNode);
|
102
105
|
}
|
103
106
|
|
104
|
-
root.forEach(logTOCNode);
|
107
|
+
root.forEach(logTOCNode.root);
|
105
108
|
```
|
106
109
|
|
107
|
-
###
|
110
|
+
### Image Types and Levels
|
108
111
|
|
109
|
-
The **CozyImageResource**
|
112
|
+
The **CozyImageResource** provides a helper properties that identify the type and level of
|
110
113
|
an image.
|
111
114
|
|
112
115
|
```ts
|
@@ -204,8 +207,11 @@ const annotations: Annotation[] = [{
|
|
204
207
|
|
205
208
|
// Generates a new CozyManifest with annotations from an original CozyManifest.
|
206
209
|
const updated = importAnnotations(original, annotations);
|
210
|
+
|
211
|
+
// The source field has the raw manifest JSON (annotations included!)
|
212
|
+
console.log(updated.source);
|
207
213
|
```
|
208
214
|
|
209
215
|
## License
|
210
216
|
|
211
|
-
MIT License - see the [LICENSE](LICENSE) file for details.
|
217
|
+
MIT License - see the [LICENSE](LICENSE) file for details.
|
package/dist/core/manifest.d.ts
CHANGED
@@ -1,2 +1,2 @@
|
|
1
|
-
import { CozyRange,
|
2
|
-
export declare const getTableOfContents: (ranges: CozyRange[]) => () =>
|
1
|
+
import { CozyRange, CozyTOC } from '../types';
|
2
|
+
export declare const getTableOfContents: (ranges: CozyRange[]) => () => CozyTOC;
|
package/dist/index.js
CHANGED
@@ -1,14 +1,14 @@
|
|
1
|
-
import { g as
|
1
|
+
import { g as h, a as $, b as w } from "./resource-DS2brz47.js";
|
2
2
|
import { c as Ft } from "./resource-DS2brz47.js";
|
3
3
|
var ce = "http://library.stanford.edu/iiif/image-api/compliance.html#level0", le = "http://library.stanford.edu/iiif/image-api/compliance.html#level1", V = "http://library.stanford.edu/iiif/image-api/compliance.html#level2", pe = "http://library.stanford.edu/iiif/image-api/conformance.html#level0", ve = "http://library.stanford.edu/iiif/image-api/conformance.html#level1", F = "http://library.stanford.edu/iiif/image-api/conformance.html#level2", he = "http://library.stanford.edu/iiif/image-api/1.1/compliance.html#level0", ue = "http://library.stanford.edu/iiif/image-api/1.1/compliance.html#level1", W = "http://library.stanford.edu/iiif/image-api/1.1/compliance.html#level2", fe = "http://library.stanford.edu/iiif/image-api/1.1/conformance.html#level0", me = "http://library.stanford.edu/iiif/image-api/1.1/conformance.html#level1", B = "http://library.stanford.edu/iiif/image-api/1.1/conformance.html#level2", ge = "http://iiif.io/api/image/1/level0.json", de = "http://iiif.io/api/image/1/profiles/level0.json", ye = "http://iiif.io/api/image/1/level1.json", Ae = "http://iiif.io/api/image/1/profiles/level1.json", H = "http://iiif.io/api/image/1/level2.json", J = "http://iiif.io/api/image/1/profiles/level2.json", Ce = "http://iiif.io/api/image/2/level0.json", be = "http://iiif.io/api/image/2/profiles/level0.json", Re = "http://iiif.io/api/image/2/level1.json", Le = "http://iiif.io/api/image/2/profiles/level1.json", G = "http://iiif.io/api/image/2/level2.json", z = "http://iiif.io/api/image/2/profiles/level2.json", we = "level0", Ie = "level1", K = "level2", Se = "http://iiif.io/api/image/2/level0", Te = "http://iiif.io/api/image/2/level1", Q = "http://iiif.io/api/image/2/level2", xe = [Q, V, F, W, B, H, J, G, z, K], $e = [Se, Te, Q, ce, le, V, pe, ve, F, he, ue, W, fe, me, B, ge, de, ye, Ae, H, J, Ce, be, Re, Le, G, z, we, Ie, K], Me = $e;
|
4
|
-
function
|
4
|
+
function u(t) {
|
5
5
|
for (let e in t) (typeof t[e] > "u" || t[e] === null) && delete t[e];
|
6
6
|
return t;
|
7
7
|
}
|
8
8
|
function b(t) {
|
9
9
|
return Array.isArray(t) ? t : t ? [t] : [];
|
10
10
|
}
|
11
|
-
var je = Object.defineProperty, ke = (t, e, r) => e in t ? je(t, e, { enumerable: !0, configurable: !0, writable: !0, value: r }) : t[e] = r,
|
11
|
+
var je = Object.defineProperty, ke = (t, e, r) => e in t ? je(t, e, { enumerable: !0, configurable: !0, writable: !0, value: r }) : t[e] = r, A = (t, e, r) => (ke(t, typeof e != "symbol" ? e + "" : e, r), r), U = ["sc:Collection", "sc:Manifest", "sc:Canvas", "sc:AnnotationList", "oa:Annotation", "sc:Range", "sc:Layer", "sc:Sequence", "oa:Choice", "Service", "ContentResource"];
|
12
12
|
function Pe(t) {
|
13
13
|
if (typeof t > "u" || t === null) throw new Error("Null or undefined is not a valid entity.");
|
14
14
|
if (Array.isArray(t)) throw new Error("Array is not a valid entity");
|
@@ -23,7 +23,7 @@ function Pe(t) {
|
|
23
23
|
}
|
24
24
|
var Oe = class X {
|
25
25
|
constructor(e, r = {}) {
|
26
|
-
|
26
|
+
A(this, "traversals"), A(this, "options"), this.traversals = { collection: [], manifest: [], canvas: [], annotationList: [], sequence: [], annotation: [], contentResource: [], choice: [], range: [], service: [], layer: [], ...e }, this.options = { convertPropsToArray: !0, mergeMemberProperties: !0, allowUndefinedReturn: !1, ...r };
|
27
27
|
}
|
28
28
|
static all(e) {
|
29
29
|
return new X({ collection: [e], manifest: [e], canvas: [e], annotationList: [e], sequence: [e], annotation: [e], contentResource: [e], choice: [e], range: [e], service: [e], layer: [e] });
|
@@ -152,7 +152,7 @@ var Oe = class X {
|
|
152
152
|
return typeof n > "u" && !this.options.allowUndefinedReturn ? i : n;
|
153
153
|
}, e);
|
154
154
|
}
|
155
|
-
}, Ue = "http://library.stanford.edu/iiif/image-api/compliance.html#level1", De = "http://library.stanford.edu/iiif/image-api/compliance.html#level2", Ee = "http://library.stanford.edu/iiif/image-api/conformance.html#level1", Ne = "http://library.stanford.edu/iiif/image-api/conformance.html#level2", qe = "http://library.stanford.edu/iiif/image-api/1.1/compliance.html#level1", _e = "http://library.stanford.edu/iiif/image-api/1.1/compliance.html#level2", Ve = "http://library.stanford.edu/iiif/image-api/1.1/conformance.html#level1", Fe = "http://library.stanford.edu/iiif/image-api/1.1/conformance.html#level2", We = "http://iiif.io/api/image/1/level1.json", Be = "http://iiif.io/api/image/1/profiles/level1.json", He = "http://iiif.io/api/image/1/level2.json", Je = "http://iiif.io/api/image/1/profiles/level2.json", Ge = "http://iiif.io/api/image/2/level1.json", ze = "http://iiif.io/api/image/2/profiles/level1.json", Ke = "http://iiif.io/api/image/2/level2.json", Qe = "http://iiif.io/api/image/2/profiles/level2.json", Xe = "level1", Ye = "level2", Ze = "http://iiif.io/api/image/2/level1", et = "http://iiif.io/api/image/2/level2", tt = [Ze, et, Ue, De, Ee, Ne, qe, _e, Ve, Fe, We, Be, He, Je, Ge, ze, Ke, Qe, Xe, Ye],
|
155
|
+
}, Ue = "http://library.stanford.edu/iiif/image-api/compliance.html#level1", De = "http://library.stanford.edu/iiif/image-api/compliance.html#level2", Ee = "http://library.stanford.edu/iiif/image-api/conformance.html#level1", Ne = "http://library.stanford.edu/iiif/image-api/conformance.html#level2", qe = "http://library.stanford.edu/iiif/image-api/1.1/compliance.html#level1", _e = "http://library.stanford.edu/iiif/image-api/1.1/compliance.html#level2", Ve = "http://library.stanford.edu/iiif/image-api/1.1/conformance.html#level1", Fe = "http://library.stanford.edu/iiif/image-api/1.1/conformance.html#level2", We = "http://iiif.io/api/image/1/level1.json", Be = "http://iiif.io/api/image/1/profiles/level1.json", He = "http://iiif.io/api/image/1/level2.json", Je = "http://iiif.io/api/image/1/profiles/level2.json", Ge = "http://iiif.io/api/image/2/level1.json", ze = "http://iiif.io/api/image/2/profiles/level1.json", Ke = "http://iiif.io/api/image/2/level2.json", Qe = "http://iiif.io/api/image/2/profiles/level2.json", Xe = "level1", Ye = "level2", Ze = "http://iiif.io/api/image/2/level1", et = "http://iiif.io/api/image/2/level2", tt = [Ze, et, Ue, De, Ee, Ne, qe, _e, Ve, Fe, We, Be, He, Je, Ge, ze, Ke, Qe, Xe, Ye], M = { attributionLabel: "Attribution", providerId: "http://example.org/provider", providerName: "Unknown" };
|
156
156
|
function rt(t) {
|
157
157
|
if (typeof t == "string") return [t];
|
158
158
|
if (!t) return [];
|
@@ -237,7 +237,7 @@ function D(t) {
|
|
237
237
|
return t;
|
238
238
|
}
|
239
239
|
var nt = ["Collection", "Manifest", "Annotation", "AnnotationPage", "Range", "Service"];
|
240
|
-
function
|
240
|
+
function k(t) {
|
241
241
|
let e = t["@id"] || t.id, r = t["@type"] || t.type, i = t.profile || void 0, s = t["@context"] || void 0;
|
242
242
|
if (i) {
|
243
243
|
let n = st(i);
|
@@ -282,12 +282,12 @@ function ot(t) {
|
|
282
282
|
function ct(t, e = "Rights/License", r = "none") {
|
283
283
|
let i = null, s = [], n = Array.isArray(t) ? t : [t];
|
284
284
|
for (let a of n) {
|
285
|
-
let
|
286
|
-
if (
|
287
|
-
|
285
|
+
let c = a ? ot(a) : void 0;
|
286
|
+
if (c && (c.indexOf("creativecommons.org") !== -1 || c.indexOf("rightsstatements.org") !== -1)) {
|
287
|
+
c.startsWith("https://") ? i = `http://${c.slice(8)}` : i = c;
|
288
288
|
continue;
|
289
289
|
}
|
290
|
-
|
290
|
+
c && s.push({ label: { [r]: [e] }, value: { [r]: [c] } });
|
291
291
|
}
|
292
292
|
return [i, s];
|
293
293
|
}
|
@@ -307,15 +307,15 @@ function Z(t, e) {
|
|
307
307
|
let r = encodeURI(t.id || t["@id"] || "").trim();
|
308
308
|
return r && e ? `${r}/${e}` : r || (E++, `http://example.org/${t["@type"]}${e ? `/${e}` : ""}/${E}`);
|
309
309
|
}
|
310
|
-
function
|
310
|
+
function d(t) {
|
311
311
|
let e = [...t.behavior || []];
|
312
312
|
t.viewingHint && e.push(t.viewingHint);
|
313
313
|
let r;
|
314
|
-
return Array.isArray(t.motivation) ? r = t.motivation.map(D) : t.motivation && (r = D(t.motivation)), { "@context": t["@context"] ? pt(t["@context"]) : void 0, id: (t["@id"] || Z(t)).trim(), type:
|
314
|
+
return Array.isArray(t.motivation) ? r = t.motivation.map(D) : t.motivation && (r = D(t.motivation)), { "@context": t["@context"] ? pt(t["@context"]) : void 0, id: (t["@id"] || Z(t)).trim(), type: k(t), behavior: e.length ? e : void 0, height: t.height ? t.height : void 0, width: t.width ? t.width : void 0, motivation: r, viewingDirection: t.viewingDirection, profile: t.profile, format: t.format ? t.format : void 0, duration: void 0, timeMode: void 0 };
|
315
315
|
}
|
316
|
-
function
|
316
|
+
function y(t) {
|
317
317
|
let [e, r] = ct(t.license), i = [...t.metadata ? vt(t.metadata) : [], ...r];
|
318
|
-
return { rights: e, metadata: i.length ? i : void 0, label: t.label ? R(t.label) : void 0, requiredStatement: t.attribution ? { label: R(
|
318
|
+
return { rights: e, metadata: i.length ? i : void 0, label: t.label ? R(t.label) : void 0, requiredStatement: t.attribution ? { label: R(M.attributionLabel), value: R(t.attribution) } : void 0, navDate: t.navDate, summary: t.description ? R(t.description) : void 0, thumbnail: ht(t.thumbnail) };
|
319
319
|
}
|
320
320
|
function ht(t) {
|
321
321
|
return t && (Array.isArray(t) ? t : [t]).map((e) => typeof e == "string" ? { id: e, type: "Image" } : (e.type === "unknown" && (e.type = "Image"), e));
|
@@ -329,24 +329,24 @@ function ut(t) {
|
|
329
329
|
r.push({ id: i, type: "Collection" });
|
330
330
|
break;
|
331
331
|
}
|
332
|
-
} else i["@id"] && r.push({ id: i["@id"], type:
|
332
|
+
} else i["@id"] && r.push({ id: i["@id"], type: k(i) });
|
333
333
|
return r.length ? r : void 0;
|
334
334
|
}
|
335
|
-
function
|
335
|
+
function C(t) {
|
336
336
|
let e = t.related ? Array.isArray(t.related) ? t.related : [t.related] : [], r = t.contentLayer;
|
337
|
-
return { provider: t.logo || e.length ? [{ id:
|
337
|
+
return { provider: t.logo || e.length ? [{ id: M.providerId, type: "Agent", homepage: e.length ? [e[0]] : void 0, logo: t.logo ? Array.isArray(t.logo) ? t.logo : [t.logo] : void 0, label: R(M.providerName) }] : void 0, partOf: ut(t), rendering: t.rendering, seeAlso: t.seeAlso, start: t.startCanvas, service: t.service ? b(t.service) : void 0, supplementary: r ? [r] : void 0 };
|
338
338
|
}
|
339
339
|
function ft(t) {
|
340
340
|
return { chars: t.chars, format: t.format ? t.format : void 0, language: t.language };
|
341
341
|
}
|
342
342
|
function mt(t) {
|
343
|
-
return
|
343
|
+
return u({ ...d(t), ...y(t), ...C(t), items: t.members });
|
344
344
|
}
|
345
345
|
function gt(t) {
|
346
346
|
let e = [], r = [], i;
|
347
347
|
for (let n of t.sequences || []) n.canvases.length && e.push(...n.canvases), n.behavior && r.push(...n.behavior), n.startCanvas && (i = n.startCanvas);
|
348
|
-
let s =
|
349
|
-
return r.length && (s.behavior ? s.behavior.push(...r) : s.behavior = r),
|
348
|
+
let s = d(t);
|
349
|
+
return r.length && (s.behavior ? s.behavior.push(...r) : s.behavior = r), u({ ...s, ...y(t), ...C(t), start: i, items: e, structures: dt(t.structures) });
|
350
350
|
}
|
351
351
|
function dt(t) {
|
352
352
|
if (!t) return t;
|
@@ -360,10 +360,10 @@ function dt(t) {
|
|
360
360
|
return t.filter((i) => r.indexOf(i.id) === -1);
|
361
361
|
}
|
362
362
|
function yt(t) {
|
363
|
-
return
|
363
|
+
return u({ ...d(t), ...y(t), ...C(t), annotations: t.otherContent && t.otherContent.length ? t.otherContent : void 0, items: t.images && t.images.length ? [{ id: Z(t, "annotation-page"), type: "AnnotationPage", items: t.images }] : void 0 });
|
364
364
|
}
|
365
365
|
function At(t) {
|
366
|
-
return
|
366
|
+
return u({ ...d(t), ...y(t), ...C(t), items: t.resources && t.resources.length ? t.resources : void 0 });
|
367
367
|
}
|
368
368
|
function Ct(t) {
|
369
369
|
return !t.canvases || t.canvases.length === 0 ? { canvases: [], behavior: [] } : { canvases: t.canvases, behavior: t.viewingHint ? [t.viewingHint] : [], startCanvas: t.startCanvas };
|
@@ -381,47 +381,47 @@ function bt(t) {
|
|
381
381
|
else if (r.full["@type"] === "dctypes:Image") i = { id: r.full["@id"], type: "Image" };
|
382
382
|
else if (r.full["@type"] === "sc:Canvas") i = { id: r.full["@id"], type: "Canvas" };
|
383
383
|
else throw new Error(`Unsupported source type on annotation: ${r.full["@type"]}`);
|
384
|
-
return { type: "SpecificResource", source: i, selector:
|
384
|
+
return { type: "SpecificResource", source: i, selector: j(r.selector) };
|
385
385
|
} else return encodeURI(r["@id"]).trim();
|
386
386
|
}
|
387
|
-
return
|
387
|
+
return u({ ...d(t), ...y(t), ...C(t), target: e(t.on), body: Array.isArray(t.resource) ? t.resource.map(N) : N(t.resource) });
|
388
388
|
}
|
389
389
|
function N(t) {
|
390
390
|
return t.type === "Choice" ? t : ee(t);
|
391
391
|
}
|
392
392
|
function ee(t) {
|
393
393
|
let e = t;
|
394
|
-
return
|
394
|
+
return u({ ...d(e), ...y(e), ...C(e), ...ft(e) });
|
395
395
|
}
|
396
396
|
function Rt(t) {
|
397
397
|
let e = [];
|
398
|
-
return t.default && t.default !== "rdf:nil" && e.push(t.default), t.item && t.item !== "rdf:nil" && e.push(...t.item),
|
398
|
+
return t.default && t.default !== "rdf:nil" && e.push(t.default), t.item && t.item !== "rdf:nil" && e.push(...t.item), u({ ...d(t), ...y(t), items: e });
|
399
399
|
}
|
400
400
|
function Lt(t) {
|
401
|
-
return
|
401
|
+
return u({ ...d(t), ...y(t), ...C(t), items: t.members });
|
402
402
|
}
|
403
403
|
function wt(t) {
|
404
404
|
let { "@id": e, "@type": r, "@context": i, profile: s, ...n } = t, a = {};
|
405
|
-
return e && (a["@id"] = e), a["@type"] =
|
405
|
+
return e && (a["@id"] = e), a["@type"] = k(t), a["@type"] === "unknown" && (i && i.length && (a["@context"] = i), a["@type"] = "Service"), s && (a.profile = Y(s)), u({ ...a, ...n });
|
406
406
|
}
|
407
407
|
function It(t) {
|
408
|
-
return
|
408
|
+
return u({ ...d(t), ...y(t), ...C(t) });
|
409
409
|
}
|
410
410
|
var St = new Oe({ collection: [mt], manifest: [gt], canvas: [yt], annotationList: [At], sequence: [Ct], annotation: [bt], contentResource: [ee], choice: [Rt], range: [Lt], service: [wt], layer: [It] });
|
411
411
|
function te(t) {
|
412
412
|
return t && t["@context"] && (t["@context"] === "http://iiif.io/api/presentation/2/context.json" || t["@context"].indexOf("http://iiif.io/api/presentation/2/context.json") !== -1 || t["@context"] === "http://www.shared-canvas.org/ns/context.json") || t["@context"] === "http://iiif.io/api/image/2/context.json" ? St.traverseUnknown(t) : t;
|
413
413
|
}
|
414
|
-
function
|
414
|
+
function j(t) {
|
415
415
|
if ((Array.isArray(t["@type"]) && t["@type"].includes("oa:SvgSelector") || t["@type"] == "oa:SvgSelector") && ("chars" in t || "value" in t)) return { type: "SvgSelector", value: "chars" in t ? t.chars : t.value };
|
416
416
|
if (t["@type"] === "oa:FragmentSelector") return { type: "FragmentSelector", value: t.value };
|
417
|
-
if (t["@type"] === "oa:Choice") return [
|
417
|
+
if (t["@type"] === "oa:Choice") return [j(t.default), ...(Array.isArray(t.item) ? t.item : [t.item]).map(j)];
|
418
418
|
if (t["@type"] == "iiif:ImageApiSelector") return { type: "ImageApiSelector", region: "region" in t ? t.region : void 0, rotation: "rotation" in t ? t.rotation : void 0 };
|
419
419
|
throw new Error(`Unsupported selector type: ${t["@type"]}`);
|
420
420
|
}
|
421
|
-
function
|
421
|
+
function x(t) {
|
422
422
|
return typeof t == "string" ? !1 : t && !t.type && "source" in t ? (t.type = "SpecificResource", !0) : !!t && t.type === "SpecificResource";
|
423
423
|
}
|
424
|
-
function
|
424
|
+
function S(...t) {
|
425
425
|
return (e) => t.reduce((r, i) => i(r), e);
|
426
426
|
}
|
427
427
|
var q = ["Collection", "Manifest", "Canvas", "AnnotationPage", "AnnotationCollection", "Annotation", "ContentResource", "Range", "Service", "Selector", "Agent"];
|
@@ -439,9 +439,9 @@ function Tt(t, e) {
|
|
439
439
|
if (t.profile) return "Service";
|
440
440
|
throw new Error("Resource type is not known");
|
441
441
|
}
|
442
|
-
var
|
442
|
+
var P = class re {
|
443
443
|
constructor(e, r = {}) {
|
444
|
-
|
444
|
+
A(this, "traversals"), A(this, "options"), A(this, "_traverseManifest", S(this.traverseManifestItems.bind(this), this.traverseLinking.bind(this), this.traverseDescriptive.bind(this), this.traverseLinkedCanvases.bind(this), this.traverseManifestStructures.bind(this), this.traverseInlineAnnotationPages.bind(this))), A(this, "_traverseCanvas", S(this.traverseCanvasItems.bind(this), this.traverseLinking.bind(this), this.traverseDescriptive.bind(this), this.traverseLinkedCanvases.bind(this), this.traverseInlineAnnotationPages.bind(this))), A(this, "_traverseAnnotationPage", S(this.traverseAnnotationPageItems.bind(this), this.traverseLinking.bind(this), this.traverseDescriptive.bind(this))), A(this, "_traverseRange", S(this.traverseRangeRanges.bind(this), this.traverseLinking.bind(this), this.traverseDescriptive.bind(this), this.traverseLinkedCanvases.bind(this))), this.traversals = { collection: [], manifest: [], canvas: [], annotationCollection: [], annotationPage: [], annotation: [], contentResource: [], choice: [], range: [], service: [], agent: [], specificResource: [], geoJson: [], ...e }, this.options = { allowUndefinedReturn: !1, ...r };
|
445
445
|
}
|
446
446
|
static all(e) {
|
447
447
|
return new re({ collection: [e], manifest: [e], canvas: [e], annotationCollection: [e], annotationPage: [e], annotation: [e], contentResource: [e], choice: [e], range: [e], service: [e], geoJson: [e], specificResource: [e], agent: [e] });
|
@@ -450,7 +450,7 @@ var k = class re {
|
|
450
450
|
return e.thumbnail && (e.thumbnail = b(e.thumbnail).map((r) => this.traverseType(r, { parent: e }, this.traversals.contentResource))), e.provider && (e.provider = e.provider.map((r) => this.traverseAgent(r, e))), e;
|
451
451
|
}
|
452
452
|
traverseLinking(e) {
|
453
|
-
return e.seeAlso && (e.seeAlso = e.seeAlso.map((r) => this.traverseType(r, { parent: e }, this.traversals.contentResource))), e.service && (e.service = b(e.service).map((r) => this.traverseService(r))), e.services && (e.services = b(e.services).map((r) => this.traverseService(r, e))), e.logo && (e.logo = e.logo.map((r) => this.traverseType(r, { parent: e }, this.traversals.contentResource))), e.homepage && (e.homepage = b(e.homepage).map((r) => this.traverseType(r, { parent: e }, this.traversals.contentResource))), e.partOf && (e.partOf = e.partOf.map((r) => typeof r == "string" || !r.type ? this.traverseType(r, { parent: e }, this.traversals.contentResource) : r.type === "Canvas" ? this.traverseType(r, { parent: e }, this.traversals.canvas) : r.type === "AnnotationCollection" ? this.traverseType(r, { parent: e }, this.traversals.annotationCollection) : r.type === "Collection" ? this.traverseType(r, { parent: e }, this.traversals.collection) : this.traverseType(r, { parent: e }, this.traversals.contentResource))), e.start && (
|
453
|
+
return e.seeAlso && (e.seeAlso = e.seeAlso.map((r) => this.traverseType(r, { parent: e }, this.traversals.contentResource))), e.service && (e.service = b(e.service).map((r) => this.traverseService(r))), e.services && (e.services = b(e.services).map((r) => this.traverseService(r, e))), e.logo && (e.logo = e.logo.map((r) => this.traverseType(r, { parent: e }, this.traversals.contentResource))), e.homepage && (e.homepage = b(e.homepage).map((r) => this.traverseType(r, { parent: e }, this.traversals.contentResource))), e.partOf && (e.partOf = e.partOf.map((r) => typeof r == "string" || !r.type ? this.traverseType(r, { parent: e }, this.traversals.contentResource) : r.type === "Canvas" ? this.traverseType(r, { parent: e }, this.traversals.canvas) : r.type === "AnnotationCollection" ? this.traverseType(r, { parent: e }, this.traversals.annotationCollection) : r.type === "Collection" ? this.traverseType(r, { parent: e }, this.traversals.collection) : this.traverseType(r, { parent: e }, this.traversals.contentResource))), e.start && (x(e.start) ? e.start = this.traverseSpecificResource(e.start, "Canvas", e) : e.start = this.traverseType(e.start, { parent: e }, this.traversals.canvas)), e.rendering && (e.rendering = e.rendering.map((r) => this.traverseType(r, { parent: e }, this.traversals.contentResource))), e.supplementary && (e.supplementary = e.supplementary.map((r) => this.traverseType(r, { parent: e }, this.traversals.contentResource))), e;
|
454
454
|
}
|
455
455
|
traverseCollectionItems(e) {
|
456
456
|
return e.items && e.items.map((r) => r.type === "Collection" ? this.traverseCollection(r) : this.traverseManifest(r)), e;
|
@@ -501,14 +501,14 @@ var k = class re {
|
|
501
501
|
return typeof e == "string" || !e || e && e.service && (e.service = b(e.service || []).map((r) => this.traverseService(r, e))), e;
|
502
502
|
}
|
503
503
|
traverseContentResource(e, r) {
|
504
|
-
return e.type === "Choice" && (e.items = e.items.map((i) => this.traverseContentResource(i, e))),
|
504
|
+
return e.type === "Choice" && (e.items = e.items.map((i) => this.traverseContentResource(i, e))), x(e) ? this.traverseSpecificResource(e, "ContentResource") : this.traverseType(this.traverseInlineAnnotationPages(this.traverseContentResourceLinking(e)), { parent: r }, this.traversals.contentResource);
|
505
505
|
}
|
506
506
|
traverseSpecificResource(e, r, i) {
|
507
507
|
let s = e.source;
|
508
508
|
return typeof e.source == "string" && (s = { id: e.source, type: r || "unknown" }), this.traverseType({ ...e, source: r === "Canvas" || s.type === "Canvas" ? this.traverseType(s, { parent: i }, this.traversals.canvas) : r === "ContentResource" ? this.traverseContentResource(s, { parent: i }) : this.traverseUnknown(s, { parent: i, typeHint: r }) }, { parent: i }, this.traversals.specificResource);
|
509
509
|
}
|
510
510
|
traverseRangeRanges(e) {
|
511
|
-
return e.items && (e.items = e.items.map((r) => typeof r == "string" ? this.traverseCanvas({ id: r, type: "Canvas" }, e) :
|
511
|
+
return e.items && (e.items = e.items.map((r) => typeof r == "string" ? this.traverseCanvas({ id: r, type: "Canvas" }, e) : x(r) ? this.traverseSpecificResource(r, "Canvas", e) : r.type === "Manifest" ? this.traverseManifest(r, e) : this.traverseRange(r, e))), e;
|
512
512
|
}
|
513
513
|
traverseRange(e, r) {
|
514
514
|
return this.traverseType(this._traverseRange(e), { parent: r }, this.traversals.range);
|
@@ -552,18 +552,18 @@ var k = class re {
|
|
552
552
|
}
|
553
553
|
}
|
554
554
|
};
|
555
|
-
const ie = (t) =>
|
556
|
-
const e =
|
555
|
+
const ie = (t) => h(t, "type").startsWith("ImageService") || t.profile && t.profile.toString().includes("iiif.io/api/image/"), se = (t) => {
|
556
|
+
const e = h(t, "type"), r = h(t, "context");
|
557
557
|
if (e === "ImageService2" || r != null && r.includes("image/2")) {
|
558
558
|
const i = t, s = ["level0", "level1", "level2"];
|
559
|
-
return { majorVersion: 2, profileLevel: (Array.isArray(i.profile) ? i.profile : [i.profile]).map((
|
559
|
+
return { majorVersion: 2, profileLevel: (Array.isArray(i.profile) ? i.profile : [i.profile]).map((c) => s.findIndex((l) => c.toString().includes(l))).filter((c) => c > -1).sort((c, l) => l - c)[0] };
|
560
560
|
} else if (e || r)
|
561
561
|
return { majorVersion: 3, profileLevel: parseInt(t.profile) };
|
562
562
|
}, _ = (t, e, r) => {
|
563
|
-
const i =
|
563
|
+
const i = h(t, "id"), s = t.profile || "";
|
564
564
|
if (typeof s == "string" && (s.includes("level0") || s.includes("level:0"))) {
|
565
565
|
if ("sizes" in t && Array.isArray(t.sizes)) {
|
566
|
-
const a = t.sizes.sort((
|
566
|
+
const a = t.sizes.sort((c, l) => l.width * l.height - c.width * c.height).filter((c) => c.width * c.height >= e * r)[0];
|
567
567
|
if (a)
|
568
568
|
return `${i}/full/${a.width},${a.height}/0/default.jpg`;
|
569
569
|
}
|
@@ -571,10 +571,10 @@ const ie = (t) => v(t, "type").startsWith("ImageService") || t.profile && t.prof
|
|
571
571
|
}
|
572
572
|
return `${i}/full/!${e},${r}/0/default.jpg`;
|
573
573
|
}, xt = (t, e, r) => {
|
574
|
-
const i =
|
574
|
+
const i = h(t, "id"), s = t.profile || "";
|
575
575
|
if (typeof s == "string" && (s.includes("level0") || s.includes("level:0"))) return;
|
576
|
-
const { x: a, y:
|
577
|
-
return `${i}/${
|
576
|
+
const { x: a, y: c, w: l, h: p } = e, v = l / p, f = v < 1, L = Math.ceil(f ? r / v : r), o = Math.ceil(f ? r : r / v), m = `${Math.round(a)},${Math.round(c)},${Math.round(l)},${Math.round(p)}`;
|
577
|
+
return `${i}/${m}/!${o},${L}/0/default.jpg`;
|
578
578
|
}, $t = (t) => (e, r = 400) => {
|
579
579
|
if (t.type === "dynamic")
|
580
580
|
return xt(t.service, e, r);
|
@@ -582,37 +582,37 @@ const ie = (t) => v(t, "type").startsWith("ImageService") || t.profile && t.prof
|
|
582
582
|
}, Mt = (t, e = []) => (r = 400) => {
|
583
583
|
const { width: i, height: s } = t;
|
584
584
|
if (!i || !s) return;
|
585
|
-
const n = i / s, a = n < 1,
|
585
|
+
const n = i / s, a = n < 1, c = Math.ceil(a ? r / n : r), l = Math.ceil(a ? r : r / n);
|
586
586
|
if (t.thumbnail && t.thumbnail.length > 0) {
|
587
587
|
const p = t.thumbnail[0];
|
588
588
|
if ("service" in p && Array.isArray(p.service)) {
|
589
|
-
const
|
590
|
-
if (
|
591
|
-
return _(
|
589
|
+
const v = p.service.find((f) => ie(f));
|
590
|
+
if (v)
|
591
|
+
return _(v, l, c);
|
592
592
|
}
|
593
593
|
if ("id" in p) return p.id;
|
594
594
|
}
|
595
595
|
for (const p of e) {
|
596
596
|
if (p.type === "dynamic" || p.type === "level0")
|
597
|
-
return _(p.service,
|
597
|
+
return _(p.service, l, c);
|
598
598
|
if (p.type === "static")
|
599
599
|
return p.url;
|
600
600
|
}
|
601
601
|
}, ne = (t) => t.endsWith("/info.json") ? t : `${t.endsWith("/") ? t : `${t}/`}info.json`, jt = (t) => {
|
602
|
-
const { format: e, height: r, width: i } = t, s =
|
602
|
+
const { format: e, height: r, width: i } = t, s = h(t, "id"), n = (t.service || []).find(ie), a = n ? se(n) : void 0;
|
603
603
|
if (a) {
|
604
|
-
const
|
604
|
+
const c = {
|
605
605
|
source: t,
|
606
606
|
type: a.profileLevel === 0 ? "level0" : "dynamic",
|
607
607
|
service: n,
|
608
608
|
width: i,
|
609
609
|
height: r,
|
610
610
|
majorVersion: a.majorVersion,
|
611
|
-
serviceUrl: ne(
|
611
|
+
serviceUrl: ne(h(n, "id"))
|
612
612
|
};
|
613
|
-
return a.profileLevel === 0 ?
|
614
|
-
...
|
615
|
-
getRegionURL: $t(
|
613
|
+
return a.profileLevel === 0 ? c : {
|
614
|
+
...c,
|
615
|
+
getRegionURL: $t(c)
|
616
616
|
};
|
617
617
|
} else
|
618
618
|
return {
|
@@ -625,7 +625,7 @@ const ie = (t) => v(t, "type").startsWith("ImageService") || t.profile && t.prof
|
|
625
625
|
};
|
626
626
|
}, kt = (t) => {
|
627
627
|
const e = [];
|
628
|
-
return new
|
628
|
+
return new P({
|
629
629
|
annotation: [(i) => {
|
630
630
|
if (i.motivation === "painting" || !i.motivation) {
|
631
631
|
const n = (i.body ? Array.isArray(i.body) ? i.body : [i.body] : []).filter((a) => a.type === "Image");
|
@@ -634,34 +634,42 @@ const ie = (t) => v(t, "type").startsWith("ImageService") || t.profile && t.prof
|
|
634
634
|
}]
|
635
635
|
}).traverseCanvas(t), e;
|
636
636
|
}, Pt = (t) => () => {
|
637
|
-
const e = (
|
638
|
-
const
|
639
|
-
id:
|
637
|
+
const e = /* @__PURE__ */ new Map(), r = (a, c, l = 0) => {
|
638
|
+
const p = {
|
639
|
+
id: a.id,
|
640
640
|
type: "range",
|
641
|
-
|
641
|
+
source: a,
|
642
642
|
children: [],
|
643
|
-
|
644
|
-
|
643
|
+
navItems: [],
|
644
|
+
navSections: [],
|
645
|
+
parent: c,
|
646
|
+
level: l,
|
647
|
+
getLabel: a.getLabel
|
645
648
|
};
|
646
|
-
|
649
|
+
a.items && a.items.length > 0 && a.items.forEach((o) => {
|
647
650
|
if (o.source.type === "Range") {
|
648
|
-
const
|
649
|
-
|
651
|
+
const I = r(o, p, l + 1);
|
652
|
+
p.children.push(I);
|
650
653
|
} else
|
651
|
-
|
654
|
+
p.children.push({
|
652
655
|
id: o.id,
|
653
656
|
type: "canvas",
|
654
|
-
|
657
|
+
source: o,
|
655
658
|
children: [],
|
656
|
-
|
657
|
-
|
659
|
+
navItems: [],
|
660
|
+
navSections: [],
|
661
|
+
parent: p,
|
662
|
+
level: l + 1,
|
663
|
+
getLabel: o.getLabel
|
658
664
|
});
|
659
|
-
})
|
665
|
+
});
|
666
|
+
const v = p.children.map((o) => o.type === "canvas" ? o.source : o.children.length === 1 && o.children[0].type === "canvas" ? o.children[0].source : o.source), f = v.filter((o) => o.source.type === "Canvas"), L = v.filter((o) => o.source.type === "Range");
|
667
|
+
return p.navItems.push(...f), p.navSections.push(...L), e.set(p.id, p), p;
|
660
668
|
};
|
661
|
-
return t.filter((
|
662
|
-
var
|
663
|
-
return (
|
664
|
-
}).map((
|
669
|
+
return { root: t.filter((a) => {
|
670
|
+
var c;
|
671
|
+
return (c = a.source.behavior) == null ? void 0 : c.includes("top");
|
672
|
+
}).map((a) => r(a, void 0)), getNode: (a) => e.get(a) };
|
665
673
|
}, Ot = async (t) => {
|
666
674
|
try {
|
667
675
|
new URL(t);
|
@@ -716,7 +724,7 @@ const ie = (t) => v(t, "type").startsWith("ImageService") || t.profile && t.prof
|
|
716
724
|
code: "INVALID_MANIFEST",
|
717
725
|
message: "Missing @context"
|
718
726
|
};
|
719
|
-
const i =
|
727
|
+
const i = h(t, "id");
|
720
728
|
if (!i)
|
721
729
|
return {
|
722
730
|
type: "error",
|
@@ -725,7 +733,7 @@ const ie = (t) => v(t, "type").startsWith("ImageService") || t.profile && t.prof
|
|
725
733
|
};
|
726
734
|
if (r.includes("presentation/2") || r.includes("presentation/3")) {
|
727
735
|
const s = r.includes("presentation/2") ? 2 : 3;
|
728
|
-
return
|
736
|
+
return h(t, "type").includes("Collection") ? {
|
729
737
|
type: "collection",
|
730
738
|
url: e || i,
|
731
739
|
resource: Ut(t, s)
|
@@ -755,13 +763,13 @@ const ie = (t) => v(t, "type").startsWith("ImageService") || t.profile && t.prof
|
|
755
763
|
}, Ut = (t, e) => {
|
756
764
|
const r = (n) => {
|
757
765
|
const a = [];
|
758
|
-
return new
|
759
|
-
manifest: [(
|
760
|
-
}).traverseCollection(n), a.map((
|
761
|
-
id:
|
762
|
-
type:
|
763
|
-
getLabel:
|
764
|
-
source:
|
766
|
+
return new P({
|
767
|
+
manifest: [(l) => a.push(l)]
|
768
|
+
}).traverseCollection(n), a.map((l) => ({
|
769
|
+
id: l.id,
|
770
|
+
type: l.type,
|
771
|
+
getLabel: w(l),
|
772
|
+
source: l
|
765
773
|
}));
|
766
774
|
}, i = e === 2 ? te(t) : t, s = r(i);
|
767
775
|
return {
|
@@ -769,46 +777,46 @@ const ie = (t) => v(t, "type").startsWith("ImageService") || t.profile && t.prof
|
|
769
777
|
id: i.id,
|
770
778
|
majorVersion: e,
|
771
779
|
items: s,
|
772
|
-
getLabel:
|
773
|
-
getMetadata:
|
780
|
+
getLabel: w(i),
|
781
|
+
getMetadata: $(i)
|
774
782
|
};
|
775
783
|
}, Dt = (t, e) => {
|
776
784
|
const r = (a) => {
|
777
|
-
const
|
778
|
-
new
|
779
|
-
canvas: [(
|
780
|
-
|
785
|
+
const c = [], l = [];
|
786
|
+
new P({
|
787
|
+
canvas: [(o) => {
|
788
|
+
o.items && c.push(o);
|
781
789
|
}],
|
782
|
-
range: [(
|
783
|
-
|
790
|
+
range: [(o) => {
|
791
|
+
o.type === "Range" && l.push(o);
|
784
792
|
}]
|
785
793
|
}).traverseManifest(a);
|
786
|
-
const
|
787
|
-
const
|
794
|
+
const v = c.map((o) => {
|
795
|
+
const m = kt(o);
|
788
796
|
return {
|
789
|
-
source:
|
790
|
-
id:
|
791
|
-
width:
|
792
|
-
height:
|
793
|
-
images:
|
794
|
-
annotations:
|
795
|
-
getLabel:
|
796
|
-
getMetadata:
|
797
|
-
getThumbnailURL: Mt(
|
797
|
+
source: o,
|
798
|
+
id: o.id,
|
799
|
+
width: o.width,
|
800
|
+
height: o.height,
|
801
|
+
images: m,
|
802
|
+
annotations: o.annotations || [],
|
803
|
+
getLabel: w(o),
|
804
|
+
getMetadata: $(o),
|
805
|
+
getThumbnailURL: Mt(o, m)
|
798
806
|
};
|
799
|
-
}),
|
800
|
-
const
|
807
|
+
}), f = (o) => {
|
808
|
+
const m = o.items || [], I = m.filter((g) => g.type === "Canvas").map((g) => v.find((T) => T.id === g.id)).filter(Boolean), O = m.filter((g) => g.type === "Range").map((g) => f(g)), oe = [...I, ...O];
|
801
809
|
return {
|
802
|
-
source:
|
803
|
-
id:
|
810
|
+
source: o,
|
811
|
+
id: o.id,
|
804
812
|
// Maintain original order
|
805
|
-
items:
|
806
|
-
canvases:
|
813
|
+
items: m.map((g) => oe.find((T) => T.id === g.id)),
|
814
|
+
canvases: I,
|
807
815
|
ranges: O,
|
808
|
-
getLabel:
|
816
|
+
getLabel: w(o)
|
809
817
|
};
|
810
|
-
},
|
811
|
-
return { canvases:
|
818
|
+
}, L = l.map((o) => f(o));
|
819
|
+
return { canvases: v, ranges: L };
|
812
820
|
}, i = e === 2 ? te(t) : t, { canvases: s, ranges: n } = r(i);
|
813
821
|
return {
|
814
822
|
source: i,
|
@@ -816,8 +824,8 @@ const ie = (t) => v(t, "type").startsWith("ImageService") || t.profile && t.prof
|
|
816
824
|
majorVersion: e,
|
817
825
|
canvases: s,
|
818
826
|
structure: n,
|
819
|
-
getLabel:
|
820
|
-
getMetadata:
|
827
|
+
getLabel: w(i),
|
828
|
+
getMetadata: $(i),
|
821
829
|
getTableOfContents: Pt(n)
|
822
830
|
};
|
823
831
|
}, Et = (t) => {
|
@@ -829,16 +837,16 @@ const ie = (t) => v(t, "type").startsWith("ImageService") || t.profile && t.prof
|
|
829
837
|
width: e,
|
830
838
|
height: r,
|
831
839
|
majorVersion: i.majorVersion,
|
832
|
-
serviceUrl: ne(
|
840
|
+
serviceUrl: ne(h(t, "id"))
|
833
841
|
};
|
834
842
|
}, qt = { parse: ae, parseURL: Ot };
|
835
843
|
export {
|
836
844
|
qt as Cozy,
|
837
845
|
_ as getImageURLFromService,
|
838
846
|
kt as getImages,
|
839
|
-
|
840
|
-
|
841
|
-
|
847
|
+
w as getLabel,
|
848
|
+
$ as getMetadata,
|
849
|
+
h as getPropertyValue,
|
842
850
|
$t as getRegionURL,
|
843
851
|
xt as getRegionURLFromService,
|
844
852
|
Ft as getStringValue,
|
package/dist/types.d.ts
CHANGED
@@ -43,7 +43,7 @@ export interface CozyManifest {
|
|
43
43
|
readonly canvases: CozyCanvas[];
|
44
44
|
readonly structure: CozyRange[];
|
45
45
|
getLabel(locale?: string): string | undefined;
|
46
|
-
getTableOfContents():
|
46
|
+
getTableOfContents(): CozyTOC;
|
47
47
|
getMetadata(locale?: string): CozyMetadata[];
|
48
48
|
}
|
49
49
|
export interface CozyRange {
|
@@ -69,13 +69,20 @@ export interface CozyMetadata {
|
|
69
69
|
readonly label: string;
|
70
70
|
readonly value: string;
|
71
71
|
}
|
72
|
+
export interface CozyTOC {
|
73
|
+
root: CozyTOCNode[];
|
74
|
+
getNode(id: string): CozyTOCNode | undefined;
|
75
|
+
}
|
72
76
|
export interface CozyTOCNode {
|
73
77
|
readonly id: string;
|
74
78
|
readonly type: 'range' | 'canvas';
|
79
|
+
readonly source: CozyRange | CozyCanvas;
|
80
|
+
readonly children: CozyTOCNode[];
|
81
|
+
readonly navItems: CozyCanvas[];
|
82
|
+
readonly navSections: CozyRange[];
|
83
|
+
readonly parent?: CozyTOCNode;
|
84
|
+
readonly level: number;
|
75
85
|
getLabel(locale?: string): string | undefined;
|
76
|
-
children: CozyTOCNode[];
|
77
|
-
parent?: CozyTOCNode;
|
78
|
-
level: number;
|
79
86
|
}
|
80
87
|
export type CozyImageResource = StaticImageResource | ImageServiceResource;
|
81
88
|
export type ImageServiceResource = DynamicImageServiceResource | Level0ImageServiceResource;
|
package/package.json
CHANGED
package/src/core/manifest.ts
CHANGED
@@ -1,38 +1,75 @@
|
|
1
|
-
import type { CozyRange, CozyTOCNode } from '../types';
|
1
|
+
import type { CozyCanvas, CozyRange, CozyTOC, CozyTOCNode } from '../types';
|
2
2
|
|
3
|
-
export const getTableOfContents = (ranges: CozyRange[]) => () => {
|
3
|
+
export const getTableOfContents = (ranges: CozyRange[]) => (): CozyTOC => {
|
4
|
+
|
5
|
+
const index = new Map<string, CozyTOCNode>();
|
4
6
|
|
5
7
|
const buildTree = (range: CozyRange, parent: CozyTOCNode | undefined, level: number = 0): CozyTOCNode => {
|
6
8
|
const node: CozyTOCNode = {
|
7
9
|
id: range.id,
|
8
10
|
type: 'range',
|
9
|
-
|
11
|
+
source: range,
|
10
12
|
children: [],
|
13
|
+
navItems: [],
|
14
|
+
navSections: [],
|
11
15
|
parent,
|
12
|
-
level
|
16
|
+
level,
|
17
|
+
getLabel: range.getLabel,
|
13
18
|
};
|
14
19
|
|
15
20
|
if (range.items && range.items.length > 0) {
|
16
21
|
range.items.forEach(item => {
|
17
22
|
if (item.source.type === 'Range') {
|
18
|
-
const
|
23
|
+
const r = item as CozyRange;
|
24
|
+
const childNode = buildTree(r, node, level + 1);
|
19
25
|
node.children.push(childNode);
|
20
26
|
} else {
|
27
|
+
// This child is Canvas, i.e. a TOCNode with
|
28
|
+
// no further children.
|
21
29
|
node.children.push({
|
22
30
|
id: item.id,
|
23
31
|
type: 'canvas',
|
24
|
-
|
32
|
+
source: item as CozyCanvas,
|
25
33
|
children: [],
|
34
|
+
navItems: [],
|
35
|
+
navSections: [],
|
26
36
|
parent: node,
|
27
|
-
level: level + 1
|
37
|
+
level: level + 1,
|
38
|
+
getLabel: item.getLabel
|
28
39
|
});
|
29
40
|
}
|
30
41
|
});
|
31
42
|
}
|
43
|
+
|
44
|
+
// From the actual child ToC Nodes, infer the "logical" child navItems
|
45
|
+
// (canvases) and navSections (ranges).
|
46
|
+
const navChildren = node.children.map(n => {
|
47
|
+
if (n.type === 'canvas') {
|
48
|
+
// An actual leaf node
|
49
|
+
return n.source as CozyCanvas;
|
50
|
+
} else if (n.children.length === 1 && n.children[0].type === 'canvas') {
|
51
|
+
// A range with a single canvas child - logical leaf node!
|
52
|
+
return n.children[0].source as CozyCanvas;
|
53
|
+
} else {
|
54
|
+
return n.source as CozyRange;
|
55
|
+
}
|
56
|
+
});
|
57
|
+
|
58
|
+
const navItems = navChildren.filter(c => c.source.type === 'Canvas') as CozyCanvas[];
|
59
|
+
const navSections = navChildren.filter(c => c.source.type === 'Range') as CozyRange[];
|
32
60
|
|
61
|
+
node.navItems.push(...navItems);
|
62
|
+
node.navSections.push(...navSections);
|
63
|
+
|
64
|
+
index.set(node.id, node);
|
65
|
+
|
33
66
|
return node;
|
34
67
|
};
|
35
68
|
|
36
69
|
const topRanges = ranges.filter(range => range.source.behavior?.includes('top'));
|
37
|
-
|
70
|
+
const root = topRanges.map(range => buildTree(range, undefined));
|
71
|
+
|
72
|
+
const getNode = (id: string) => index.get(id);
|
73
|
+
|
74
|
+
return { root, getNode };
|
38
75
|
}
|
package/src/types.ts
CHANGED
@@ -1,4 +1,13 @@
|
|
1
|
-
import type {
|
1
|
+
import type {
|
2
|
+
Manifest,
|
3
|
+
Canvas,
|
4
|
+
ImageService2,
|
5
|
+
ImageService3,
|
6
|
+
IIIFExternalWebResource,
|
7
|
+
Collection,
|
8
|
+
Range,
|
9
|
+
AnnotationPage
|
10
|
+
} from '@iiif/presentation-3';
|
2
11
|
|
3
12
|
export type CozyParseResult =
|
4
13
|
| { type: 'collection', url: string, resource: CozyCollection }
|
@@ -54,7 +63,7 @@ export interface CozyManifest {
|
|
54
63
|
|
55
64
|
getLabel(locale?: string): string | undefined;
|
56
65
|
|
57
|
-
getTableOfContents():
|
66
|
+
getTableOfContents(): CozyTOC;
|
58
67
|
|
59
68
|
getMetadata(locale?: string): CozyMetadata[];
|
60
69
|
|
@@ -106,19 +115,33 @@ export interface CozyMetadata {
|
|
106
115
|
|
107
116
|
}
|
108
117
|
|
118
|
+
export interface CozyTOC {
|
119
|
+
|
120
|
+
root: CozyTOCNode[];
|
121
|
+
|
122
|
+
getNode(id: string): CozyTOCNode | undefined;
|
123
|
+
|
124
|
+
}
|
125
|
+
|
109
126
|
export interface CozyTOCNode {
|
110
127
|
|
111
128
|
readonly id: string;
|
112
129
|
|
113
130
|
readonly type: 'range' | 'canvas';
|
114
131
|
|
115
|
-
|
132
|
+
readonly source: CozyRange | CozyCanvas;
|
133
|
+
|
134
|
+
readonly children: CozyTOCNode[];
|
135
|
+
|
136
|
+
readonly navItems: CozyCanvas[];
|
116
137
|
|
117
|
-
|
138
|
+
readonly navSections: CozyRange[];
|
118
139
|
|
119
|
-
parent?: CozyTOCNode;
|
140
|
+
readonly parent?: CozyTOCNode;
|
120
141
|
|
121
|
-
level: number;
|
142
|
+
readonly level: number;
|
143
|
+
|
144
|
+
getLabel(locale?: string): string | undefined;
|
122
145
|
|
123
146
|
}
|
124
147
|
|