cozy-iiif 0.7.1 → 0.7.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.
@@ -11,11 +11,11 @@ export declare const getStaticImagePixelSize: (url: string) => () => Promise<{
11
11
  width: number;
12
12
  height: number;
13
13
  }>;
14
- export declare const getImageURLFromService: (service: Service, width: number, height: number) => string;
14
+ export declare const getImageURLFromService: (service: Service, width: number, height: number, rotation?: number) => string;
15
15
  export declare const getRegionURLFromService: (service: Service, bounds: Bounds, rotation?: number, // 0, 90, 180, 270
16
16
  opts?: GetRegionURLOpts) => string | undefined;
17
17
  export declare const getRegionURL: (image: CozyImageResource) => (bounds: Bounds, rotation?: number, opts?: GetRegionURLOpts) => string | undefined;
18
- export declare const getImageURL: (width: number | undefined, height: number | undefined, service: Service) => (minSize?: number) => string | undefined;
18
+ export declare const getImageURL: (width: number | undefined, height: number | undefined, service: Service) => (minSize?: number, rotation?: number) => string | undefined;
19
19
  export declare const getPixelSizeFromServiceUrl: (serviceUrl: string) => () => Promise<{
20
20
  width: number;
21
21
  height: number;
package/dist/index.js CHANGED
@@ -119,8 +119,8 @@ var N = class F {
119
119
  return t.type === "Choice" && (t.items = t.items.map((i) => this.traverseContentResource(i, t))), j(t) ? this.traverseSpecificResource(t, "ContentResource") : this.traverseType(this.traverseInlineAnnotationPages(this.traverseContentResourceLinking(t)), { parent: r }, this.traversals.contentResource);
120
120
  }
121
121
  traverseSpecificResource(t, r, i) {
122
- let n = t.source;
123
- return typeof t.source == "string" && (n = { id: t.source, type: r || "unknown" }), this.traverseType({ ...t, source: r === "Canvas" || n.type === "Canvas" ? this.traverseType(n, { parent: i }, this.traversals.canvas) : r === "ContentResource" ? this.traverseContentResource(n, { parent: i }) : this.traverseUnknown(n, { parent: i, typeHint: r }) }, { parent: i }, this.traversals.specificResource);
122
+ let s = t.source;
123
+ return typeof t.source == "string" && (s = { id: t.source, type: r || "unknown" }), this.traverseType({ ...t, 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);
124
124
  }
125
125
  traverseRangeRanges(t) {
126
126
  return t.items &&= t.items.map((r) => typeof r == "string" ? this.traverseCanvas({ id: r, type: "Canvas" }, t) : j(r) ? this.traverseSpecificResource(r, "Canvas", t) : r.type === "Manifest" ? this.traverseManifest(r, t) : this.traverseRange(r, t)), t;
@@ -132,18 +132,18 @@ var N = class F {
132
132
  return this.traverseType(this.traverseDescriptive(this.traverseLinking(t)), { parent: r }, this.traversals.agent);
133
133
  }
134
134
  traverseType(t, r, i) {
135
- return i.reduce((n, s) => {
136
- let a = s(n, r);
137
- return a === void 0 && !this.options.allowUndefinedReturn ? n : a;
135
+ return i.reduce((s, n) => {
136
+ let a = n(s, r);
137
+ return a === void 0 && !this.options.allowUndefinedReturn ? s : a;
138
138
  }, t);
139
139
  }
140
140
  traverseService(t, r) {
141
141
  let i = Object.assign({}, t);
142
- return i && i.service && (i.service = A(i.service).map((n) => this.traverseService(n))), this.traverseType(i, { parent: r }, this.traversals.service);
142
+ return i && i.service && (i.service = A(i.service).map((s) => this.traverseService(s))), this.traverseType(i, { parent: r }, this.traversals.service);
143
143
  }
144
144
  traverseUnknown(t, { parent: r, typeHint: i } = {}) {
145
- let n = dt(t, i);
146
- switch (n) {
145
+ let s = dt(t, i);
146
+ switch (s) {
147
147
  case "Collection":
148
148
  return this.traverseCollection(t, r);
149
149
  case "Manifest":
@@ -163,7 +163,7 @@ var N = class F {
163
163
  case "Agent":
164
164
  return this.traverseAgent(t, r);
165
165
  default:
166
- throw Error(`Unknown or unsupported resource type of ${n}`);
166
+ throw Error(`Unknown or unsupported resource type of ${s}`);
167
167
  }
168
168
  }
169
169
  };
@@ -192,10 +192,13 @@ var zt = class et {
192
192
  }
193
193
  traverseCollectionItems(t) {
194
194
  if (this.options.mergeMemberProperties) {
195
- let r = [...(t.manifests || []).map((s) => typeof s == "string" ? { "@id": s, "@type": "sc:Manifest" } : s), ...(t.collections || []).map((s) => typeof s == "string" ? { "@id": s, "@type": "sc:Collection" } : s), ...t.members || []], i = [], n = r.filter((s) => i.includes(s["@id"]) ? !1 : (i.push(s["@id"]), !0));
196
- delete t.collections, delete t.manifests, t.members = n;
195
+ let r = [...(t.manifests || []).map((n) => typeof n == "string" ? { "@id": n, "@type": "sc:Manifest" } : (n["@type"] ||= "sc:Manifest", n)), ...(t.collections || []).map((n) => typeof n == "string" ? { "@id": n, "@type": "sc:Collection" } : n), ...t.members || []], i = [], s = r.filter((n) => i.includes(n["@id"]) ? !1 : (i.push(n["@id"]), !0));
196
+ delete t.collections, delete t.manifests, t.members = s;
197
197
  }
198
- return t.manifests &&= t.manifests.map((r) => this.traverseManifest(typeof r == "string" ? { "@id": r, "@type": "sc:Manifest" } : r)), t.collections &&= t.collections.map((r) => this.traverseCollection(typeof r == "string" ? { "@id": r, "@type": "sc:Collection" } : r)), t.members &&= t.members.map((r) => typeof r == "string" ? r : r["@type"] === "sc:Collection" ? this.traverseCollection(r) : r["@type"] === "sc:Manifest" ? this.traverseManifest(r) : this.traverseUnknown(r)), t;
198
+ return t.manifests &&= t.manifests.map((r) => {
199
+ let i = r;
200
+ return typeof r == "string" && (i = { "@id": r, "@type": "sc:Manifest" }), i["@type"] ||= "sc:Manifest", this.traverseManifest(i);
201
+ }), t.collections &&= t.collections.map((r) => this.traverseCollection(typeof r == "string" ? { "@id": r, "@type": "sc:Collection" } : r)), t.members &&= t.members.map((r) => typeof r == "string" ? r : r["@type"] === "sc:Collection" ? this.traverseCollection(r) : r["@type"] === "sc:Manifest" ? this.traverseManifest(r) : this.traverseUnknown(r)), t;
199
202
  }
200
203
  traverseManifest(t) {
201
204
  return this.traverseType(this.traverseDescriptive(this.traverseLinking(this.traverseManifestItems(t))), this.traversals.manifest);
@@ -285,17 +288,17 @@ var zt = class et {
285
288
  return t.profile ? this.traverseService(t) : t;
286
289
  }
287
290
  traverseImageResource(t) {
288
- let r = Array.isArray(t), i = Array.isArray(t) ? t : [t], n = [];
289
- for (let s of i) typeof s == "string" ? n.push(this.traverseContentResource({ "@id": s, "@type": "dctypes:Image" })) : n.push(this.traverseContentResource(s));
290
- return !r && !this.options.convertPropsToArray ? n[0] : n;
291
+ let r = Array.isArray(t), i = Array.isArray(t) ? t : [t], s = [];
292
+ for (let n of i) typeof n == "string" ? s.push(this.traverseContentResource({ "@id": n, "@type": "dctypes:Image" })) : s.push(this.traverseContentResource(n));
293
+ return !r && !this.options.convertPropsToArray ? s[0] : s;
291
294
  }
292
295
  traverseDescriptive(t) {
293
296
  return t.thumbnail &&= this.traverseImageResource(t.thumbnail), t.logo &&= this.traverseImageResource(t.logo), t;
294
297
  }
295
298
  traverseOneOrMoreServices(t) {
296
- let r = Array.isArray(t), i = Array.isArray(t) ? t : [t], n = [];
297
- for (let s of i) n.push(this.traverseService(s));
298
- return !r && !this.options.convertPropsToArray ? n[0] : n;
299
+ let r = Array.isArray(t), i = Array.isArray(t) ? t : [t], s = [];
300
+ for (let n of i) s.push(this.traverseService(n));
301
+ return !r && !this.options.convertPropsToArray ? s[0] : s;
299
302
  }
300
303
  traverseLinking(t) {
301
304
  return t.related &&= this.traverseOneOrManyType(t.related, this.traversals.contentResource), t.rendering &&= this.traverseOneOrManyType(t.rendering, this.traversals.contentResource), t.service &&= this.traverseOneOrMoreServices(t.service), t.seeAlso &&= this.traverseOneOrManyType(t.seeAlso, this.traversals.contentResource), t.within && (typeof t.within == "string" || (t.within = this.traverseOneOrManyType(t.within, this.traversals.contentResource))), t.startCanvas && (typeof t.startCanvas == "string" ? t.startCanvas = this.traverseType({ "@id": t.startCanvas, "@type": "sc:Canvas" }, this.traversals.canvas) : t.startCanvas && this.traverseType(t.startCanvas, this.traversals.canvas)), t.contentLayer && (typeof t.contentLayer == "string" ? t.contentLayer = this.traverseLayer({ "@id": t.contentLayer, "@type": "sc:Layer" }) : t.contentLayer = this.traverseLayer(t.contentLayer)), t;
@@ -306,9 +309,9 @@ var zt = class et {
306
309
  return t.map((i) => this.traverseType(i, r));
307
310
  }
308
311
  traverseType(t, r) {
309
- return r.reduce((i, n) => {
310
- let s = n(i);
311
- return s === void 0 && !this.options.allowUndefinedReturn ? i : s;
312
+ return r.reduce((i, s) => {
313
+ let n = s(i);
314
+ return n === void 0 && !this.options.allowUndefinedReturn ? i : n;
312
315
  }, t);
313
316
  }
314
317
  };
@@ -329,17 +332,17 @@ function Ft(e) {
329
332
  function I(e, t = "none") {
330
333
  if (!e) return { none: [""] };
331
334
  let r = Ft(e), i = {};
332
- for (let n of r) {
333
- if (typeof n == "string") {
334
- i[t] = i[t] ? i[t] : [], i[t].push(n || "");
335
+ for (let s of r) {
336
+ if (typeof s == "string") {
337
+ i[t] = i[t] ? i[t] : [], i[t].push(s || "");
335
338
  continue;
336
339
  }
337
- if (!n["@language"]) {
338
- i[t] = i[t] ? i[t] : [], i[t].push(n["@value"] || "");
340
+ if (!s["@language"]) {
341
+ i[t] = i[t] ? i[t] : [], i[t].push(s["@value"] || "");
339
342
  continue;
340
343
  }
341
- let s = n["@language"];
342
- i[s] = i[s] ? i[s] : [], i[s].push(n["@value"] || "");
344
+ let n = s["@language"];
345
+ i[n] = i[n] ? i[n] : [], i[n].push(s["@value"] || "");
343
346
  }
344
347
  return Object.keys(i).length === 0 ? { none: [""] } : i;
345
348
  }
@@ -398,14 +401,14 @@ function V(e) {
398
401
  }
399
402
  const Jt = ["Collection", "Manifest", "Annotation", "AnnotationPage", "Range", "Service"];
400
403
  function E(e) {
401
- let t = e["@id"] || e.id, r = e["@type"] || e.type, i = e.profile || void 0, n = e["@context"] || void 0;
404
+ let t = e["@id"] || e.id, r = e["@type"] || e.type, i = e.profile || void 0, s = e["@context"] || void 0;
402
405
  if (i) {
403
- let s = Ht(i);
404
- if (s) return s;
406
+ let n = Ht(i);
407
+ if (n) return n;
405
408
  }
406
- if (n) {
407
- let s = Wt(n);
408
- if (s) return s;
409
+ if (s) {
410
+ let n = Wt(s);
411
+ if (n) return n;
409
412
  }
410
413
  if (r) {
411
414
  if (Array.isArray(r)) {
@@ -413,8 +416,8 @@ function E(e) {
413
416
  if (r.indexOf("cnt:ContentAsText") !== -1) return "TextualBody";
414
417
  r = r[0];
415
418
  }
416
- for (let s of ["sc", "oa", "dcterms", "dctypes", "iiif"]) if (r.startsWith(`${s}:`)) {
417
- r = r.slice(s.length + 1);
419
+ for (let n of ["sc", "oa", "dcterms", "dctypes", "iiif"]) if (r.startsWith(`${n}:`)) {
420
+ r = r.slice(n.length + 1);
418
421
  break;
419
422
  }
420
423
  switch (r) {
@@ -440,16 +443,16 @@ function Kt(e) {
440
443
  return t ? t[0] : e;
441
444
  }
442
445
  function Xt(e, t = "Rights/License", r = "none") {
443
- let i = null, n = [], s = Array.isArray(e) ? e : [e];
444
- for (let a of s) {
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;
446
+ let i = null, s = [], n = Array.isArray(e) ? e : [e];
447
+ for (let a of n) {
448
+ let l = a ? Kt(a) : void 0;
449
+ if (l && (l.indexOf("creativecommons.org") !== -1 || l.indexOf("rightsstatements.org") !== -1)) {
450
+ i = l.startsWith("https://") ? `http://${l.slice(8)}` : l;
448
451
  continue;
449
452
  }
450
- c && n.push({ label: { [r]: [t] }, value: { [r]: [c] } });
453
+ l && s.push({ label: { [r]: [t] }, value: { [r]: [l] } });
451
454
  }
452
- return [i, n];
455
+ return [i, s];
453
456
  }
454
457
  const Yt = ["http://iiif.io/api/presentation/2/context.json", "http://iiif.io/api/image/2/context.json", "http://iiif.io/api/image/1/context.json", "http://library.stanford.edu/iiif/image-api/1.1/context.json", "http://iiif.io/api/search/1/context.json", "http://iiif.io/api/search/0/context.json", "http://iiif.io/api/auth/1/context.json", "http://iiif.io/api/auth/0/context.json", "http://iiif.io/api/annex/openannotation/context.json"];
455
458
  function Qt(e) {
@@ -525,10 +528,10 @@ function se(e) {
525
528
  return y({ ...C(e), ...b(e), ...S(e), ...ie(e), items: ne(e.members) });
526
529
  }
527
530
  function ae(e) {
528
- let t = [], r = [], i, n;
529
- 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);
530
- let s = C(e);
531
- return r.length && (s.behavior ? s.behavior.push(...r) : s.behavior = r), y({ ...s, ...b(e), ...S(e), viewingDirection: n, start: i, items: t, structures: oe(e.structures) });
531
+ let t = [], r = [], i, s;
532
+ for (let a of e.sequences || []) a.canvases.length && t.push(...a.canvases), a.behavior && r.push(...a.behavior), a.viewingDirection && (s = a.viewingDirection), a.startCanvas && (i = a.startCanvas);
533
+ let n = C(e);
534
+ return r.length && (n.behavior ? n.behavior.push(...r) : n.behavior = r), y({ ...n, ...b(e), ...S(e), viewingDirection: s, start: i, items: t, structures: oe(e.structures) });
532
535
  }
533
536
  function oe(e) {
534
537
  if (!e) return e;
@@ -536,8 +539,8 @@ function oe(e) {
536
539
  for (let i of e) t.set(i.id, i);
537
540
  let r = [];
538
541
  for (let i of e) if (i.items) {
539
- let n = i.items.map((s) => typeof s == "string" ? (r.push(s), t.get(s) || s) : s && s.id ? (r.push(s.id), t.get(s.id) || s) : s);
540
- i.items = n;
542
+ let s = i.items.map((n) => typeof n == "string" ? (r.push(n), t.get(n) || n) : n && n.id ? (r.push(n.id), t.get(n.id) || n) : n);
543
+ i.items = s;
541
544
  }
542
545
  return e.filter((i) => r.indexOf(i.id) === -1);
543
546
  }
@@ -583,8 +586,8 @@ function he(e) {
583
586
  return y({ ...C(e), ...b(e), ...S(e), items: e.members });
584
587
  }
585
588
  function fe(e) {
586
- let { "@id": t, "@type": r, "@context": i, profile: n, ...s } = e, a = {};
587
- 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)), y({ ...a, ...s });
589
+ let { "@id": t, "@type": r, "@context": i, profile: s, ...n } = e, a = {};
590
+ return t && (a["@id"] = t), a["@type"] = E(e), a["@type"] === "unknown" && (i && i.length && (a["@context"] = i), a["@type"] = "Service"), s && (a.profile = rt(s)), y({ ...a, ...n });
588
591
  }
589
592
  function ge(e) {
590
593
  return y({ ...C(e), ...b(e), ...S(e) });
@@ -600,85 +603,85 @@ function O(e) {
600
603
  if (e["@type"] == "iiif:ImageApiSelector") return { type: "ImageApiSelector", region: "region" in e ? e.region : void 0, rotation: "rotation" in e ? e.rotation : void 0 };
601
604
  throw Error(`Unsupported selector type: ${e["@type"]}`);
602
605
  }
603
- const at = (e) => e.endsWith("/info.json") ? e : `${e.endsWith("/") ? e : `${e}/`}info.json`, ot = (e) => d(e, "type").startsWith("ImageService") || e.profile?.toString().includes("iiif.io/api/image/"), ct = (e) => {
606
+ const at = (e) => e.endsWith("/info.json") ? e : `${e.endsWith("/") ? e : `${e}/`}info.json`, ot = (e) => d(e, "type")?.startsWith("ImageService") || e.profile?.toString().includes("iiif.io/api/image/"), ct = (e) => {
604
607
  const t = d(e, "type"), r = d(e, "context");
605
608
  if (t === "ImageService2" || r?.includes("image/2")) {
606
- const n = d(e, "profile"), s = ["level0", "level1", "level2"];
607
- 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] };
609
+ const s = d(e, "profile"), n = ["level0", "level1", "level2"];
610
+ return { majorVersion: 2, profileLevel: (Array.isArray(s) ? s : s ? [s] : []).map((c) => n.findIndex((o) => c.toString().includes(o))).filter((c) => c > -1).sort((c, o) => o - c)[0] };
608
611
  } else if (t || r)
609
612
  return { majorVersion: 3, profileLevel: parseInt(e.profile) };
610
613
  }, lt = (e) => () => {
611
614
  const t = typeof window < "u";
612
615
  return fetch(e).then((r) => r.blob()).then((r) => t ? createImageBitmap(r).then((i) => {
613
- const { width: n, height: s } = i;
614
- return i.close(), { width: n, height: s };
616
+ const { width: s, height: n } = i;
617
+ return i.close(), { width: s, height: n };
615
618
  }) : r.arrayBuffer().then((i) => ft(new Uint8Array(i))));
616
- }, D = (e, t, r) => {
617
- const i = d(e, "id"), n = e.profile || "";
619
+ }, D = (e, t, r, i = 0) => {
620
+ const s = d(e, "id"), n = e.profile || "";
618
621
  if (typeof n == "string" && (n.includes("level0") || n.includes("level:0"))) {
619
622
  if ("sizes" in e && Array.isArray(e.sizes)) {
620
- const a = e.sizes.sort((c, p) => p.width * p.height - c.width * c.height).filter((c) => c.width * c.height >= t * r)[0];
621
- if (a)
622
- return `${i}/full/${a.width},${a.height}/0/default.jpg`;
623
+ const l = e.sizes.sort((c, o) => o.width * o.height - c.width * c.height).filter((c) => c.width * c.height >= t * r)[0];
624
+ if (l)
625
+ return `${s}/full/${l.width},${l.height}/0/default.jpg`;
623
626
  }
624
- return `${i}/full/full/0/default.jpg`;
627
+ return `${s}/full/full/0/default.jpg`;
625
628
  }
626
- return `${i}/full/!${t},${r}/0/default.jpg`;
629
+ return `${s}/full/!${t},${r}/${i}/default.jpg`;
627
630
  }, de = (e, t, r = 0, i = { minSize: 400 }) => {
628
- const n = d(e, "id"), s = e.profile || "";
629
- if (typeof s == "string" && (s.includes("level0") || s.includes("level:0"))) {
630
- console.warn(`Level 0 image service does not support custom region URLs: ${n}`);
631
+ const s = d(e, "id"), n = e.profile || "";
632
+ if (typeof n == "string" && (n.includes("level0") || n.includes("level:0"))) {
633
+ console.warn(`Level 0 image service does not support custom region URLs: ${s}`);
631
634
  return;
632
635
  }
633
- const { x: c, y: p, w: o, h: v } = t, { minSize: u = 400, maxSize: f } = i, l = u / Math.min(o, v), g = f ? Math.max(l, f / Math.max(o, v)) : l, w = Math.round(o * g), h = Math.round(v * g), R = (r % 360 + 360) % 360, m = `${Math.round(c)},${Math.round(p)},${Math.round(o)},${Math.round(v)}`;
634
- return `${n}/${m}/!${w},${h}/${R}/default.jpg`;
636
+ const { x: l, y: c, w: o, h: v } = t, { minSize: u = 400, maxSize: f } = i, p = u / Math.min(o, v), g = f ? Math.max(p, f / Math.max(o, v)) : p, w = Math.round(o * g), h = Math.round(v * g), R = (r % 360 + 360) % 360, m = `${Math.round(l)},${Math.round(c)},${Math.round(o)},${Math.round(v)}`;
637
+ return `${s}/${m}/!${w},${h}/${R}/default.jpg`;
635
638
  }, pt = (e) => (t, r = 0, i = { minSize: 400 }) => {
636
639
  if (e.type === "dynamic")
637
640
  return de(e.service, t, r, i);
638
641
  console.error("Level 0 or static image canvas: unsupported");
639
- }, vt = (e, t, r) => (i = 800) => {
642
+ }, vt = (e, t, r) => (i = 800, s = 0) => {
640
643
  if (!e || !t) return;
641
- const n = e / t, s = n < 1, a = Math.ceil(s ? i / n : i), c = Math.ceil(s ? i : i / n);
642
- return D(r, c, a);
644
+ const n = e / t, a = n < 1, l = Math.ceil(a ? i / n : i), c = Math.ceil(a ? i : i / n);
645
+ return D(r, c, l, s);
643
646
  }, ut = (e) => () => fetch(e).then((t) => t.json()).then((t) => {
644
647
  const r = t.width, i = t.height;
645
648
  return r !== void 0 && i !== void 0 ? { width: r, height: i } : void 0;
646
649
  }), ye = (e, t = []) => (r = 400) => {
647
- const { width: i, height: n } = e;
648
- if (!i || !n) return;
649
- const s = i / n, a = s < 1, c = Math.ceil(a ? r / s : r), p = Math.ceil(a ? r : r / s);
650
+ const { width: i, height: s } = e;
651
+ if (!i || !s) return;
652
+ const n = i / s, a = n < 1, l = Math.ceil(a ? r / n : r), c = Math.ceil(a ? r : r / n);
650
653
  if (e.thumbnail && e.thumbnail.length > 0) {
651
654
  const o = e.thumbnail[0];
652
655
  if ("service" in o && Array.isArray(o.service)) {
653
656
  const v = o.service.find((u) => ot(u));
654
657
  if (v)
655
- return D(v, p, c);
658
+ return D(v, c, l);
656
659
  }
657
660
  if ("id" in o) return o.id;
658
661
  }
659
662
  for (const o of t) {
660
663
  if (o.type === "dynamic" || o.type === "level0")
661
- return D(o.service, p, c);
664
+ return D(o.service, c, l);
662
665
  if (o.type === "static")
663
666
  return o.url;
664
667
  }
665
668
  }, Ae = (e) => {
666
- const { format: t, height: r, width: i } = e, n = d(e, "id"), s = (e.service || []).find(ot), a = s ? ct(s) : void 0;
667
- if (s && a) {
668
- const c = at(d(s, "id")), p = {
669
+ const { format: t, height: r, width: i } = e, s = d(e, "id"), n = (e.service || []).find(ot), a = n ? ct(n) : void 0;
670
+ if (n && a) {
671
+ const l = at(d(n, "id")), c = {
669
672
  source: e,
670
673
  type: a.profileLevel === 0 ? "level0" : "dynamic",
671
- service: s,
674
+ service: n,
672
675
  width: i,
673
676
  height: r,
674
677
  majorVersion: a.majorVersion,
675
- serviceUrl: c,
676
- getImageURL: vt(i, r, s),
677
- getPixelSize: ut(c)
678
+ serviceUrl: l,
679
+ getImageURL: vt(i, r, n),
680
+ getPixelSize: ut(l)
678
681
  };
679
- return a.profileLevel === 0 ? p : {
680
- ...p,
681
- getRegionURL: pt(p)
682
+ return a.profileLevel === 0 ? c : {
683
+ ...c,
684
+ getRegionURL: pt(c)
682
685
  };
683
686
  } else
684
687
  return {
@@ -686,18 +689,18 @@ const at = (e) => e.endsWith("/info.json") ? e : `${e.endsWith("/") ? e : `${e}/
686
689
  type: "static",
687
690
  width: i,
688
691
  height: r,
689
- url: n,
692
+ url: s,
690
693
  format: t,
691
- getImageURL: () => n,
692
- getPixelSize: lt(n)
694
+ getImageURL: () => s,
695
+ getPixelSize: lt(s)
693
696
  };
694
697
  }, Ce = (e) => {
695
698
  const t = [];
696
699
  return new N({
697
700
  annotation: [(i) => {
698
701
  if (i.motivation === "painting" || !i.motivation) {
699
- const s = (i.body ? Array.isArray(i.body) ? i.body : [i.body] : []).filter((a) => a.type === "Image");
700
- t.push(...s.map((a) => Ae(a)));
702
+ const n = (i.body ? Array.isArray(i.body) ? i.body : [i.body] : []).filter((a) => a.type === "Image");
703
+ t.push(...n.map((a) => Ae(a)));
701
704
  }
702
705
  }]
703
706
  }).traverseCanvas(e), t;
@@ -733,7 +736,7 @@ const at = (e) => e.endsWith("/info.json") ? e : `${e.endsWith("/") ? e : `${e}/
733
736
  f.children.push(R), t.set(R.id, R);
734
737
  }
735
738
  });
736
- const l = f.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"), w = l.filter((h) => h.source.type === "Range");
739
+ const p = f.children.map((h) => h.type === "canvas" ? h.source : h.children.length === 1 && h.children[0].type === "canvas" ? h.children[0].source : h.source), g = p.filter((h) => h.source.type === "Canvas"), w = p.filter((h) => h.source.type === "Range");
737
740
  return f.navItems.push(...g), f.navSections.push(...w), t.set(f.id, f), f;
738
741
  };
739
742
  return { root: e.filter((o) => o.source.behavior?.includes("top")).map((o) => r(o, void 0)), enumerateNodes: (o) => {
@@ -742,7 +745,7 @@ const at = (e) => e.endsWith("/info.json") ? e : `${e.endsWith("/") ? e : `${e}/
742
745
  }, getBreadcrumbs: (o) => {
743
746
  const v = t.get(o);
744
747
  if (!v) return [];
745
- const u = (f, l = []) => f.parent ? u(f.parent, [f, ...l]) : [f, ...l];
748
+ const u = (f, p = []) => f.parent ? u(f.parent, [f, ...p]) : [f, ...p];
746
749
  return u(v);
747
750
  }, getNavParent: (o) => {
748
751
  const v = t.get(o);
@@ -797,7 +800,7 @@ const at = (e) => e.endsWith("/info.json") ? e : `${e.endsWith("/") ? e : `${e}/
797
800
  };
798
801
  }
799
802
  }, ht = (e, t) => {
800
- const r = Array.isArray(e["@context"]) ? e["@context"].find((n) => n.includes("iiif.io/api/presentation") || n.includes("iiif.io/api/image") || n.includes("shared-canvas")) : e["@context"];
803
+ const r = Array.isArray(e["@context"]) ? e["@context"].find((s) => s.includes("iiif.io/api/presentation") || s.includes("iiif.io/api/image") || s.includes("shared-canvas")) : e["@context"];
801
804
  if (!r)
802
805
  return {
803
806
  type: "error",
@@ -812,23 +815,23 @@ const at = (e) => e.endsWith("/info.json") ? e : `${e.endsWith("/") ? e : `${e}/
812
815
  message: "Missing id property"
813
816
  };
814
817
  if (r.includes("presentation/2") || r.includes("presentation/3") || r.includes("shared-canvas")) {
815
- const n = r.includes("presentation/3") ? 3 : 2;
818
+ const s = r.includes("presentation/3") ? 3 : 2;
816
819
  return d(e, "type").includes("Collection") ? {
817
820
  type: "collection",
818
821
  url: t || i,
819
- resource: Le(e, n)
822
+ resource: Le(e, s)
820
823
  } : {
821
824
  type: "manifest",
822
825
  url: t || i,
823
- resource: Se(e, n)
826
+ resource: Se(e, s)
824
827
  };
825
828
  }
826
829
  if (r.includes("image/2") || r.includes("image/3")) {
827
- const n = Ie(e);
828
- return n ? {
830
+ const s = Ie(e);
831
+ return s ? {
829
832
  type: "iiif-image",
830
833
  url: t || i,
831
- resource: n
834
+ resource: s
832
835
  } : {
833
836
  type: "error",
834
837
  code: "INVALID_MANIFEST",
@@ -841,92 +844,92 @@ const at = (e) => e.endsWith("/info.json") ? e : `${e.endsWith("/") ? e : `${e}/
841
844
  message: "JSON resource is not a recognized IIIF format"
842
845
  };
843
846
  }, Le = (e, t) => {
844
- const r = (s) => {
847
+ const r = (n) => {
845
848
  const a = [];
846
849
  return new N({
847
- manifest: [(p) => a.push(p)]
848
- }).traverseCollection(s), a.map((p) => ({
849
- id: p.id,
850
- type: p.type,
851
- getLabel: x(p),
852
- source: p
850
+ manifest: [(c) => a.push(c)]
851
+ }).traverseCollection(n), a.map((c) => ({
852
+ id: c.id,
853
+ type: c.type,
854
+ getLabel: x(c),
855
+ source: c
853
856
  }));
854
- }, i = t === 2 ? st(e) : e, n = r(i);
857
+ }, i = t === 2 ? st(e) : e, s = r(i);
855
858
  return {
856
859
  source: i,
857
860
  id: i.id,
858
861
  majorVersion: t,
859
- items: n,
862
+ items: s,
860
863
  getLabel: x(i),
861
864
  getMetadata: k(i)
862
865
  };
863
866
  }, Se = (e, t) => {
864
867
  const r = (a) => {
865
- const c = [], p = [];
868
+ const l = [], c = [];
866
869
  new N({
867
- canvas: [(l) => {
868
- l.items && c.push(l);
870
+ canvas: [(p) => {
871
+ p.items && l.push(p);
869
872
  }],
870
- range: [(l) => {
871
- l.type === "Range" && p.push(l);
873
+ range: [(p) => {
874
+ p.type === "Range" && c.push(p);
872
875
  }]
873
876
  }).traverseManifest(a);
874
- const v = c.map((l) => {
875
- const g = Ce(l);
877
+ const v = l.map((p) => {
878
+ const g = Ce(p);
876
879
  return {
877
- source: l,
878
- id: l.id,
879
- width: l.width,
880
- height: l.height,
880
+ source: p,
881
+ id: p.id,
882
+ width: p.width,
883
+ height: p.height,
881
884
  images: g,
882
- annotations: l.annotations || [],
885
+ annotations: p.annotations || [],
883
886
  getImageURL: g.length > 0 ? g[0].getImageURL : () => {
884
887
  },
885
- getLabel: x(l),
886
- getMetadata: k(l),
887
- getThumbnailURL: ye(l, g)
888
+ getLabel: x(p),
889
+ getMetadata: k(p),
890
+ getThumbnailURL: ye(p, g)
888
891
  };
889
- }), u = (l) => {
890
- const g = l.items || [], w = g.filter((m) => m.type === "Canvas").map((m) => v.find((M) => M.id === m.id)).filter(Boolean), h = g.filter((m) => m.type === "Range").map((m) => u(m)), R = [...w, ...h];
892
+ }), u = (p) => {
893
+ const g = p.items || [], w = g.filter((m) => m.type === "Canvas").map((m) => v.find((M) => M.id === m.id)).filter(Boolean), h = g.filter((m) => m.type === "Range").map((m) => u(m)), R = [...w, ...h];
891
894
  return {
892
- source: l,
893
- id: l.id,
895
+ source: p,
896
+ id: p.id,
894
897
  // Maintain original order
895
898
  items: g.map((m) => R.find((M) => M.id === m.id)),
896
899
  canvases: w,
897
900
  ranges: h,
898
- getLabel: x(l)
901
+ getLabel: x(p)
899
902
  };
900
- }, f = p.map((l) => u(l));
903
+ }, f = c.map((p) => u(p));
901
904
  return { canvases: v, ranges: f };
902
- }, i = t === 2 ? st(e) : e, { canvases: n, ranges: s } = r(i);
905
+ }, i = t === 2 ? st(e) : e, { canvases: s, ranges: n } = r(i);
903
906
  return {
904
907
  source: i,
905
908
  id: i.id,
906
909
  majorVersion: t,
907
- canvases: n,
908
- structure: s,
910
+ canvases: s,
911
+ structure: n,
909
912
  getLabel: x(i),
910
913
  getMetadata: k(i),
911
- getTableOfContents: be(s)
914
+ getTableOfContents: be(n)
912
915
  };
913
916
  }, Ie = (e) => {
914
- const { width: t, height: r, format: i } = e, n = d(e, "id"), s = ct(e);
915
- if (s) {
916
- const a = at(d(e, "id")), c = {
917
+ const { width: t, height: r, format: i } = e, s = d(e, "id"), n = ct(e);
918
+ if (n) {
919
+ const a = at(d(e, "id")), l = {
917
920
  source: e,
918
- type: s.profileLevel === 0 ? "level0" : "dynamic",
921
+ type: n.profileLevel === 0 ? "level0" : "dynamic",
919
922
  service: e,
920
923
  width: t,
921
924
  height: r,
922
- majorVersion: s.majorVersion,
925
+ majorVersion: n.majorVersion,
923
926
  serviceUrl: a,
924
927
  getImageURL: vt(t, r, e),
925
928
  getPixelSize: ut(a)
926
929
  };
927
- return s.profileLevel === 0 ? c : {
928
- ...c,
929
- getRegionURL: pt(c)
930
+ return n.profileLevel === 0 ? l : {
931
+ ...l,
932
+ getRegionURL: pt(l)
930
933
  };
931
934
  } else
932
935
  return {
@@ -934,10 +937,10 @@ const at = (e) => e.endsWith("/info.json") ? e : `${e.endsWith("/") ? e : `${e}/
934
937
  type: "static",
935
938
  width: t,
936
939
  height: r,
937
- url: n,
940
+ url: s,
938
941
  format: i,
939
- getImageURL: () => n,
940
- getPixelSize: lt(n)
942
+ getImageURL: () => s,
943
+ getPixelSize: lt(s)
941
944
  };
942
945
  }, Te = { parse: ht, parseURL: Re };
943
946
  export {
package/dist/types.d.ts CHANGED
@@ -61,7 +61,7 @@ export interface CozyCanvas {
61
61
  readonly height: number;
62
62
  readonly images: CozyImageResource[];
63
63
  readonly annotations: AnnotationPage[];
64
- getImageURL(minSize?: number): string;
64
+ getImageURL(minSize?: number, rotation?: number): string;
65
65
  getLabel(locale?: string): string;
66
66
  getMetadata(locale?: string): CozyMetadata[];
67
67
  getThumbnailURL(minSize?: number): string;
@@ -95,7 +95,7 @@ interface BaseImageResource {
95
95
  readonly type: 'static' | 'dynamic' | 'level0';
96
96
  readonly width: number;
97
97
  readonly height: number;
98
- getImageURL(minSize?: number): string;
98
+ getImageURL(minSize?: number, rotation?: number): string;
99
99
  getPixelSize(): Promise<{
100
100
  width: number;
101
101
  height: number;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cozy-iiif",
3
- "version": "0.7.1",
3
+ "version": "0.7.3",
4
4
  "description": "A developer-friendly collection of abstractions and utilities built on top of @iiif/presentation-3 and @iiif/parser",
5
5
  "license": "MIT",
6
6
  "author": "Rainer Simon",
@@ -29,11 +29,11 @@
29
29
  },
30
30
  "devDependencies": {
31
31
  "typescript": "^5.9.3",
32
- "vite": "^7.3.1",
33
- "vitest": "^4.0.18"
32
+ "vite": "^7.3.2",
33
+ "vitest": "^4.1.2"
34
34
  },
35
35
  "dependencies": {
36
- "@iiif/parser": "^2.2.9",
36
+ "@iiif/parser": "^2.2.10",
37
37
  "@iiif/presentation-3": "^2.2.3",
38
38
  "image-size": "^2.0.2",
39
39
  "p-throttle": "^8.1.0",
@@ -11,7 +11,7 @@ export const normalizeServiceUrl = (url: string) =>
11
11
  export const isImageService = (data: any): data is ImageService => {
12
12
  const t = getPropertyValue<string>(data, 'type');
13
13
 
14
- return t.startsWith('ImageService') || (
14
+ return t?.startsWith('ImageService') || (
15
15
  data.profile?.toString().includes('iiif.io/api/image/')
16
16
  );
17
17
  }
@@ -60,7 +60,8 @@ export const getStaticImagePixelSize = (url: string) => () => {
60
60
  export const getImageURLFromService = (
61
61
  service: Service,
62
62
  width: number,
63
- height: number
63
+ height: number,
64
+ rotation: number = 0
64
65
  ): string => {
65
66
  const id = getPropertyValue(service, 'id');
66
67
 
@@ -84,7 +85,7 @@ export const getImageURLFromService = (
84
85
  return `${id}/full/full/0/default.jpg`;
85
86
  }
86
87
 
87
- return `${id}/full/!${width},${height}/0/default.jpg`;
88
+ return `${id}/full/!${width},${height}/${rotation}/default.jpg`;
88
89
  }
89
90
 
90
91
  export const getRegionURLFromService = (
@@ -141,7 +142,7 @@ export const getImageURL = (
141
142
  width: number | undefined,
142
143
  height: number | undefined,
143
144
  service: Service
144
- ) => (minSize = 800) => {
145
+ ) => (minSize = 800, rotation = 0) => {
145
146
  if (!width || !height) return;
146
147
 
147
148
  const aspect = width / height;
@@ -150,7 +151,7 @@ export const getImageURL = (
150
151
  const h = Math.ceil(isPortrait ? minSize / aspect : minSize);
151
152
  const w = Math.ceil(isPortrait ? minSize : minSize / aspect);
152
153
 
153
- return getImageURLFromService(service!, w, h);
154
+ return getImageURLFromService(service!, w, h, rotation);
154
155
  }
155
156
 
156
157
  export const getPixelSizeFromServiceUrl = (serviceUrl: string) => () =>
package/src/types.ts CHANGED
@@ -98,7 +98,7 @@ export interface CozyCanvas {
98
98
 
99
99
  readonly annotations: AnnotationPage[];
100
100
 
101
- getImageURL(minSize?: number): string;
101
+ getImageURL(minSize?: number, rotation?: number): string;
102
102
 
103
103
  getLabel(locale?: string): string;
104
104
 
@@ -170,7 +170,7 @@ interface BaseImageResource {
170
170
 
171
171
  readonly height: number;
172
172
 
173
- getImageURL(minSize?: number): string;
173
+ getImageURL(minSize?: number, rotation?: number): string;
174
174
 
175
175
  getPixelSize(): Promise<{ width: number, height: number }>;
176
176