cozy-iiif 0.6.2 → 0.6.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/dist/core/image-service.d.ts +3 -2
- package/dist/index.js +111 -111
- package/package.json +1 -1
- package/src/core/image-service.ts +6 -3
- package/test/core/canvas.test.ts +1 -19
- package/test/core/fixtures.ts +0 -4
- package/test/helpers/fixtures.ts +7 -1
- package/test/core/manifest.test.ts +0 -28
|
@@ -12,8 +12,9 @@ export declare const getStaticImagePixelSize: (url: string) => () => Promise<{
|
|
|
12
12
|
height: number;
|
|
13
13
|
}>;
|
|
14
14
|
export declare const getImageURLFromService: (service: Service, width: number, height: number) => string;
|
|
15
|
-
export declare const getRegionURLFromService: (service: Service, bounds: Bounds,
|
|
16
|
-
|
|
15
|
+
export declare const getRegionURLFromService: (service: Service, bounds: Bounds, rotation?: number, // 0, 90, 180, 270
|
|
16
|
+
opts?: GetRegionURLOpts) => string | undefined;
|
|
17
|
+
export declare const getRegionURL: (image: CozyImageResource) => (bounds: Bounds, rotation?: number, opts?: GetRegionURLOpts) => string | undefined;
|
|
17
18
|
export declare const getImageURL: (width: number | undefined, height: number | undefined, service: Service) => (minSize?: number) => string | undefined;
|
|
18
19
|
export declare const getPixelSizeFromServiceUrl: (serviceUrl: string) => () => Promise<{
|
|
19
20
|
width: number;
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { g as
|
|
1
|
+
import { g as y, a as k, b as x } from "./resource-DS2brz47.js";
|
|
2
2
|
import { c as je } from "./resource-DS2brz47.js";
|
|
3
3
|
import { imageSize as ft } from "image-size";
|
|
4
4
|
function T(e) {
|
|
@@ -23,7 +23,7 @@ function mt(e) {
|
|
|
23
23
|
var t = gt(e, "string");
|
|
24
24
|
return T(t) == "symbol" ? t : t + "";
|
|
25
25
|
}
|
|
26
|
-
function
|
|
26
|
+
function S(e, t, r) {
|
|
27
27
|
return (t = mt(t)) in e ? Object.defineProperty(e, t, { value: r, enumerable: !0, configurable: !0, writable: !0 }) : e[t] = r, e;
|
|
28
28
|
}
|
|
29
29
|
function C(e) {
|
|
@@ -56,7 +56,7 @@ function dt(e, t) {
|
|
|
56
56
|
}
|
|
57
57
|
var N = class F {
|
|
58
58
|
constructor(t, r = {}) {
|
|
59
|
-
|
|
59
|
+
S(this, "traversals", void 0), S(this, "options", void 0), S(this, "_traverseManifest", $(this.traverseManifestItems.bind(this), this.traverseNavPlace.bind(this), this.traverseLinking.bind(this), this.traverseDescriptive.bind(this), this.traverseLinkedCanvases.bind(this), this.traverseManifestStructures.bind(this), this.traverseInlineAnnotationPages.bind(this))), S(this, "_traverseCanvas", $(this.traverseCanvasItems.bind(this), this.traverseLinking.bind(this), this.traverseDescriptive.bind(this), this.traverseLinkedCanvases.bind(this), this.traverseInlineAnnotationPages.bind(this))), S(this, "_traverseAnnotationPage", $(this.traverseAnnotationPageItems.bind(this), this.traverseLinking.bind(this), this.traverseDescriptive.bind(this))), S(this, "_traverseRange", $(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: [], ...t }, this.options = { allowUndefinedReturn: !1, ...r };
|
|
60
60
|
}
|
|
61
61
|
static all(t) {
|
|
62
62
|
return new F({ collection: [t], manifest: [t], canvas: [t], annotationCollection: [t], annotationPage: [t], annotation: [t], contentResource: [t], choice: [t], range: [t], service: [t], geoJson: [t], specificResource: [t], agent: [t] });
|
|
@@ -182,7 +182,7 @@ function Vt(e) {
|
|
|
182
182
|
}
|
|
183
183
|
var Bt = class et {
|
|
184
184
|
constructor(t, r = {}) {
|
|
185
|
-
|
|
185
|
+
S(this, "traversals", void 0), S(this, "options", void 0), this.traversals = { collection: [], manifest: [], canvas: [], annotationList: [], sequence: [], annotation: [], contentResource: [], choice: [], range: [], service: [], layer: [], ...t }, this.options = { convertPropsToArray: !0, mergeMemberProperties: !0, allowUndefinedReturn: !1, ...r };
|
|
186
186
|
}
|
|
187
187
|
static all(t) {
|
|
188
188
|
return new et({ collection: [t], manifest: [t], canvas: [t], annotationList: [t], sequence: [t], annotation: [t], contentResource: [t], choice: [t], range: [t], service: [t], layer: [t] });
|
|
@@ -326,7 +326,7 @@ function Ft(e) {
|
|
|
326
326
|
}
|
|
327
327
|
return r;
|
|
328
328
|
}
|
|
329
|
-
function
|
|
329
|
+
function w(e, t = "none") {
|
|
330
330
|
if (!e) return { none: [""] };
|
|
331
331
|
let r = Ft(e), i = {};
|
|
332
332
|
for (let n of r) {
|
|
@@ -442,12 +442,12 @@ function Kt(e) {
|
|
|
442
442
|
function Xt(e, t = "Rights/License", r = "none") {
|
|
443
443
|
let i = null, n = [], s = Array.isArray(e) ? e : [e];
|
|
444
444
|
for (let a of s) {
|
|
445
|
-
let
|
|
446
|
-
if (
|
|
447
|
-
i =
|
|
445
|
+
let c = a ? Kt(a) : void 0;
|
|
446
|
+
if (c && (c.indexOf("creativecommons.org") !== -1 || c.indexOf("rightsstatements.org") !== -1)) {
|
|
447
|
+
i = c.startsWith("https://") ? `http://${c.slice(8)}` : c;
|
|
448
448
|
continue;
|
|
449
449
|
}
|
|
450
|
-
|
|
450
|
+
c && n.push({ label: { [r]: [t] }, value: { [r]: [c] } });
|
|
451
451
|
}
|
|
452
452
|
return [i, n];
|
|
453
453
|
}
|
|
@@ -461,7 +461,7 @@ function Qt(e) {
|
|
|
461
461
|
}
|
|
462
462
|
}
|
|
463
463
|
function Zt(e) {
|
|
464
|
-
return e ? e.map((t) => ({ label:
|
|
464
|
+
return e ? e.map((t) => ({ label: w(t.label), value: w(t.value) })) : [];
|
|
465
465
|
}
|
|
466
466
|
let B = 0;
|
|
467
467
|
function it(e, t) {
|
|
@@ -476,7 +476,7 @@ function b(e) {
|
|
|
476
476
|
}
|
|
477
477
|
function R(e) {
|
|
478
478
|
let [t, r] = Xt(e.license), i = [...e.metadata ? Zt(e.metadata) : [], ...r];
|
|
479
|
-
return { rights: t, metadata: i.length ? i : void 0, label: e.label ?
|
|
479
|
+
return { rights: t, metadata: i.length ? i : void 0, label: e.label ? w(e.label) : void 0, requiredStatement: e.attribution ? { label: w(U.attributionLabel), value: w(e.attribution) } : void 0, navDate: e.navDate, summary: e.description ? w(e.description) : void 0, thumbnail: te(e.thumbnail) };
|
|
480
480
|
}
|
|
481
481
|
function te(e) {
|
|
482
482
|
return e && (Array.isArray(e) ? e : [e]).map((r) => typeof r == "string" ? { id: r, type: "Image" } : (r.type === "unknown" && (r.type = "Image"), r));
|
|
@@ -493,9 +493,9 @@ function ee(e) {
|
|
|
493
493
|
} else i["@id"] && r.push({ id: i["@id"], type: E(i) });
|
|
494
494
|
return r.length ? r : void 0;
|
|
495
495
|
}
|
|
496
|
-
function
|
|
496
|
+
function I(e) {
|
|
497
497
|
let t = e.related ? Array.isArray(e.related) ? e.related : [e.related] : [], r = e.contentLayer;
|
|
498
|
-
return { provider: e.logo || t.length ? [{ id: U.providerId, type: "Agent", homepage: t.length ? [t[0]] : void 0, logo: e.logo ? Array.isArray(e.logo) ? e.logo : [e.logo] : void 0, label:
|
|
498
|
+
return { provider: e.logo || t.length ? [{ id: U.providerId, type: "Agent", homepage: t.length ? [t[0]] : void 0, logo: e.logo ? Array.isArray(e.logo) ? e.logo : [e.logo] : void 0, label: w(U.providerName) }] : void 0, partOf: ee(e), rendering: e.rendering, seeAlso: e.seeAlso, start: e.startCanvas, service: e.service ? C(e.service) : void 0, supplementary: r ? [r] : void 0 };
|
|
499
499
|
}
|
|
500
500
|
function re(e) {
|
|
501
501
|
return { chars: e.chars, format: e.format ? e.format : void 0, language: e.language };
|
|
@@ -528,13 +528,13 @@ function ne(e) {
|
|
|
528
528
|
return t;
|
|
529
529
|
}
|
|
530
530
|
function se(e) {
|
|
531
|
-
return A({ ...b(e), ...R(e), ...
|
|
531
|
+
return A({ ...b(e), ...R(e), ...I(e), ...ie(e), items: ne(e.members) });
|
|
532
532
|
}
|
|
533
533
|
function ae(e) {
|
|
534
534
|
let t = [], r = [], i, n;
|
|
535
535
|
for (let a of e.sequences || []) a.canvases.length && t.push(...a.canvases), a.behavior && r.push(...a.behavior), a.viewingDirection && (n = a.viewingDirection), a.startCanvas && (i = a.startCanvas);
|
|
536
536
|
let s = b(e);
|
|
537
|
-
return r.length && (s.behavior ? s.behavior.push(...r) : s.behavior = r), A({ ...s, ...R(e), ...
|
|
537
|
+
return r.length && (s.behavior ? s.behavior.push(...r) : s.behavior = r), A({ ...s, ...R(e), ...I(e), viewingDirection: n, start: i, items: t, structures: oe(e.structures) });
|
|
538
538
|
}
|
|
539
539
|
function oe(e) {
|
|
540
540
|
if (!e) return e;
|
|
@@ -548,10 +548,10 @@ function oe(e) {
|
|
|
548
548
|
return e.filter((i) => r.indexOf(i.id) === -1);
|
|
549
549
|
}
|
|
550
550
|
function ce(e) {
|
|
551
|
-
return A({ ...b(e), ...R(e), ...
|
|
551
|
+
return A({ ...b(e), ...R(e), ...I(e), annotations: e.otherContent && e.otherContent.length ? e.otherContent : void 0, items: e.images && e.images.length ? [{ id: it(e, "annotation-page"), type: "AnnotationPage", items: e.images }] : void 0 });
|
|
552
552
|
}
|
|
553
553
|
function le(e) {
|
|
554
|
-
return A({ ...b(e), ...R(e), ...
|
|
554
|
+
return A({ ...b(e), ...R(e), ...I(e), items: e.resources && e.resources.length ? e.resources : void 0 });
|
|
555
555
|
}
|
|
556
556
|
function pe(e) {
|
|
557
557
|
return !e.canvases || e.canvases.length === 0 ? { canvases: [], behavior: [] } : { canvases: e.canvases, behavior: e.viewingHint ? [e.viewingHint] : [], viewingDirection: e.viewingDirection, startCanvas: e.startCanvas };
|
|
@@ -572,28 +572,28 @@ function ve(e) {
|
|
|
572
572
|
return { type: "SpecificResource", source: i, selector: O(r.selector) };
|
|
573
573
|
} else return encodeURI(r["@id"]).trim();
|
|
574
574
|
}
|
|
575
|
-
return A({ ...b(e), ...R(e), ...
|
|
575
|
+
return A({ ...b(e), ...R(e), ...I(e), target: t(e.on), body: Array.isArray(e.resource) ? e.resource.map(z) : z(e.resource) });
|
|
576
576
|
}
|
|
577
577
|
function z(e) {
|
|
578
578
|
return e.type === "Choice" ? e : nt(e);
|
|
579
579
|
}
|
|
580
580
|
function nt(e) {
|
|
581
581
|
let t = e;
|
|
582
|
-
return A({ ...b(t), ...R(t), ...
|
|
582
|
+
return A({ ...b(t), ...R(t), ...I(t), ...re(t) });
|
|
583
583
|
}
|
|
584
584
|
function he(e) {
|
|
585
585
|
let t = [];
|
|
586
586
|
return e.default && e.default !== "rdf:nil" && t.push(e.default), e.item && e.item !== "rdf:nil" && t.push(...e.item), A({ ...b(e), ...R(e), items: t });
|
|
587
587
|
}
|
|
588
588
|
function ue(e) {
|
|
589
|
-
return A({ ...b(e), ...R(e), ...
|
|
589
|
+
return A({ ...b(e), ...R(e), ...I(e), items: e.members });
|
|
590
590
|
}
|
|
591
591
|
function fe(e) {
|
|
592
592
|
let { "@id": t, "@type": r, "@context": i, profile: n, ...s } = e, a = {};
|
|
593
593
|
return t && (a["@id"] = t), a["@type"] = E(e), a["@type"] === "unknown" && (i && i.length && (a["@context"] = i), a["@type"] = "Service"), n && (a.profile = rt(n)), A({ ...a, ...s });
|
|
594
594
|
}
|
|
595
595
|
function ge(e) {
|
|
596
|
-
return A({ ...b(e), ...R(e), ...
|
|
596
|
+
return A({ ...b(e), ...R(e), ...I(e) });
|
|
597
597
|
}
|
|
598
598
|
const me = new Bt({ collection: [se], manifest: [ae], canvas: [ce], annotationList: [le], sequence: [pe], annotation: [ve], contentResource: [nt], choice: [he], range: [ue], service: [fe], layer: [ge] });
|
|
599
599
|
function st(e) {
|
|
@@ -608,11 +608,11 @@ function O(e) {
|
|
|
608
608
|
}
|
|
609
609
|
const at = (e) => e.endsWith("/info.json") ? e : `${e.endsWith("/") ? e : `${e}/`}info.json`, ot = (e) => {
|
|
610
610
|
var r;
|
|
611
|
-
return
|
|
611
|
+
return y(e, "type").startsWith("ImageService") || ((r = e.profile) == null ? void 0 : r.toString().includes("iiif.io/api/image/"));
|
|
612
612
|
}, ct = (e) => {
|
|
613
|
-
const t =
|
|
613
|
+
const t = y(e, "type"), r = y(e, "context");
|
|
614
614
|
if (t === "ImageService2" || r != null && r.includes("image/2")) {
|
|
615
|
-
const n =
|
|
615
|
+
const n = y(e, "profile"), s = ["level0", "level1", "level2"];
|
|
616
616
|
return { majorVersion: 2, profileLevel: (Array.isArray(n) ? n : n ? [n] : []).map((p) => s.findIndex((o) => p.toString().includes(o))).filter((p) => p > -1).sort((p, o) => o - p)[0] };
|
|
617
617
|
} else if (t || r)
|
|
618
618
|
return { majorVersion: 3, profileLevel: parseInt(e.profile) };
|
|
@@ -623,70 +623,70 @@ const at = (e) => e.endsWith("/info.json") ? e : `${e.endsWith("/") ? e : `${e}/
|
|
|
623
623
|
return i.close(), { width: n, height: s };
|
|
624
624
|
}) : r.arrayBuffer().then((i) => ft(new Uint8Array(i))));
|
|
625
625
|
}, D = (e, t, r) => {
|
|
626
|
-
const i =
|
|
626
|
+
const i = y(e, "id"), n = e.profile || "";
|
|
627
627
|
if (typeof n == "string" && (n.includes("level0") || n.includes("level:0"))) {
|
|
628
628
|
if ("sizes" in e && Array.isArray(e.sizes)) {
|
|
629
|
-
const a = e.sizes.sort((
|
|
629
|
+
const a = e.sizes.sort((c, p) => p.width * p.height - c.width * c.height).filter((c) => c.width * c.height >= t * r)[0];
|
|
630
630
|
if (a)
|
|
631
631
|
return `${i}/full/${a.width},${a.height}/0/default.jpg`;
|
|
632
632
|
}
|
|
633
633
|
return `${i}/full/full/0/default.jpg`;
|
|
634
634
|
}
|
|
635
635
|
return `${i}/full/!${t},${r}/0/default.jpg`;
|
|
636
|
-
}, de = (e, t, r = { minSize: 400 }) => {
|
|
637
|
-
const
|
|
638
|
-
if (typeof
|
|
639
|
-
console.warn(`Level 0 image service does not support custom region URLs: ${
|
|
636
|
+
}, de = (e, t, r = 0, i = { minSize: 400 }) => {
|
|
637
|
+
const n = y(e, "id"), s = e.profile || "";
|
|
638
|
+
if (typeof s == "string" && (s.includes("level0") || s.includes("level:0"))) {
|
|
639
|
+
console.warn(`Level 0 image service does not support custom region URLs: ${n}`);
|
|
640
640
|
return;
|
|
641
641
|
}
|
|
642
|
-
const { x:
|
|
643
|
-
let
|
|
644
|
-
|
|
645
|
-
const
|
|
646
|
-
return `${
|
|
647
|
-
}, pt = (e) => (t, r = { minSize: 400 }) => {
|
|
642
|
+
const { x: c, y: p, w: o, h: u } = t, { minSize: f = 400, maxSize: v } = i, g = r % 180 !== 0 ? u / o : o / u, L = g < 1;
|
|
643
|
+
let h = Math.ceil(L ? f / g : f), m = Math.ceil(L ? f : f / g);
|
|
644
|
+
v && (m > v || h > v) && (L ? (h = Math.min(h, v), m = Math.ceil(h * g)) : (m = Math.min(m, v), h = Math.ceil(m / g)));
|
|
645
|
+
const d = `${Math.round(c)},${Math.round(p)},${Math.round(o)},${Math.round(u)}`;
|
|
646
|
+
return `${n}/${d}/!${m},${h}/${r}/default.jpg`;
|
|
647
|
+
}, pt = (e) => (t, r = 0, i = { minSize: 400 }) => {
|
|
648
648
|
if (e.type === "dynamic")
|
|
649
|
-
return de(e.service, t, r);
|
|
649
|
+
return de(e.service, t, r, i);
|
|
650
650
|
console.error("Level 0 or static image canvas: unsupported");
|
|
651
651
|
}, vt = (e, t, r) => (i = 800) => {
|
|
652
652
|
if (!e || !t) return;
|
|
653
|
-
const n = e / t, s = n < 1, a = Math.ceil(s ? i / n : i),
|
|
654
|
-
return D(r,
|
|
653
|
+
const n = e / t, s = n < 1, a = Math.ceil(s ? i / n : i), c = Math.ceil(s ? i : i / n);
|
|
654
|
+
return D(r, c, a);
|
|
655
655
|
}, ht = (e) => () => fetch(e).then((t) => t.json()).then((t) => {
|
|
656
656
|
const r = t.width, i = t.height;
|
|
657
657
|
return r !== void 0 && i !== void 0 ? { width: r, height: i } : void 0;
|
|
658
658
|
}), ye = (e, t = []) => (r = 400) => {
|
|
659
659
|
const { width: i, height: n } = e;
|
|
660
660
|
if (!i || !n) return;
|
|
661
|
-
const s = i / n, a = s < 1,
|
|
661
|
+
const s = i / n, a = s < 1, c = Math.ceil(a ? r / s : r), p = Math.ceil(a ? r : r / s);
|
|
662
662
|
if (e.thumbnail && e.thumbnail.length > 0) {
|
|
663
663
|
const o = e.thumbnail[0];
|
|
664
664
|
if ("service" in o && Array.isArray(o.service)) {
|
|
665
|
-
const
|
|
666
|
-
if (
|
|
667
|
-
return D(
|
|
665
|
+
const u = o.service.find((f) => ot(f));
|
|
666
|
+
if (u)
|
|
667
|
+
return D(u, p, c);
|
|
668
668
|
}
|
|
669
669
|
if ("id" in o) return o.id;
|
|
670
670
|
}
|
|
671
671
|
for (const o of t) {
|
|
672
672
|
if (o.type === "dynamic" || o.type === "level0")
|
|
673
|
-
return D(o.service, p,
|
|
673
|
+
return D(o.service, p, c);
|
|
674
674
|
if (o.type === "static")
|
|
675
675
|
return o.url;
|
|
676
676
|
}
|
|
677
677
|
}, Ae = (e) => {
|
|
678
|
-
const { format: t, height: r, width: i } = e, n =
|
|
678
|
+
const { format: t, height: r, width: i } = e, n = y(e, "id"), s = (e.service || []).find(ot), a = s ? ct(s) : void 0;
|
|
679
679
|
if (s && a) {
|
|
680
|
-
const
|
|
680
|
+
const c = at(y(s, "id")), p = {
|
|
681
681
|
source: e,
|
|
682
682
|
type: a.profileLevel === 0 ? "level0" : "dynamic",
|
|
683
683
|
service: s,
|
|
684
684
|
width: i,
|
|
685
685
|
height: r,
|
|
686
686
|
majorVersion: a.majorVersion,
|
|
687
|
-
serviceUrl:
|
|
687
|
+
serviceUrl: c,
|
|
688
688
|
getImageURL: vt(i, r, s),
|
|
689
|
-
getPixelSize: ht(
|
|
689
|
+
getPixelSize: ht(c)
|
|
690
690
|
};
|
|
691
691
|
return a.profileLevel === 0 ? p : {
|
|
692
692
|
...p,
|
|
@@ -714,57 +714,57 @@ const at = (e) => e.endsWith("/info.json") ? e : `${e.endsWith("/") ? e : `${e}/
|
|
|
714
714
|
}]
|
|
715
715
|
}).traverseCanvas(e), t;
|
|
716
716
|
}, be = (e) => () => {
|
|
717
|
-
const t = /* @__PURE__ */ new Map(), r = (o,
|
|
718
|
-
const
|
|
717
|
+
const t = /* @__PURE__ */ new Map(), r = (o, u, f = 0) => {
|
|
718
|
+
const v = {
|
|
719
719
|
id: o.id,
|
|
720
720
|
type: "range",
|
|
721
721
|
source: o,
|
|
722
722
|
children: [],
|
|
723
723
|
navItems: [],
|
|
724
724
|
navSections: [],
|
|
725
|
-
parent:
|
|
726
|
-
level:
|
|
725
|
+
parent: u,
|
|
726
|
+
level: f,
|
|
727
727
|
getLabel: o.getLabel
|
|
728
728
|
};
|
|
729
|
-
o.items && o.items.length > 0 && o.items.forEach((
|
|
730
|
-
if (
|
|
731
|
-
const
|
|
732
|
-
|
|
729
|
+
o.items && o.items.length > 0 && o.items.forEach((h) => {
|
|
730
|
+
if (h.source.type === "Range") {
|
|
731
|
+
const d = r(h, v, f + 1);
|
|
732
|
+
v.children.push(d);
|
|
733
733
|
} else {
|
|
734
|
-
const
|
|
735
|
-
id:
|
|
734
|
+
const m = {
|
|
735
|
+
id: h.id,
|
|
736
736
|
type: "canvas",
|
|
737
|
-
source:
|
|
737
|
+
source: h,
|
|
738
738
|
children: [],
|
|
739
739
|
navItems: [],
|
|
740
740
|
navSections: [],
|
|
741
|
-
parent:
|
|
742
|
-
level:
|
|
743
|
-
getLabel:
|
|
741
|
+
parent: v,
|
|
742
|
+
level: f + 1,
|
|
743
|
+
getLabel: h.getLabel
|
|
744
744
|
};
|
|
745
|
-
|
|
745
|
+
v.children.push(m), t.set(m.id, m);
|
|
746
746
|
}
|
|
747
747
|
});
|
|
748
|
-
const
|
|
749
|
-
return
|
|
748
|
+
const l = v.children.map((h) => h.type === "canvas" ? h.source : h.children.length === 1 && h.children[0].type === "canvas" ? h.children[0].source : h.source), g = l.filter((h) => h.source.type === "Canvas"), L = l.filter((h) => h.source.type === "Range");
|
|
749
|
+
return v.navItems.push(...g), v.navSections.push(...L), t.set(v.id, v), v;
|
|
750
750
|
};
|
|
751
751
|
return { root: e.filter((o) => {
|
|
752
|
-
var
|
|
753
|
-
return (
|
|
752
|
+
var u;
|
|
753
|
+
return (u = o.source.behavior) == null ? void 0 : u.includes("top");
|
|
754
754
|
}).map((o) => r(o, void 0)), enumerateNodes: (o) => {
|
|
755
|
-
const
|
|
756
|
-
return o ?
|
|
755
|
+
const u = Array.from(t.values());
|
|
756
|
+
return o ? u.filter((f) => f.type === o) : u;
|
|
757
757
|
}, getBreadcrumbs: (o) => {
|
|
758
|
-
const
|
|
759
|
-
if (!
|
|
760
|
-
const
|
|
761
|
-
return u
|
|
758
|
+
const u = t.get(o);
|
|
759
|
+
if (!u) return [];
|
|
760
|
+
const f = (v, l = []) => v.parent ? f(v.parent, [v, ...l]) : [v, ...l];
|
|
761
|
+
return f(u);
|
|
762
762
|
}, getNavParent: (o) => {
|
|
763
|
-
var
|
|
764
|
-
const
|
|
765
|
-
if (!
|
|
766
|
-
const { parent:
|
|
767
|
-
return
|
|
763
|
+
var v, l;
|
|
764
|
+
const u = t.get(o);
|
|
765
|
+
if (!u || u.type !== "canvas" || ((v = u.parent) == null ? void 0 : v.type) !== "range") return;
|
|
766
|
+
const { parent: f } = u;
|
|
767
|
+
return f.children.length === 1 && f.children[0].type === "canvas" ? ((l = f.parent) == null ? void 0 : l.type) === "range" ? f.parent.source : void 0 : f.source;
|
|
768
768
|
}, getNode: (o) => t.get(o) };
|
|
769
769
|
}, Re = async (e) => {
|
|
770
770
|
try {
|
|
@@ -820,7 +820,7 @@ const at = (e) => e.endsWith("/info.json") ? e : `${e.endsWith("/") ? e : `${e}/
|
|
|
820
820
|
code: "INVALID_MANIFEST",
|
|
821
821
|
message: "Missing @context"
|
|
822
822
|
};
|
|
823
|
-
const i =
|
|
823
|
+
const i = y(e, "id");
|
|
824
824
|
if (!i)
|
|
825
825
|
return {
|
|
826
826
|
type: "error",
|
|
@@ -829,7 +829,7 @@ const at = (e) => e.endsWith("/info.json") ? e : `${e.endsWith("/") ? e : `${e}/
|
|
|
829
829
|
};
|
|
830
830
|
if (r.includes("presentation/2") || r.includes("presentation/3") || r.includes("shared-canvas")) {
|
|
831
831
|
const n = r.includes("presentation/3") ? 3 : 2;
|
|
832
|
-
return
|
|
832
|
+
return y(e, "type").includes("Collection") ? {
|
|
833
833
|
type: "collection",
|
|
834
834
|
url: t || i,
|
|
835
835
|
resource: Le(e, n)
|
|
@@ -878,43 +878,43 @@ const at = (e) => e.endsWith("/info.json") ? e : `${e.endsWith("/") ? e : `${e}/
|
|
|
878
878
|
};
|
|
879
879
|
}, Se = (e, t) => {
|
|
880
880
|
const r = (a) => {
|
|
881
|
-
const
|
|
881
|
+
const c = [], p = [];
|
|
882
882
|
new N({
|
|
883
|
-
canvas: [(
|
|
884
|
-
|
|
883
|
+
canvas: [(l) => {
|
|
884
|
+
l.items && c.push(l);
|
|
885
885
|
}],
|
|
886
|
-
range: [(
|
|
887
|
-
|
|
886
|
+
range: [(l) => {
|
|
887
|
+
l.type === "Range" && p.push(l);
|
|
888
888
|
}]
|
|
889
889
|
}).traverseManifest(a);
|
|
890
|
-
const
|
|
891
|
-
const g = Ce(
|
|
890
|
+
const u = c.map((l) => {
|
|
891
|
+
const g = Ce(l);
|
|
892
892
|
return {
|
|
893
|
-
source:
|
|
894
|
-
id:
|
|
895
|
-
width:
|
|
896
|
-
height:
|
|
893
|
+
source: l,
|
|
894
|
+
id: l.id,
|
|
895
|
+
width: l.width,
|
|
896
|
+
height: l.height,
|
|
897
897
|
images: g,
|
|
898
|
-
annotations:
|
|
898
|
+
annotations: l.annotations || [],
|
|
899
899
|
getImageURL: g.length > 0 ? g[0].getImageURL : () => {
|
|
900
900
|
},
|
|
901
|
-
getLabel: x(
|
|
902
|
-
getMetadata: k(
|
|
903
|
-
getThumbnailURL: ye(
|
|
901
|
+
getLabel: x(l),
|
|
902
|
+
getMetadata: k(l),
|
|
903
|
+
getThumbnailURL: ye(l, g)
|
|
904
904
|
};
|
|
905
|
-
}),
|
|
906
|
-
const g =
|
|
905
|
+
}), f = (l) => {
|
|
906
|
+
const g = l.items || [], L = g.filter((d) => d.type === "Canvas").map((d) => u.find((M) => M.id === d.id)).filter(Boolean), h = g.filter((d) => d.type === "Range").map((d) => f(d)), m = [...L, ...h];
|
|
907
907
|
return {
|
|
908
|
-
source:
|
|
909
|
-
id:
|
|
908
|
+
source: l,
|
|
909
|
+
id: l.id,
|
|
910
910
|
// Maintain original order
|
|
911
|
-
items: g.map((
|
|
912
|
-
canvases:
|
|
913
|
-
ranges:
|
|
914
|
-
getLabel: x(
|
|
911
|
+
items: g.map((d) => m.find((M) => M.id === d.id)),
|
|
912
|
+
canvases: L,
|
|
913
|
+
ranges: h,
|
|
914
|
+
getLabel: x(l)
|
|
915
915
|
};
|
|
916
|
-
},
|
|
917
|
-
return { canvases:
|
|
916
|
+
}, v = p.map((l) => f(l));
|
|
917
|
+
return { canvases: u, ranges: v };
|
|
918
918
|
}, i = t === 2 ? st(e) : e, { canvases: n, ranges: s } = r(i);
|
|
919
919
|
return {
|
|
920
920
|
source: i,
|
|
@@ -927,9 +927,9 @@ const at = (e) => e.endsWith("/info.json") ? e : `${e.endsWith("/") ? e : `${e}/
|
|
|
927
927
|
getTableOfContents: be(s)
|
|
928
928
|
};
|
|
929
929
|
}, Ie = (e) => {
|
|
930
|
-
const { width: t, height: r, format: i } = e, n =
|
|
930
|
+
const { width: t, height: r, format: i } = e, n = y(e, "id"), s = ct(e);
|
|
931
931
|
if (s) {
|
|
932
|
-
const a = at(
|
|
932
|
+
const a = at(y(e, "id")), c = {
|
|
933
933
|
source: e,
|
|
934
934
|
type: s.profileLevel === 0 ? "level0" : "dynamic",
|
|
935
935
|
service: e,
|
|
@@ -940,9 +940,9 @@ const at = (e) => e.endsWith("/info.json") ? e : `${e.endsWith("/") ? e : `${e}/
|
|
|
940
940
|
getImageURL: vt(t, r, e),
|
|
941
941
|
getPixelSize: ht(a)
|
|
942
942
|
};
|
|
943
|
-
return s.profileLevel === 0 ?
|
|
944
|
-
...
|
|
945
|
-
getRegionURL: pt(
|
|
943
|
+
return s.profileLevel === 0 ? c : {
|
|
944
|
+
...c,
|
|
945
|
+
getRegionURL: pt(c)
|
|
946
946
|
};
|
|
947
947
|
} else
|
|
948
948
|
return {
|
|
@@ -964,7 +964,7 @@ export {
|
|
|
964
964
|
x as getLabel,
|
|
965
965
|
k as getMetadata,
|
|
966
966
|
ht as getPixelSizeFromServiceUrl,
|
|
967
|
-
|
|
967
|
+
y as getPropertyValue,
|
|
968
968
|
pt as getRegionURL,
|
|
969
969
|
de as getRegionURLFromService,
|
|
970
970
|
lt as getStaticImagePixelSize,
|
package/package.json
CHANGED
|
@@ -90,6 +90,7 @@ export const getImageURLFromService = (
|
|
|
90
90
|
export const getRegionURLFromService = (
|
|
91
91
|
service: Service,
|
|
92
92
|
bounds: Bounds,
|
|
93
|
+
rotation = 0, // 0, 90, 180, 270
|
|
93
94
|
opts: GetRegionURLOpts = { minSize: 400 }
|
|
94
95
|
): string | undefined => {
|
|
95
96
|
const id = getPropertyValue(service, 'id');
|
|
@@ -106,7 +107,8 @@ export const getRegionURLFromService = (
|
|
|
106
107
|
const { x, y, w , h } = bounds;
|
|
107
108
|
const { minSize = 400, maxSize } = opts;
|
|
108
109
|
|
|
109
|
-
const
|
|
110
|
+
const isTransposed = rotation % 180 !== 0;
|
|
111
|
+
const aspect = isTransposed ? h / w : w / h;
|
|
110
112
|
const isPortrait = aspect < 1;
|
|
111
113
|
|
|
112
114
|
let height = Math.ceil(isPortrait ? minSize / aspect : minSize);
|
|
@@ -126,17 +128,18 @@ export const getRegionURLFromService = (
|
|
|
126
128
|
}
|
|
127
129
|
|
|
128
130
|
const regionParam = `${Math.round(x)},${Math.round(y)},${Math.round(w)},${Math.round(h)}`;
|
|
129
|
-
return `${id}/${regionParam}/!${width},${height}/
|
|
131
|
+
return `${id}/${regionParam}/!${width},${height}/${rotation}/default.jpg`;
|
|
130
132
|
}
|
|
131
133
|
|
|
132
134
|
export const getRegionURL = (
|
|
133
135
|
image: CozyImageResource
|
|
134
136
|
) => (
|
|
135
137
|
bounds: Bounds,
|
|
138
|
+
rotation = 0,
|
|
136
139
|
opts: GetRegionURLOpts = { minSize: 400 }
|
|
137
140
|
): string | undefined => {
|
|
138
141
|
if (image.type === 'dynamic') {
|
|
139
|
-
return getRegionURLFromService(image.service, bounds, opts);
|
|
142
|
+
return getRegionURLFromService(image.service, bounds, rotation, opts);
|
|
140
143
|
} else {
|
|
141
144
|
console.error('Level 0 or static image canvas: unsupported');
|
|
142
145
|
}
|
package/test/core/canvas.test.ts
CHANGED
|
@@ -1,28 +1,10 @@
|
|
|
1
1
|
import { describe, it, expect } from 'vitest';
|
|
2
2
|
import { Cozy, CozyManifest } from '../../src';
|
|
3
3
|
|
|
4
|
-
import { STATIC_IMAGE
|
|
4
|
+
import { STATIC_IMAGE } from './fixtures';
|
|
5
5
|
|
|
6
6
|
describe('canvas', () => {
|
|
7
7
|
|
|
8
|
-
it('should determine correct pixel size for image service', async () => {
|
|
9
|
-
const result = await Cozy.parseURL(WITH_DIFFERENT_CANVAS_DIMENSIONS);
|
|
10
|
-
expect(result.type).toBe('manifest');
|
|
11
|
-
expect('resource' in result).toBeTruthy();
|
|
12
|
-
|
|
13
|
-
const manifest = (result as any).resource as CozyManifest;
|
|
14
|
-
expect(manifest.canvases.length).toBe(66);
|
|
15
|
-
|
|
16
|
-
const page2 = manifest.canvases[1];
|
|
17
|
-
expect(page2.getLabel()).toBe('Page 2');
|
|
18
|
-
expect(page2.images.length).toBe(1);
|
|
19
|
-
|
|
20
|
-
const image = page2.images[0];
|
|
21
|
-
const { width, height } = await image.getPixelSize();
|
|
22
|
-
expect(width).toBe(3796);
|
|
23
|
-
expect(height).toBe(5910);
|
|
24
|
-
});
|
|
25
|
-
|
|
26
8
|
it('should determine correct pixel size for static image', async () => {
|
|
27
9
|
const result = await Cozy.parseURL(STATIC_IMAGE);
|
|
28
10
|
expect(result.type).toBe('manifest');
|
package/test/core/fixtures.ts
CHANGED
|
@@ -1,10 +1,6 @@
|
|
|
1
1
|
// IIIF cookbook static image
|
|
2
2
|
export const STATIC_IMAGE =
|
|
3
3
|
'https://iiif.io/api/cookbook/recipe/0001-mvm-image/manifest.json';
|
|
4
|
-
|
|
5
|
-
// Manifest that uses `structures` to define a Table of Contents
|
|
6
|
-
export const WITH_STRUCTURES =
|
|
7
|
-
'https://lib.is/IE19255085/manifest';
|
|
8
4
|
|
|
9
5
|
// Manifest that specifies a different size for the canvas
|
|
10
6
|
// then the physical image pixel size
|
package/test/helpers/fixtures.ts
CHANGED
|
@@ -135,4 +135,10 @@ export const TWO_CANVASES_NO_ANNOTATIONS = {
|
|
|
135
135
|
]
|
|
136
136
|
}
|
|
137
137
|
]
|
|
138
|
-
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// With Media Fragment in target URL
|
|
141
|
+
// {
|
|
142
|
+
// "target": "https://cogapplabs.github.io/StoriiiesViewer/demo/grande-jatte/canvases/1#xywh=346,597,8800,4812"
|
|
143
|
+
// }
|
|
144
|
+
export const HAS_FRAGEMENT_TARGET = 'https://raw.githubusercontent.com/cogappLabs/storiiiesViewer/main/docs/demo/grande-jatte.json';
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect } from 'vitest';
|
|
2
|
-
import { Cozy, CozyManifest } from '../../src';
|
|
3
|
-
|
|
4
|
-
import { WITH_STRUCTURES } from './fixtures';
|
|
5
|
-
|
|
6
|
-
describe('manifest', () => {
|
|
7
|
-
|
|
8
|
-
it('should generate proper ToC breadcrumbs', async () => {
|
|
9
|
-
const result = await Cozy.parseURL(WITH_STRUCTURES);
|
|
10
|
-
expect(result.type).toBe('manifest');
|
|
11
|
-
expect('resource' in result).toBeTruthy();
|
|
12
|
-
|
|
13
|
-
const manifest = (result as any).resource as CozyManifest;
|
|
14
|
-
expect(manifest.structure.length > 0).toBeTruthy();
|
|
15
|
-
|
|
16
|
-
/*
|
|
17
|
-
const toc = manifest.getTableOfContents();
|
|
18
|
-
|
|
19
|
-
const breadcrumbs = toc.getBreadcrumbs('https://lib.is/IE19255085/range/range-0-12.json');
|
|
20
|
-
|
|
21
|
-
expect(breadcrumbs.length).toBe(3);
|
|
22
|
-
expect(breadcrumbs[0].getLabel()).toBe('Table of Contents');
|
|
23
|
-
expect(breadcrumbs[1].getLabel()).toBe('Woodcuts full');
|
|
24
|
-
expect(breadcrumbs[2].getLabel()).toBe('f. X2v-f. X3r: woodcut full ')
|
|
25
|
-
*/
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
});
|