cozy-iiif 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -135,6 +135,9 @@ console.log(image.getRegionURL(bounds));
135
135
  // With custom minimum shorted dimension
136
136
  console.log(image.getRegionURL(bounds, 800));
137
137
 
138
+ // Full image with custom minimum shorted dimension
139
+ console.log(image.getImageURL(800));
140
+
138
141
  // Resolves the actual image pixel size from the info.json
139
142
  // or the image file (which may **differ**) from the canvas size!
140
143
  console.log(image.getPixelSize());
@@ -1,6 +1,5 @@
1
1
  import { Canvas } from '@iiif/presentation-3';
2
2
  import { CozyImageResource } from '../types';
3
3
  export declare const getThumbnailURL: (canvas: Canvas, images?: CozyImageResource[]) => (minSize?: number) => string | undefined;
4
- export declare const getImageURL: (canvas: Canvas, images?: CozyImageResource[]) => (minSize?: number) => string | undefined;
5
4
  export declare const normalizeServiceUrl: (url: string) => string;
6
5
  export declare const getImages: (canvas: Canvas) => CozyImageResource[];
@@ -1,12 +1,12 @@
1
1
  import { ImageService2, ImageService3, Service } from '@iiif/presentation-3';
2
- import { Bounds, CozyImageResource } from '../types';
2
+ import { Bounds, CozyImageResource, GetRegionURLOpts } from '../types';
3
3
  type ImageService = ImageService2 | ImageService3;
4
4
  export declare const isImageService: (data: any) => data is ImageService;
5
5
  export declare const parseImageService: (service: Service) => {
6
6
  majorVersion: number;
7
7
  profileLevel: number;
8
8
  } | undefined;
9
- export declare const getImageURLFromService: (service: ImageService2 | ImageService3, width: number, height: number) => string;
10
- export declare const getRegionURLFromService: (service: ImageService2 | ImageService3, bounds: Bounds, minSize: number) => string | undefined;
11
- export declare const getRegionURL: (image: CozyImageResource) => (bounds: Bounds, minSize?: number) => string | undefined;
9
+ export declare const getImageURLFromService: (service: Service, width: number, height: number) => string;
10
+ export declare const getRegionURLFromService: (service: Service, bounds: Bounds, opts?: GetRegionURLOpts) => string | undefined;
11
+ export declare const getRegionURL: (image: CozyImageResource) => (bounds: Bounds, opts?: GetRegionURLOpts) => string | undefined;
12
12
  export {};
package/dist/index.js CHANGED
@@ -1,15 +1,15 @@
1
1
  import { imageSize as ce } from "image-size";
2
- import { g as m, a as j, b as S } from "./resource-DS2brz47.js";
3
- import { c as zt } from "./resource-DS2brz47.js";
4
- var le = "http://library.stanford.edu/iiif/image-api/compliance.html#level0", pe = "http://library.stanford.edu/iiif/image-api/compliance.html#level1", V = "http://library.stanford.edu/iiif/image-api/compliance.html#level2", ve = "http://library.stanford.edu/iiif/image-api/conformance.html#level0", he = "http://library.stanford.edu/iiif/image-api/conformance.html#level1", F = "http://library.stanford.edu/iiif/image-api/conformance.html#level2", ue = "http://library.stanford.edu/iiif/image-api/1.1/compliance.html#level0", fe = "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", me = "http://library.stanford.edu/iiif/image-api/1.1/conformance.html#level0", ge = "http://library.stanford.edu/iiif/image-api/1.1/conformance.html#level1", H = "http://library.stanford.edu/iiif/image-api/1.1/conformance.html#level2", de = "http://iiif.io/api/image/1/level0.json", ye = "http://iiif.io/api/image/1/profiles/level0.json", Ae = "http://iiif.io/api/image/1/level1.json", Ce = "http://iiif.io/api/image/1/profiles/level1.json", J = "http://iiif.io/api/image/1/level2.json", z = "http://iiif.io/api/image/1/profiles/level2.json", be = "http://iiif.io/api/image/2/level0.json", Re = "http://iiif.io/api/image/2/profiles/level0.json", Le = "http://iiif.io/api/image/2/level1.json", we = "http://iiif.io/api/image/2/profiles/level1.json", G = "http://iiif.io/api/image/2/level2.json", K = "http://iiif.io/api/image/2/profiles/level2.json", Ie = "level0", Se = "level1", Q = "level2", xe = "http://iiif.io/api/image/2/level0", Te = "http://iiif.io/api/image/2/level1", X = "http://iiif.io/api/image/2/level2", $e = [X, V, F, W, H, J, z, G, K, Q], Me = [xe, Te, X, le, pe, V, ve, he, F, ue, fe, W, me, ge, H, de, ye, Ae, Ce, J, z, be, Re, Le, we, G, K, Ie, Se, Q], je = Me;
5
- function g(t) {
2
+ import { g, a as j, b as S } from "./resource-DS2brz47.js";
3
+ import { c as Jt } from "./resource-DS2brz47.js";
4
+ var le = "http://library.stanford.edu/iiif/image-api/compliance.html#level0", pe = "http://library.stanford.edu/iiif/image-api/compliance.html#level1", V = "http://library.stanford.edu/iiif/image-api/compliance.html#level2", ve = "http://library.stanford.edu/iiif/image-api/conformance.html#level0", he = "http://library.stanford.edu/iiif/image-api/conformance.html#level1", F = "http://library.stanford.edu/iiif/image-api/conformance.html#level2", ue = "http://library.stanford.edu/iiif/image-api/1.1/compliance.html#level0", fe = "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", me = "http://library.stanford.edu/iiif/image-api/1.1/conformance.html#level0", ge = "http://library.stanford.edu/iiif/image-api/1.1/conformance.html#level1", z = "http://library.stanford.edu/iiif/image-api/1.1/conformance.html#level2", de = "http://iiif.io/api/image/1/level0.json", ye = "http://iiif.io/api/image/1/profiles/level0.json", Ae = "http://iiif.io/api/image/1/level1.json", Ce = "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", be = "http://iiif.io/api/image/2/level0.json", Re = "http://iiif.io/api/image/2/profiles/level0.json", Le = "http://iiif.io/api/image/2/level1.json", we = "http://iiif.io/api/image/2/profiles/level1.json", G = "http://iiif.io/api/image/2/level2.json", K = "http://iiif.io/api/image/2/profiles/level2.json", Ie = "level0", Se = "level1", Q = "level2", xe = "http://iiif.io/api/image/2/level0", Te = "http://iiif.io/api/image/2/level1", X = "http://iiif.io/api/image/2/level2", $e = [X, V, F, W, z, H, J, G, K, Q], Me = [xe, Te, X, le, pe, V, ve, he, F, ue, fe, W, me, ge, z, de, ye, Ae, Ce, H, J, be, Re, Le, we, G, K, Ie, Se, Q], je = Me;
5
+ function d(t) {
6
6
  for (let e in t) (typeof t[e] > "u" || t[e] === null) && delete t[e];
7
7
  return t;
8
8
  }
9
9
  function w(t) {
10
10
  return Array.isArray(t) ? t : t ? [t] : [];
11
11
  }
12
- var ke = Object.defineProperty, Pe = (t, e, r) => e in t ? ke(t, e, { enumerable: !0, configurable: !0, writable: !0, value: r }) : t[e] = r, b = (t, e, r) => (Pe(t, typeof e != "symbol" ? e + "" : e, r), r), N = ["sc:Collection", "sc:Manifest", "sc:Canvas", "sc:AnnotationList", "oa:Annotation", "sc:Range", "sc:Layer", "sc:Sequence", "oa:Choice", "Service", "ContentResource"];
12
+ var ke = Object.defineProperty, Pe = (t, e, r) => e in t ? ke(t, e, { enumerable: !0, configurable: !0, writable: !0, value: r }) : t[e] = r, R = (t, e, r) => (Pe(t, typeof e != "symbol" ? e + "" : e, r), r), N = ["sc:Collection", "sc:Manifest", "sc:Canvas", "sc:AnnotationList", "oa:Annotation", "sc:Range", "sc:Layer", "sc:Sequence", "oa:Choice", "Service", "ContentResource"];
13
13
  function Oe(t) {
14
14
  if (typeof t > "u" || t === null) throw new Error("Null or undefined is not a valid entity.");
15
15
  if (Array.isArray(t)) throw new Error("Array is not a valid entity");
@@ -24,7 +24,7 @@ function Oe(t) {
24
24
  }
25
25
  var Ue = class Y {
26
26
  constructor(e, r = {}) {
27
- b(this, "traversals"), b(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
+ R(this, "traversals"), R(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 };
28
28
  }
29
29
  static all(e) {
30
30
  return new Y({ collection: [e], manifest: [e], canvas: [e], annotationList: [e], sequence: [e], annotation: [e], contentResource: [e], choice: [e], range: [e], service: [e], layer: [e] });
@@ -153,7 +153,7 @@ var Ue = class Y {
153
153
  return typeof n > "u" && !this.options.allowUndefinedReturn ? i : n;
154
154
  }, e);
155
155
  }
156
- }, De = "http://library.stanford.edu/iiif/image-api/compliance.html#level1", Ne = "http://library.stanford.edu/iiif/image-api/compliance.html#level2", Ee = "http://library.stanford.edu/iiif/image-api/conformance.html#level1", qe = "http://library.stanford.edu/iiif/image-api/conformance.html#level2", _e = "http://library.stanford.edu/iiif/image-api/1.1/compliance.html#level1", Be = "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", He = "http://iiif.io/api/image/1/profiles/level1.json", Je = "http://iiif.io/api/image/1/level2.json", ze = "http://iiif.io/api/image/1/profiles/level2.json", Ge = "http://iiif.io/api/image/2/level1.json", Ke = "http://iiif.io/api/image/2/profiles/level1.json", Qe = "http://iiif.io/api/image/2/level2.json", Xe = "http://iiif.io/api/image/2/profiles/level2.json", Ye = "level1", Ze = "level2", et = "http://iiif.io/api/image/2/level1", tt = "http://iiif.io/api/image/2/level2", rt = [et, tt, De, Ne, Ee, qe, _e, Be, Ve, Fe, We, He, Je, ze, Ge, Ke, Qe, Xe, Ye, Ze], k = { attributionLabel: "Attribution", providerId: "http://example.org/provider", providerName: "Unknown" };
156
+ }, De = "http://library.stanford.edu/iiif/image-api/compliance.html#level1", Ne = "http://library.stanford.edu/iiif/image-api/compliance.html#level2", Ee = "http://library.stanford.edu/iiif/image-api/conformance.html#level1", qe = "http://library.stanford.edu/iiif/image-api/conformance.html#level2", _e = "http://library.stanford.edu/iiif/image-api/1.1/compliance.html#level1", Be = "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", ze = "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", Ke = "http://iiif.io/api/image/2/profiles/level1.json", Qe = "http://iiif.io/api/image/2/level2.json", Xe = "http://iiif.io/api/image/2/profiles/level2.json", Ye = "level1", Ze = "level2", et = "http://iiif.io/api/image/2/level1", tt = "http://iiif.io/api/image/2/level2", rt = [et, tt, De, Ne, Ee, qe, _e, Be, Ve, Fe, We, ze, He, Je, Ge, Ke, Qe, Xe, Ye, Ze], k = { attributionLabel: "Attribution", providerId: "http://example.org/provider", providerName: "Unknown" };
157
157
  function it(t) {
158
158
  if (typeof t == "string") return [t];
159
159
  if (!t) return [];
@@ -308,13 +308,13 @@ function ee(t, e) {
308
308
  let r = encodeURI(t.id || t["@id"] || "").trim();
309
309
  return r && e ? `${r}/${e}` : r || (q++, `http://example.org/${t["@type"]}${e ? `/${e}` : ""}/${q}`);
310
310
  }
311
- function A(t) {
311
+ function C(t) {
312
312
  let e = [...t.behavior || []];
313
313
  t.viewingHint && e.push(t.viewingHint);
314
314
  let r;
315
315
  return Array.isArray(t.motivation) ? r = t.motivation.map(E) : t.motivation && (r = E(t.motivation)), { "@context": t["@context"] ? vt(t["@context"]) : void 0, id: (t["@id"] || ee(t)).trim(), type: U(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 };
316
316
  }
317
- function C(t) {
317
+ function b(t) {
318
318
  let [e, r] = lt(t.license), i = [...t.metadata ? ht(t.metadata) : [], ...r];
319
319
  return { rights: e, metadata: i.length ? i : void 0, label: t.label ? I(t.label) : void 0, requiredStatement: t.attribution ? { label: I(k.attributionLabel), value: I(t.attribution) } : void 0, navDate: t.navDate, summary: t.description ? I(t.description) : void 0, thumbnail: ut(t.thumbnail) };
320
320
  }
@@ -333,7 +333,7 @@ function ft(t) {
333
333
  } else i["@id"] && r.push({ id: i["@id"], type: U(i) });
334
334
  return r.length ? r : void 0;
335
335
  }
336
- function R(t) {
336
+ function L(t) {
337
337
  let e = t.related ? Array.isArray(t.related) ? t.related : [t.related] : [], r = t.contentLayer;
338
338
  return { provider: t.logo || e.length ? [{ id: k.providerId, type: "Agent", homepage: e.length ? [e[0]] : void 0, logo: t.logo ? Array.isArray(t.logo) ? t.logo : [t.logo] : void 0, label: I(k.providerName) }] : void 0, partOf: ft(t), rendering: t.rendering, seeAlso: t.seeAlso, start: t.startCanvas, service: t.service ? w(t.service) : void 0, supplementary: r ? [r] : void 0 };
339
339
  }
@@ -341,13 +341,13 @@ function mt(t) {
341
341
  return { chars: t.chars, format: t.format ? t.format : void 0, language: t.language };
342
342
  }
343
343
  function gt(t) {
344
- return g({ ...A(t), ...C(t), ...R(t), items: t.members });
344
+ return d({ ...C(t), ...b(t), ...L(t), items: t.members });
345
345
  }
346
346
  function dt(t) {
347
347
  let e = [], r = [], i;
348
348
  for (let n of t.sequences || []) n.canvases.length && e.push(...n.canvases), n.behavior && r.push(...n.behavior), n.startCanvas && (i = n.startCanvas);
349
- let s = A(t);
350
- return r.length && (s.behavior ? s.behavior.push(...r) : s.behavior = r), g({ ...s, ...C(t), ...R(t), start: i, items: e, structures: yt(t.structures) });
349
+ let s = C(t);
350
+ return r.length && (s.behavior ? s.behavior.push(...r) : s.behavior = r), d({ ...s, ...b(t), ...L(t), start: i, items: e, structures: yt(t.structures) });
351
351
  }
352
352
  function yt(t) {
353
353
  if (!t) return t;
@@ -361,10 +361,10 @@ function yt(t) {
361
361
  return t.filter((i) => r.indexOf(i.id) === -1);
362
362
  }
363
363
  function At(t) {
364
- return g({ ...A(t), ...C(t), ...R(t), annotations: t.otherContent && t.otherContent.length ? t.otherContent : void 0, items: t.images && t.images.length ? [{ id: ee(t, "annotation-page"), type: "AnnotationPage", items: t.images }] : void 0 });
364
+ return d({ ...C(t), ...b(t), ...L(t), annotations: t.otherContent && t.otherContent.length ? t.otherContent : void 0, items: t.images && t.images.length ? [{ id: ee(t, "annotation-page"), type: "AnnotationPage", items: t.images }] : void 0 });
365
365
  }
366
366
  function Ct(t) {
367
- return g({ ...A(t), ...C(t), ...R(t), items: t.resources && t.resources.length ? t.resources : void 0 });
367
+ return d({ ...C(t), ...b(t), ...L(t), items: t.resources && t.resources.length ? t.resources : void 0 });
368
368
  }
369
369
  function bt(t) {
370
370
  return !t.canvases || t.canvases.length === 0 ? { canvases: [], behavior: [] } : { canvases: t.canvases, behavior: t.viewingHint ? [t.viewingHint] : [], startCanvas: t.startCanvas };
@@ -385,28 +385,28 @@ function Rt(t) {
385
385
  return { type: "SpecificResource", source: i, selector: P(r.selector) };
386
386
  } else return encodeURI(r["@id"]).trim();
387
387
  }
388
- return g({ ...A(t), ...C(t), ...R(t), target: e(t.on), body: Array.isArray(t.resource) ? t.resource.map(_) : _(t.resource) });
388
+ return d({ ...C(t), ...b(t), ...L(t), target: e(t.on), body: Array.isArray(t.resource) ? t.resource.map(_) : _(t.resource) });
389
389
  }
390
390
  function _(t) {
391
391
  return t.type === "Choice" ? t : te(t);
392
392
  }
393
393
  function te(t) {
394
394
  let e = t;
395
- return g({ ...A(e), ...C(e), ...R(e), ...mt(e) });
395
+ return d({ ...C(e), ...b(e), ...L(e), ...mt(e) });
396
396
  }
397
397
  function Lt(t) {
398
398
  let e = [];
399
- return t.default && t.default !== "rdf:nil" && e.push(t.default), t.item && t.item !== "rdf:nil" && e.push(...t.item), g({ ...A(t), ...C(t), items: e });
399
+ return t.default && t.default !== "rdf:nil" && e.push(t.default), t.item && t.item !== "rdf:nil" && e.push(...t.item), d({ ...C(t), ...b(t), items: e });
400
400
  }
401
401
  function wt(t) {
402
- return g({ ...A(t), ...C(t), ...R(t), items: t.members });
402
+ return d({ ...C(t), ...b(t), ...L(t), items: t.members });
403
403
  }
404
404
  function It(t) {
405
405
  let { "@id": e, "@type": r, "@context": i, profile: s, ...n } = t, o = {};
406
- return e && (o["@id"] = e), o["@type"] = U(t), o["@type"] === "unknown" && (i && i.length && (o["@context"] = i), o["@type"] = "Service"), s && (o.profile = Z(s)), g({ ...o, ...n });
406
+ return e && (o["@id"] = e), o["@type"] = U(t), o["@type"] === "unknown" && (i && i.length && (o["@context"] = i), o["@type"] = "Service"), s && (o.profile = Z(s)), d({ ...o, ...n });
407
407
  }
408
408
  function St(t) {
409
- return g({ ...A(t), ...C(t), ...R(t) });
409
+ return d({ ...C(t), ...b(t), ...L(t) });
410
410
  }
411
411
  var xt = new Ue({ collection: [gt], manifest: [dt], canvas: [At], annotationList: [Ct], sequence: [bt], annotation: [Rt], contentResource: [te], choice: [Lt], range: [wt], service: [It], layer: [St] });
412
412
  function re(t) {
@@ -442,7 +442,7 @@ function Tt(t, e) {
442
442
  }
443
443
  var D = class ie {
444
444
  constructor(e, r = {}) {
445
- b(this, "traversals"), b(this, "options"), b(this, "_traverseManifest", x(this.traverseManifestItems.bind(this), this.traverseLinking.bind(this), this.traverseDescriptive.bind(this), this.traverseLinkedCanvases.bind(this), this.traverseManifestStructures.bind(this), this.traverseInlineAnnotationPages.bind(this))), b(this, "_traverseCanvas", x(this.traverseCanvasItems.bind(this), this.traverseLinking.bind(this), this.traverseDescriptive.bind(this), this.traverseLinkedCanvases.bind(this), this.traverseInlineAnnotationPages.bind(this))), b(this, "_traverseAnnotationPage", x(this.traverseAnnotationPageItems.bind(this), this.traverseLinking.bind(this), this.traverseDescriptive.bind(this))), b(this, "_traverseRange", x(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
+ R(this, "traversals"), R(this, "options"), R(this, "_traverseManifest", x(this.traverseManifestItems.bind(this), this.traverseLinking.bind(this), this.traverseDescriptive.bind(this), this.traverseLinkedCanvases.bind(this), this.traverseManifestStructures.bind(this), this.traverseInlineAnnotationPages.bind(this))), R(this, "_traverseCanvas", x(this.traverseCanvasItems.bind(this), this.traverseLinking.bind(this), this.traverseDescriptive.bind(this), this.traverseLinkedCanvases.bind(this), this.traverseInlineAnnotationPages.bind(this))), R(this, "_traverseAnnotationPage", x(this.traverseAnnotationPageItems.bind(this), this.traverseLinking.bind(this), this.traverseDescriptive.bind(this))), R(this, "_traverseRange", x(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 };
446
446
  }
447
447
  static all(e) {
448
448
  return new ie({ 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] });
@@ -553,15 +553,15 @@ var D = class ie {
553
553
  }
554
554
  }
555
555
  };
556
- const se = (t) => m(t, "type").startsWith("ImageService") || t.profile && t.profile.toString().includes("iiif.io/api/image/"), ne = (t) => {
557
- const e = m(t, "type"), r = m(t, "context");
556
+ const se = (t) => g(t, "type").startsWith("ImageService") || t.profile && t.profile.toString().includes("iiif.io/api/image/"), ne = (t) => {
557
+ const e = g(t, "type"), r = g(t, "context");
558
558
  if (e === "ImageService2" || r != null && r.includes("image/2")) {
559
559
  const i = t, s = ["level0", "level1", "level2"];
560
560
  return { majorVersion: 2, profileLevel: (Array.isArray(i.profile) ? i.profile : [i.profile]).map((c) => s.findIndex((a) => c.toString().includes(a))).filter((c) => c > -1).sort((c, a) => a - c)[0] };
561
561
  } else if (e || r)
562
562
  return { majorVersion: 3, profileLevel: parseInt(t.profile) };
563
563
  }, O = (t, e, r) => {
564
- const i = m(t, "id"), s = t.profile || "";
564
+ const i = g(t, "id"), s = t.profile || "";
565
565
  if (typeof s == "string" && (s.includes("level0") || s.includes("level:0"))) {
566
566
  if ("sizes" in t && Array.isArray(t.sizes)) {
567
567
  const o = t.sizes.sort((c, a) => a.width * a.height - c.width * c.height).filter((c) => c.width * c.height >= e * r)[0];
@@ -571,12 +571,18 @@ const se = (t) => m(t, "type").startsWith("ImageService") || t.profile && t.prof
571
571
  return `${i}/full/full/0/default.jpg`;
572
572
  }
573
573
  return `${i}/full/!${e},${r}/0/default.jpg`;
574
- }, $t = (t, e, r) => {
575
- const i = m(t, "id"), s = t.profile || "";
576
- if (typeof s == "string" && (s.includes("level0") || s.includes("level:0"))) return;
577
- const { x: o, y: c, w: a, h: l } = e, u = a / l, v = u < 1, d = Math.ceil(v ? r / u : r), p = Math.ceil(v ? r : r / u), f = `${Math.round(o)},${Math.round(c)},${Math.round(a)},${Math.round(l)}`;
578
- return `${i}/${f}/!${p},${d}/0/default.jpg`;
579
- }, Mt = (t) => (e, r = 400) => {
574
+ }, $t = (t, e, r = { minSize: 400 }) => {
575
+ const i = g(t, "id"), s = t.profile || "";
576
+ if (typeof s == "string" && (s.includes("level0") || s.includes("level:0"))) {
577
+ console.warn(`Level 0 image service does not support custom region URLs: ${i}`);
578
+ return;
579
+ }
580
+ const { x: o, y: c, w: a, h: p } = e, { minSize: u = 400, maxSize: v } = r, m = a / p, l = m < 1;
581
+ let f = Math.ceil(l ? u / m : u), h = Math.ceil(l ? u : u / m);
582
+ v && (h > v || f > v) && (l ? (f = Math.min(f, v), h = Math.ceil(f * m)) : (h = Math.min(h, v), f = Math.ceil(h / m)));
583
+ const y = `${Math.round(o)},${Math.round(c)},${Math.round(a)},${Math.round(p)}`;
584
+ return `${i}/${y}/!${h},${f}/0/default.jpg`;
585
+ }, Mt = (t) => (e, r = { minSize: 400 }) => {
580
586
  if (t.type === "dynamic")
581
587
  return $t(t.service, e, r);
582
588
  console.error("Level 0 or static image canvas: unsupported");
@@ -585,31 +591,25 @@ const se = (t) => m(t, "type").startsWith("ImageService") || t.profile && t.prof
585
591
  if (!i || !s) return;
586
592
  const n = i / s, o = n < 1, c = Math.ceil(o ? r / n : r), a = Math.ceil(o ? r : r / n);
587
593
  if (t.thumbnail && t.thumbnail.length > 0) {
588
- const l = t.thumbnail[0];
589
- if ("service" in l && Array.isArray(l.service)) {
590
- const u = l.service.find((v) => se(v));
594
+ const p = t.thumbnail[0];
595
+ if ("service" in p && Array.isArray(p.service)) {
596
+ const u = p.service.find((v) => se(v));
591
597
  if (u)
592
598
  return O(u, a, c);
593
599
  }
594
- if ("id" in l) return l.id;
595
- }
596
- for (const l of e) {
597
- if (l.type === "dynamic" || l.type === "level0")
598
- return O(l.service, a, c);
599
- if (l.type === "static")
600
- return l.url;
601
- }
602
- }, kt = (t, e = []) => (r = 800) => {
603
- const { width: i, height: s } = t;
604
- if (!i || !s) return;
605
- const n = i / s, o = n < 1, c = Math.ceil(o ? r / n : r), a = Math.ceil(o ? r : r / n);
606
- for (const l of e) {
607
- if (l.type === "dynamic" || l.type === "level0")
608
- return O(l.service, a, c);
609
- if (l.type === "static")
610
- return l.url;
611
- }
612
- }, ae = (t) => t.endsWith("/info.json") ? t : `${t.endsWith("/") ? t : `${t}/`}info.json`, Pt = (t) => () => fetch(t).then((e) => e.json()).then((e) => {
600
+ if ("id" in p) return p.id;
601
+ }
602
+ for (const p of e) {
603
+ if (p.type === "dynamic" || p.type === "level0")
604
+ return O(p.service, a, c);
605
+ if (p.type === "static")
606
+ return p.url;
607
+ }
608
+ }, ae = (t) => t.endsWith("/info.json") ? t : `${t.endsWith("/") ? t : `${t}/`}info.json`, kt = (t, e, r) => (i = 800) => {
609
+ if (!t || !e) return;
610
+ const s = t / e, n = s < 1, o = Math.ceil(n ? i / s : i), c = Math.ceil(n ? i : i / s);
611
+ return O(r, c, o);
612
+ }, Pt = (t) => () => fetch(t).then((e) => e.json()).then((e) => {
613
613
  const r = e.width, i = e.height;
614
614
  return r !== void 0 && i !== void 0 ? { width: r, height: i } : void 0;
615
615
  }), Ot = (t) => () => {
@@ -619,9 +619,9 @@ const se = (t) => m(t, "type").startsWith("ImageService") || t.profile && t.prof
619
619
  return i.close(), { width: s, height: n };
620
620
  }) : r.arrayBuffer().then((i) => ce(new Uint8Array(i))));
621
621
  }, Ut = (t) => {
622
- const { format: e, height: r, width: i } = t, s = m(t, "id"), n = (t.service || []).find(se), o = n ? ne(n) : void 0;
623
- if (o) {
624
- const c = ae(m(n, "id")), a = {
622
+ const { format: e, height: r, width: i } = t, s = g(t, "id"), n = (t.service || []).find(se), o = n ? ne(n) : void 0;
623
+ if (n && o) {
624
+ const c = ae(g(n, "id")), a = {
625
625
  source: t,
626
626
  type: o.profileLevel === 0 ? "level0" : "dynamic",
627
627
  service: n,
@@ -629,6 +629,7 @@ const se = (t) => m(t, "type").startsWith("ImageService") || t.profile && t.prof
629
629
  height: r,
630
630
  majorVersion: o.majorVersion,
631
631
  serviceUrl: c,
632
+ getImageURL: kt(i, r, n),
632
633
  getPixelSize: Pt(c)
633
634
  };
634
635
  return o.profileLevel === 0 ? a : {
@@ -643,6 +644,7 @@ const se = (t) => m(t, "type").startsWith("ImageService") || t.profile && t.prof
643
644
  height: r,
644
645
  url: s,
645
646
  format: e,
647
+ getImageURL: () => s,
646
648
  getPixelSize: Ot(s)
647
649
  };
648
650
  }, Dt = (t) => {
@@ -656,7 +658,7 @@ const se = (t) => m(t, "type").startsWith("ImageService") || t.profile && t.prof
656
658
  }]
657
659
  }).traverseCanvas(t), e;
658
660
  }, Nt = (t) => () => {
659
- const e = /* @__PURE__ */ new Map(), r = (a, l, u = 0) => {
661
+ const e = /* @__PURE__ */ new Map(), r = (a, p, u = 0) => {
660
662
  const v = {
661
663
  id: a.id,
662
664
  type: "range",
@@ -664,7 +666,7 @@ const se = (t) => m(t, "type").startsWith("ImageService") || t.profile && t.prof
664
666
  children: [],
665
667
  navItems: [],
666
668
  navSections: [],
667
- parent: l,
669
+ parent: p,
668
670
  level: u,
669
671
  getLabel: a.getLabel
670
672
  };
@@ -673,7 +675,7 @@ const se = (t) => m(t, "type").startsWith("ImageService") || t.profile && t.prof
673
675
  const T = r(h, v, u + 1);
674
676
  v.children.push(T);
675
677
  } else {
676
- const L = {
678
+ const y = {
677
679
  id: h.id,
678
680
  type: "canvas",
679
681
  source: h,
@@ -684,23 +686,23 @@ const se = (t) => m(t, "type").startsWith("ImageService") || t.profile && t.prof
684
686
  level: u + 1,
685
687
  getLabel: h.getLabel
686
688
  };
687
- v.children.push(L), e.set(L.id, L);
689
+ v.children.push(y), e.set(y.id, y);
688
690
  }
689
691
  });
690
- const d = v.children.map((h) => h.type === "canvas" ? h.source : h.children.length === 1 && h.children[0].type === "canvas" ? h.children[0].source : h.source), p = d.filter((h) => h.source.type === "Canvas"), f = d.filter((h) => h.source.type === "Range");
691
- return v.navItems.push(...p), v.navSections.push(...f), e.set(v.id, v), v;
692
+ const m = v.children.map((h) => h.type === "canvas" ? h.source : h.children.length === 1 && h.children[0].type === "canvas" ? h.children[0].source : h.source), l = m.filter((h) => h.source.type === "Canvas"), f = m.filter((h) => h.source.type === "Range");
693
+ return v.navItems.push(...l), v.navSections.push(...f), e.set(v.id, v), v;
692
694
  };
693
695
  return { root: t.filter((a) => {
694
- var l;
695
- return (l = a.source.behavior) == null ? void 0 : l.includes("top");
696
+ var p;
697
+ return (p = a.source.behavior) == null ? void 0 : p.includes("top");
696
698
  }).map((a) => r(a, void 0)), enumerateNodes: (a) => {
697
- const l = Array.from(e.values());
698
- return a ? l.filter((u) => u.type === a) : l;
699
+ const p = Array.from(e.values());
700
+ return a ? p.filter((u) => u.type === a) : p;
699
701
  }, getBreadcrumbs: (a) => {
700
- const l = e.get(a);
701
- if (!l) return [];
702
- const u = (v, d = []) => v.parent ? u(v.parent, [v, ...d]) : [v, ...d];
703
- return u(l);
702
+ const p = e.get(a);
703
+ if (!p) return [];
704
+ const u = (v, m = []) => v.parent ? u(v.parent, [v, ...m]) : [v, ...m];
705
+ return u(p);
704
706
  }, getNode: (a) => e.get(a) };
705
707
  }, Et = async (t) => {
706
708
  try {
@@ -756,7 +758,7 @@ const se = (t) => m(t, "type").startsWith("ImageService") || t.profile && t.prof
756
758
  code: "INVALID_MANIFEST",
757
759
  message: "Missing @context"
758
760
  };
759
- const i = m(t, "id");
761
+ const i = g(t, "id");
760
762
  if (!i)
761
763
  return {
762
764
  type: "error",
@@ -765,7 +767,7 @@ const se = (t) => m(t, "type").startsWith("ImageService") || t.profile && t.prof
765
767
  };
766
768
  if (r.includes("presentation/2") || r.includes("presentation/3")) {
767
769
  const s = r.includes("presentation/2") ? 2 : 3;
768
- return m(t, "type").includes("Collection") ? {
770
+ return g(t, "type").includes("Collection") ? {
769
771
  type: "collection",
770
772
  url: e || i,
771
773
  resource: qt(t, s)
@@ -816,40 +818,41 @@ const se = (t) => m(t, "type").startsWith("ImageService") || t.profile && t.prof
816
818
  const r = (o) => {
817
819
  const c = [], a = [];
818
820
  new D({
819
- canvas: [(p) => {
820
- p.items && c.push(p);
821
+ canvas: [(l) => {
822
+ l.items && c.push(l);
821
823
  }],
822
- range: [(p) => {
823
- p.type === "Range" && a.push(p);
824
+ range: [(l) => {
825
+ l.type === "Range" && a.push(l);
824
826
  }]
825
827
  }).traverseManifest(o);
826
- const u = c.map((p) => {
827
- const f = Dt(p);
828
+ const u = c.map((l) => {
829
+ const f = Dt(l);
828
830
  return {
829
- source: p,
830
- id: p.id,
831
- width: p.width,
832
- height: p.height,
831
+ source: l,
832
+ id: l.id,
833
+ width: l.width,
834
+ height: l.height,
833
835
  images: f,
834
- annotations: p.annotations || [],
835
- getImageURL: kt(p, f),
836
- getLabel: S(p),
837
- getMetadata: j(p),
838
- getThumbnailURL: jt(p, f)
836
+ annotations: l.annotations || [],
837
+ getImageURL: f.length > 0 ? f[0].getImageURL : () => {
838
+ },
839
+ getLabel: S(l),
840
+ getMetadata: j(l),
841
+ getThumbnailURL: jt(l, f)
839
842
  };
840
- }), v = (p) => {
841
- const f = p.items || [], h = f.filter((y) => y.type === "Canvas").map((y) => u.find(($) => $.id === y.id)).filter(Boolean), L = f.filter((y) => y.type === "Range").map((y) => v(y)), T = [...h, ...L];
843
+ }), v = (l) => {
844
+ const f = l.items || [], h = f.filter((A) => A.type === "Canvas").map((A) => u.find(($) => $.id === A.id)).filter(Boolean), y = f.filter((A) => A.type === "Range").map((A) => v(A)), T = [...h, ...y];
842
845
  return {
843
- source: p,
844
- id: p.id,
846
+ source: l,
847
+ id: l.id,
845
848
  // Maintain original order
846
- items: f.map((y) => T.find(($) => $.id === y.id)),
849
+ items: f.map((A) => T.find(($) => $.id === A.id)),
847
850
  canvases: h,
848
- ranges: L,
849
- getLabel: S(p)
851
+ ranges: y,
852
+ getLabel: S(l)
850
853
  };
851
- }, d = a.map((p) => v(p));
852
- return { canvases: u, ranges: d };
854
+ }, m = a.map((l) => v(l));
855
+ return { canvases: u, ranges: m };
853
856
  }, i = e === 2 ? re(t) : t, { canvases: s, ranges: n } = r(i);
854
857
  return {
855
858
  source: i,
@@ -870,20 +873,19 @@ const se = (t) => m(t, "type").startsWith("ImageService") || t.profile && t.prof
870
873
  width: e,
871
874
  height: r,
872
875
  majorVersion: i.majorVersion,
873
- serviceUrl: ae(m(t, "id"))
876
+ serviceUrl: ae(g(t, "id"))
874
877
  };
875
878
  }, Wt = { parse: oe, parseURL: Et };
876
879
  export {
877
880
  Wt as Cozy,
878
- kt as getImageURL,
879
881
  O as getImageURLFromService,
880
882
  Dt as getImages,
881
883
  S as getLabel,
882
884
  j as getMetadata,
883
- m as getPropertyValue,
885
+ g as getPropertyValue,
884
886
  Mt as getRegionURL,
885
887
  $t as getRegionURLFromService,
886
- zt as getStringValue,
888
+ Jt as getStringValue,
887
889
  Nt as getTableOfContents,
888
890
  jt as getThumbnailURL,
889
891
  se as isImageService,
package/dist/types.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { Manifest, Canvas, ImageService2, ImageService3, IIIFExternalWebResource, Collection, Range, AnnotationPage } from '@iiif/presentation-3';
1
+ import { Manifest, Canvas, IIIFExternalWebResource, Collection, Range, AnnotationPage, Service } from '@iiif/presentation-3';
2
2
  export type CozyParseResult = {
3
3
  type: 'collection';
4
4
  url: string;
@@ -94,6 +94,7 @@ interface BaseImageResource {
94
94
  readonly type: 'static' | 'dynamic' | 'level0';
95
95
  readonly width: number;
96
96
  readonly height: number;
97
+ getImageURL(minSize?: number): string;
97
98
  getPixelSize(): Promise<{
98
99
  width: number;
99
100
  height: number;
@@ -105,15 +106,15 @@ export interface StaticImageResource extends BaseImageResource {
105
106
  }
106
107
  export interface DynamicImageServiceResource extends BaseImageResource {
107
108
  readonly type: 'dynamic';
108
- readonly service: ImageService2 | ImageService3;
109
+ readonly service: Service;
109
110
  readonly serviceUrl: string;
110
111
  readonly majorVersion: number;
111
- getRegionURL(bounds: Bounds, minSize?: number): string;
112
+ getRegionURL(bounds: Bounds, opts?: GetRegionURLOpts): string;
112
113
  }
113
114
  export interface Level0ImageServiceResource extends BaseImageResource {
114
115
  readonly type: 'level0';
115
116
  readonly majorVersion: number;
116
- readonly service: ImageService2 | ImageService3;
117
+ readonly service: Service;
117
118
  readonly serviceUrl: string;
118
119
  }
119
120
  export interface ImageRequestOptions {
@@ -134,4 +135,8 @@ export interface Bounds {
134
135
  w: number;
135
136
  h: number;
136
137
  }
138
+ export interface GetRegionURLOpts {
139
+ minSize?: number;
140
+ maxSize?: number;
141
+ }
137
142
  export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cozy-iiif",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
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",
package/src/Cozy.ts CHANGED
@@ -2,8 +2,7 @@ import type { Canvas, Collection, Manifest, Range } from '@iiif/presentation-3';
2
2
  import { convertPresentation2 } from '@iiif/parser/presentation-2';
3
3
  import { Traverse } from '@iiif/parser';
4
4
  import {
5
- getImages,
6
- getImageURL,
5
+ getImages,
7
6
  getLabel,
8
7
  getMetadata,
9
8
  getPropertyValue,
@@ -15,7 +14,7 @@ import {
15
14
  import type {
16
15
  CozyCanvas,
17
16
  CozyCollection,
18
- CozyCollectionItem,
17
+ CozyCollectionItem,
19
18
  CozyManifest,
20
19
  CozyParseResult,
21
20
  CozyRange,
@@ -194,7 +193,7 @@ const parseManifestResource = (resource: any, majorVersion: number): CozyManifes
194
193
  height: c.height,
195
194
  images,
196
195
  annotations: (c.annotations || []),
197
- getImageURL: getImageURL(c, images),
196
+ getImageURL: images.length > 0 ? images[0].getImageURL : () => undefined,
198
197
  getLabel: getLabel(c),
199
198
  getMetadata: getMetadata(c),
200
199
  getThumbnailURL: getThumbnailURL(c, images)
@@ -1,5 +1,5 @@
1
1
  import { imageSize } from 'image-size';
2
- import type { Canvas, IIIFExternalWebResource } from '@iiif/presentation-3';
2
+ import type { Canvas, IIIFExternalWebResource, Service } from '@iiif/presentation-3';
3
3
  import { Traverse } from '@iiif/parser';
4
4
  import { getPropertyValue } from './resource';
5
5
  import { getImageURLFromService, getRegionURL, isImageService, parseImageService } from './image-service';
@@ -43,9 +43,14 @@ export const getThumbnailURL = (canvas: Canvas, images: CozyImageResource[] = []
43
43
  }
44
44
  }
45
45
 
46
- export const getImageURL = (canvas: Canvas, images: CozyImageResource[] = []) => (minSize = 800) => {
47
- const { width, height } = canvas;
46
+ export const normalizeServiceUrl = (url: string) =>
47
+ url.endsWith('/info.json') ? url : `${url.endsWith('/') ? url : `${url}/`}info.json`;
48
48
 
49
+ const getImageURL = (
50
+ width: number | undefined,
51
+ height: number | undefined,
52
+ service: Service
53
+ ) => (minSize = 800) => {
49
54
  if (!width || !height) return;
50
55
 
51
56
  const aspect = width / height;
@@ -54,18 +59,9 @@ export const getImageURL = (canvas: Canvas, images: CozyImageResource[] = []) =>
54
59
  const h = Math.ceil(isPortrait ? minSize / aspect : minSize);
55
60
  const w = Math.ceil(isPortrait ? minSize : minSize / aspect);
56
61
 
57
- for (const image of images) {
58
- if (image.type === 'dynamic' || image.type === 'level0') {
59
- return getImageURLFromService(image.service, w, h);
60
- } else if (image.type === 'static') {
61
- return image.url;
62
- }
63
- }
62
+ return getImageURLFromService(service!, w, h);
64
63
  }
65
64
 
66
- export const normalizeServiceUrl = (url: string) =>
67
- url.endsWith('/info.json') ? url : `${url.endsWith('/') ? url : `${url}/`}info.json`;
68
-
69
65
  const getPixelSizeFromServiceUrl = (serviceUrl: string) => () =>
70
66
  fetch(serviceUrl).then(res => res.json()).then(data => {
71
67
  const width: number = data.width;
@@ -83,8 +79,7 @@ const getStaticImagePixelSize = (url: string) => () => {
83
79
  bitmap.close();
84
80
  return { width, height }
85
81
  });
86
- } else {
87
- return blob.arrayBuffer().then(buffer =>
82
+ } else { return blob.arrayBuffer().then(buffer =>
88
83
  imageSize(new Uint8Array(buffer)));
89
84
  }
90
85
  });
@@ -99,7 +94,7 @@ const toCozyImageResource = (resource: IIIFExternalWebResource) => {
99
94
 
100
95
  const service = imageService ? parseImageService(imageService) : undefined;
101
96
 
102
- if (service) {
97
+ if (imageService && service) {
103
98
  const serviceUrl = normalizeServiceUrl(getPropertyValue<string>(imageService, 'id'));
104
99
 
105
100
  const image = {
@@ -110,6 +105,7 @@ const toCozyImageResource = (resource: IIIFExternalWebResource) => {
110
105
  height,
111
106
  majorVersion: service.majorVersion,
112
107
  serviceUrl,
108
+ getImageURL: getImageURL(width, height, imageService),
113
109
  getPixelSize: getPixelSizeFromServiceUrl(serviceUrl)
114
110
  } as ImageServiceResource;
115
111
 
@@ -129,6 +125,7 @@ const toCozyImageResource = (resource: IIIFExternalWebResource) => {
129
125
  height,
130
126
  url: id,
131
127
  format,
128
+ getImageURL: () => id,
132
129
  getPixelSize: getStaticImagePixelSize(id)
133
130
  } as StaticImageResource;
134
131
  }
@@ -1,6 +1,6 @@
1
1
  import type { ImageService2, ImageService3, Service } from '@iiif/presentation-3';
2
2
  import { getPropertyValue } from './resource';
3
- import type { Bounds, CozyImageResource } from '../types';
3
+ import type { Bounds, CozyImageResource, GetRegionURLOpts } from '../types';
4
4
 
5
5
  type ImageService = ImageService2 | ImageService3;
6
6
 
@@ -36,7 +36,7 @@ export const parseImageService = (service: Service) => {
36
36
  }
37
37
 
38
38
  export const getImageURLFromService = (
39
- service: ImageService2 | ImageService3,
39
+ service: Service,
40
40
  width: number,
41
41
  height: number
42
42
  ): string => {
@@ -66,9 +66,9 @@ export const getImageURLFromService = (
66
66
  }
67
67
 
68
68
  export const getRegionURLFromService = (
69
- service: ImageService2 | ImageService3,
69
+ service: Service,
70
70
  bounds: Bounds,
71
- minSize: number
71
+ opts: GetRegionURLOpts = { minSize: 400 }
72
72
  ): string | undefined => {
73
73
  const id = getPropertyValue(service, 'id');
74
74
  const compliance = service.profile || '';
@@ -76,16 +76,32 @@ export const getRegionURLFromService = (
76
76
  const isLevel0 = typeof compliance === 'string' &&
77
77
  (compliance.includes('level0') || compliance.includes('level:0'));
78
78
 
79
- // TODO
80
- if (isLevel0) return;
79
+ if (isLevel0) {
80
+ console.warn(`Level 0 image service does not support custom region URLs: ${id}`);
81
+ return;
82
+ }
81
83
 
82
84
  const { x, y, w , h } = bounds;
85
+ const { minSize = 400, maxSize } = opts;
83
86
 
84
87
  const aspect = w / h;
85
88
  const isPortrait = aspect < 1;
86
89
 
87
- const height = Math.ceil(isPortrait ? minSize / aspect : minSize);
88
- const width = Math.ceil(isPortrait ? minSize : minSize / aspect);
90
+ let height = Math.ceil(isPortrait ? minSize / aspect : minSize);
91
+ let width = Math.ceil(isPortrait ? minSize : minSize / aspect);
92
+
93
+ // Apply maxSize constraint if specified
94
+ if (maxSize) {
95
+ if (width > maxSize || height > maxSize) {
96
+ if (isPortrait) {
97
+ height = Math.min(height, maxSize);
98
+ width = Math.ceil(height * aspect);
99
+ } else {
100
+ width = Math.min(width, maxSize);
101
+ height = Math.ceil(width / aspect);
102
+ }
103
+ }
104
+ }
89
105
 
90
106
  const regionParam = `${Math.round(x)},${Math.round(y)},${Math.round(w)},${Math.round(h)}`;
91
107
  return `${id}/${regionParam}/!${width},${height}/0/default.jpg`;
@@ -95,10 +111,10 @@ export const getRegionURL = (
95
111
  image: CozyImageResource
96
112
  ) => (
97
113
  bounds: Bounds,
98
- minSize = 400
114
+ opts: GetRegionURLOpts = { minSize: 400 }
99
115
  ): string | undefined => {
100
116
  if (image.type === 'dynamic') {
101
- return getRegionURLFromService(image.service, bounds, minSize);
117
+ return getRegionURLFromService(image.service, bounds, opts);
102
118
  } else {
103
119
  console.error('Level 0 or static image canvas: unsupported');
104
120
  }
package/src/types.ts CHANGED
@@ -1,12 +1,11 @@
1
1
  import type {
2
2
  Manifest,
3
- Canvas,
4
- ImageService2,
5
- ImageService3,
3
+ Canvas,
6
4
  IIIFExternalWebResource,
7
5
  Collection,
8
6
  Range,
9
- AnnotationPage
7
+ AnnotationPage,
8
+ Service
10
9
  } from '@iiif/presentation-3';
11
10
 
12
11
  export type CozyParseResult =
@@ -169,6 +168,8 @@ interface BaseImageResource {
169
168
 
170
169
  readonly height: number;
171
170
 
171
+ getImageURL(minSize?: number): string;
172
+
172
173
  getPixelSize(): Promise<{ width: number, height: number }>;
173
174
 
174
175
  }
@@ -185,13 +186,13 @@ export interface DynamicImageServiceResource extends BaseImageResource {
185
186
 
186
187
  readonly type: 'dynamic';
187
188
 
188
- readonly service: ImageService2 | ImageService3;
189
+ readonly service: Service;
189
190
 
190
191
  readonly serviceUrl: string;
191
192
 
192
193
  readonly majorVersion: number;
193
194
 
194
- getRegionURL(bounds: Bounds, minSize?: number): string;
195
+ getRegionURL(bounds: Bounds, opts?: GetRegionURLOpts): string;
195
196
 
196
197
  }
197
198
 
@@ -201,7 +202,7 @@ export interface Level0ImageServiceResource extends BaseImageResource {
201
202
 
202
203
  readonly majorVersion: number;
203
204
 
204
- readonly service: ImageService2 | ImageService3;
205
+ readonly service: Service;
205
206
 
206
207
  readonly serviceUrl: string;
207
208
 
@@ -232,4 +233,12 @@ export interface Bounds {
232
233
 
233
234
  h: number;
234
235
 
236
+ }
237
+
238
+ export interface GetRegionURLOpts {
239
+
240
+ minSize?: number;
241
+
242
+ maxSize?: number;
243
+
235
244
  }