@canopy-iiif/app 1.5.3 → 1.5.5
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/lib/build/iiif.js +108 -29
- package/lib/iiif/thumbnail.js +48 -0
- package/package.json +1 -1
package/lib/build/iiif.js
CHANGED
|
@@ -28,6 +28,7 @@ const {
|
|
|
28
28
|
buildIiifImageUrlForDimensions,
|
|
29
29
|
findPrimaryCanvasImage,
|
|
30
30
|
buildIiifImageSrcset,
|
|
31
|
+
isLevel0Service,
|
|
31
32
|
} = require("../iiif/thumbnail");
|
|
32
33
|
|
|
33
34
|
const IIIF_CACHE_DIR = path.resolve(".cache/iiif");
|
|
@@ -167,9 +168,29 @@ function ensureThumbnailValue(target, url, width, height) {
|
|
|
167
168
|
return true;
|
|
168
169
|
}
|
|
169
170
|
|
|
171
|
+
function extractResourceThumbnail(resource) {
|
|
172
|
+
try {
|
|
173
|
+
const rawThumb = resource && resource.thumbnail;
|
|
174
|
+
const first = Array.isArray(rawThumb) ? rawThumb[0] : rawThumb;
|
|
175
|
+
if (!first) return null;
|
|
176
|
+
if (typeof first === "string") {
|
|
177
|
+
const trimmed = first.trim();
|
|
178
|
+
return trimmed ? {url: trimmed} : null;
|
|
179
|
+
}
|
|
180
|
+
const id = first.id || first["@id"];
|
|
181
|
+
if (!id) return null;
|
|
182
|
+
const width = typeof first.width === "number" ? first.width : undefined;
|
|
183
|
+
const height = typeof first.height === "number" ? first.height : undefined;
|
|
184
|
+
return {url: String(id), width, height};
|
|
185
|
+
} catch (_) {
|
|
186
|
+
return null;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
170
190
|
async function resolveHeroMedia(manifest) {
|
|
171
191
|
if (!manifest) return null;
|
|
172
192
|
try {
|
|
193
|
+
const manifestThumb = extractResourceThumbnail(manifest);
|
|
173
194
|
const heroSource = (() => {
|
|
174
195
|
if (manifest && manifest.thumbnail) {
|
|
175
196
|
const clone = { ...manifest };
|
|
@@ -191,15 +212,11 @@ async function resolveHeroMedia(manifest) {
|
|
|
191
212
|
const heroService =
|
|
192
213
|
(canvasImage && canvasImage.service) ||
|
|
193
214
|
(heroRep && heroRep.service);
|
|
215
|
+
const serviceIsLevel0 = isLevel0Service(heroService);
|
|
194
216
|
const heroPreferred = buildIiifImageUrlFromService(
|
|
195
|
-
heroService,
|
|
217
|
+
serviceIsLevel0 ? null : heroService,
|
|
196
218
|
HERO_THUMBNAIL_SIZE
|
|
197
219
|
);
|
|
198
|
-
const heroFallbackId = (() => {
|
|
199
|
-
if (canvasImage && canvasImage.id) return String(canvasImage.id);
|
|
200
|
-
if (heroRep && heroRep.id) return String(heroRep.id);
|
|
201
|
-
return '';
|
|
202
|
-
})();
|
|
203
220
|
const heroWidth = (() => {
|
|
204
221
|
if (canvasImage && typeof canvasImage.width === 'number')
|
|
205
222
|
return canvasImage.width;
|
|
@@ -213,21 +230,59 @@ async function resolveHeroMedia(manifest) {
|
|
|
213
230
|
return heroRep.height;
|
|
214
231
|
return undefined;
|
|
215
232
|
})();
|
|
216
|
-
const heroSrcset =
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
233
|
+
const heroSrcset = serviceIsLevel0
|
|
234
|
+
? ''
|
|
235
|
+
: buildIiifImageSrcset(heroService);
|
|
236
|
+
const ogFromService =
|
|
237
|
+
!serviceIsLevel0 && heroService
|
|
238
|
+
? buildIiifImageUrlForDimensions(
|
|
239
|
+
heroService,
|
|
240
|
+
OG_IMAGE_WIDTH,
|
|
241
|
+
OG_IMAGE_HEIGHT
|
|
242
|
+
)
|
|
243
|
+
: '';
|
|
244
|
+
const annotationImageId =
|
|
245
|
+
canvasImage && canvasImage.isImageBody && canvasImage.id
|
|
246
|
+
? String(canvasImage.id)
|
|
247
|
+
: '';
|
|
248
|
+
let heroThumbnail = heroPreferred || '';
|
|
249
|
+
let heroThumbWidth = heroWidth;
|
|
250
|
+
let heroThumbHeight = heroHeight;
|
|
251
|
+
if (!heroThumbnail && manifestThumb && manifestThumb.url) {
|
|
252
|
+
heroThumbnail = manifestThumb.url;
|
|
253
|
+
if (typeof manifestThumb.width === 'number')
|
|
254
|
+
heroThumbWidth = manifestThumb.width;
|
|
255
|
+
if (typeof manifestThumb.height === 'number')
|
|
256
|
+
heroThumbHeight = manifestThumb.height;
|
|
257
|
+
}
|
|
258
|
+
if (!heroThumbnail) {
|
|
259
|
+
if (annotationImageId) {
|
|
260
|
+
heroThumbnail = annotationImageId;
|
|
261
|
+
} else if (!serviceIsLevel0 && heroRep && heroRep.id) {
|
|
262
|
+
heroThumbnail = String(heroRep.id);
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
let ogImage = '';
|
|
266
|
+
let ogImageWidth;
|
|
267
|
+
let ogImageHeight;
|
|
268
|
+
if (ogFromService) {
|
|
269
|
+
ogImage = ogFromService;
|
|
270
|
+
ogImageWidth = OG_IMAGE_WIDTH;
|
|
271
|
+
ogImageHeight = OG_IMAGE_HEIGHT;
|
|
272
|
+
} else if (heroThumbnail) {
|
|
273
|
+
ogImage = heroThumbnail;
|
|
274
|
+
if (typeof heroThumbWidth === 'number') ogImageWidth = heroThumbWidth;
|
|
275
|
+
if (typeof heroThumbHeight === 'number') ogImageHeight = heroThumbHeight;
|
|
276
|
+
}
|
|
224
277
|
return {
|
|
225
|
-
heroThumbnail:
|
|
226
|
-
heroThumbnailWidth:
|
|
227
|
-
heroThumbnailHeight:
|
|
278
|
+
heroThumbnail: heroThumbnail || '',
|
|
279
|
+
heroThumbnailWidth: heroThumbWidth,
|
|
280
|
+
heroThumbnailHeight: heroThumbHeight,
|
|
228
281
|
heroThumbnailSrcset: heroSrcset || '',
|
|
229
282
|
heroThumbnailSizes: heroSrcset ? HERO_IMAGE_SIZES_ATTR : '',
|
|
230
283
|
ogImage: ogImage || '',
|
|
284
|
+
ogImageWidth,
|
|
285
|
+
ogImageHeight,
|
|
231
286
|
};
|
|
232
287
|
} catch (_) {
|
|
233
288
|
return null;
|
|
@@ -987,14 +1042,28 @@ async function ensureFeaturedInCache(cfg) {
|
|
|
987
1042
|
}
|
|
988
1043
|
}
|
|
989
1044
|
if (heroMedia && heroMedia.ogImage) {
|
|
990
|
-
if (entry.ogImage !== heroMedia.ogImage)
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
1045
|
+
if (entry.ogImage !== heroMedia.ogImage) {
|
|
1046
|
+
entry.ogImage = heroMedia.ogImage;
|
|
1047
|
+
touched = true;
|
|
1048
|
+
}
|
|
1049
|
+
if (typeof heroMedia.ogImageWidth === 'number') {
|
|
1050
|
+
if (entry.ogImageWidth !== heroMedia.ogImageWidth) touched = true;
|
|
1051
|
+
entry.ogImageWidth = heroMedia.ogImageWidth;
|
|
1052
|
+
} else if (entry.ogImageWidth !== undefined) {
|
|
1053
|
+
delete entry.ogImageWidth;
|
|
1054
|
+
touched = true;
|
|
1055
|
+
}
|
|
1056
|
+
if (typeof heroMedia.ogImageHeight === 'number') {
|
|
1057
|
+
if (entry.ogImageHeight !== heroMedia.ogImageHeight) touched = true;
|
|
1058
|
+
entry.ogImageHeight = heroMedia.ogImageHeight;
|
|
1059
|
+
} else if (entry.ogImageHeight !== undefined) {
|
|
1060
|
+
delete entry.ogImageHeight;
|
|
1061
|
+
touched = true;
|
|
1062
|
+
}
|
|
994
1063
|
} else if (entry.ogImage !== undefined) {
|
|
995
1064
|
delete entry.ogImage;
|
|
996
|
-
delete entry.ogImageWidth;
|
|
997
|
-
delete entry.ogImageHeight;
|
|
1065
|
+
if (entry.ogImageWidth !== undefined) delete entry.ogImageWidth;
|
|
1066
|
+
if (entry.ogImageHeight !== undefined) delete entry.ogImageHeight;
|
|
998
1067
|
touched = true;
|
|
999
1068
|
}
|
|
1000
1069
|
if (
|
|
@@ -1236,8 +1305,12 @@ async function rebuildManifestIndexFromCache() {
|
|
|
1236
1305
|
}
|
|
1237
1306
|
if (heroMedia.ogImage) {
|
|
1238
1307
|
entry.ogImage = heroMedia.ogImage;
|
|
1239
|
-
|
|
1240
|
-
|
|
1308
|
+
if (typeof heroMedia.ogImageWidth === 'number')
|
|
1309
|
+
entry.ogImageWidth = heroMedia.ogImageWidth;
|
|
1310
|
+
else delete entry.ogImageWidth;
|
|
1311
|
+
if (typeof heroMedia.ogImageHeight === 'number')
|
|
1312
|
+
entry.ogImageHeight = heroMedia.ogImageHeight;
|
|
1313
|
+
else delete entry.ogImageHeight;
|
|
1241
1314
|
}
|
|
1242
1315
|
ensureThumbnailValue(
|
|
1243
1316
|
entry,
|
|
@@ -2006,12 +2079,18 @@ async function buildIiifCollectionPages(CONFIG) {
|
|
|
2006
2079
|
entry.ogImage = heroMedia.ogImage;
|
|
2007
2080
|
touched = true;
|
|
2008
2081
|
}
|
|
2009
|
-
if (
|
|
2010
|
-
entry.ogImageWidth =
|
|
2082
|
+
if (typeof heroMedia.ogImageWidth === 'number') {
|
|
2083
|
+
if (entry.ogImageWidth !== heroMedia.ogImageWidth) touched = true;
|
|
2084
|
+
entry.ogImageWidth = heroMedia.ogImageWidth;
|
|
2085
|
+
} else if (entry.ogImageWidth !== undefined) {
|
|
2086
|
+
delete entry.ogImageWidth;
|
|
2011
2087
|
touched = true;
|
|
2012
2088
|
}
|
|
2013
|
-
if (
|
|
2014
|
-
entry.ogImageHeight =
|
|
2089
|
+
if (typeof heroMedia.ogImageHeight === 'number') {
|
|
2090
|
+
if (entry.ogImageHeight !== heroMedia.ogImageHeight) touched = true;
|
|
2091
|
+
entry.ogImageHeight = heroMedia.ogImageHeight;
|
|
2092
|
+
} else if (entry.ogImageHeight !== undefined) {
|
|
2093
|
+
delete entry.ogImageHeight;
|
|
2015
2094
|
touched = true;
|
|
2016
2095
|
}
|
|
2017
2096
|
} else {
|
package/lib/iiif/thumbnail.js
CHANGED
|
@@ -12,6 +12,30 @@ function arrayify(value) {
|
|
|
12
12
|
return Array.isArray(value) ? value : [value];
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
+
function normalizeBodyType(value) {
|
|
16
|
+
if (!value) return '';
|
|
17
|
+
if (typeof value === 'string') {
|
|
18
|
+
const trimmed = value.trim();
|
|
19
|
+
return trimmed;
|
|
20
|
+
}
|
|
21
|
+
if (Array.isArray(value)) {
|
|
22
|
+
for (const entry of value) {
|
|
23
|
+
const normalized = normalizeBodyType(entry);
|
|
24
|
+
if (normalized) return normalized;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
return '';
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function isImageBodyType(value) {
|
|
31
|
+
if (!value) return false;
|
|
32
|
+
try {
|
|
33
|
+
return /image/i.test(String(value));
|
|
34
|
+
} catch (_) {
|
|
35
|
+
return false;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
15
39
|
function normalizeImageServiceCandidate(candidate) {
|
|
16
40
|
if (!candidate || typeof candidate !== 'object') return null;
|
|
17
41
|
const id = candidate.id || candidate['@id'];
|
|
@@ -41,6 +65,23 @@ function normalizeImageServiceCandidate(candidate) {
|
|
|
41
65
|
};
|
|
42
66
|
}
|
|
43
67
|
|
|
68
|
+
function isLevel0Profile(profile) {
|
|
69
|
+
if (!profile) return false;
|
|
70
|
+
try {
|
|
71
|
+
return /level0/i.test(String(profile));
|
|
72
|
+
} catch (_) {
|
|
73
|
+
return false;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function isLevel0Service(candidate) {
|
|
78
|
+
if (!candidate || typeof candidate !== 'object') return false;
|
|
79
|
+
if (candidate.profile && isLevel0Profile(candidate.profile)) return true;
|
|
80
|
+
const normalized = normalizeImageServiceCandidate(candidate);
|
|
81
|
+
if (!normalized) return false;
|
|
82
|
+
return Boolean(normalized.profile && isLevel0Profile(normalized.profile));
|
|
83
|
+
}
|
|
84
|
+
|
|
44
85
|
function isIiifImageService(candidate) {
|
|
45
86
|
if (!candidate) return false;
|
|
46
87
|
const {type, profile} = candidate;
|
|
@@ -77,6 +118,7 @@ function extractImageService(value, seen = new Set()) {
|
|
|
77
118
|
function normalizeImagePayload(body, canvas) {
|
|
78
119
|
if (!body || typeof body !== 'object') return null;
|
|
79
120
|
const id = body.id || body['@id'];
|
|
121
|
+
const bodyType = normalizeBodyType(body.type || body['@type']);
|
|
80
122
|
const width =
|
|
81
123
|
typeof body.width === 'number'
|
|
82
124
|
? body.width
|
|
@@ -95,6 +137,8 @@ function normalizeImagePayload(body, canvas) {
|
|
|
95
137
|
width,
|
|
96
138
|
height,
|
|
97
139
|
service: service || undefined,
|
|
140
|
+
bodyType: bodyType || undefined,
|
|
141
|
+
isImageBody: Boolean(bodyType && isImageBodyType(bodyType)),
|
|
98
142
|
};
|
|
99
143
|
}
|
|
100
144
|
|
|
@@ -185,6 +229,7 @@ function selectServiceQuality(candidate) {
|
|
|
185
229
|
|
|
186
230
|
function buildIiifImageUrlFromNormalizedService(service, preferredSize = 800) {
|
|
187
231
|
if (!service || !isIiifImageService(service)) return '';
|
|
232
|
+
if (isLevel0Profile(service.profile)) return '';
|
|
188
233
|
const baseId = normalizeServiceBaseId(service.id);
|
|
189
234
|
if (!baseId) return '';
|
|
190
235
|
const size = preferredSize && preferredSize > 0 ? preferredSize : 800;
|
|
@@ -202,6 +247,7 @@ function buildIiifImageUrlFromService(service, preferredSize = 800) {
|
|
|
202
247
|
function buildIiifImageUrlForDimensions(service, width = 1200, height = 630) {
|
|
203
248
|
const normalized = normalizeImageServiceCandidate(service);
|
|
204
249
|
if (!normalized || !isIiifImageService(normalized)) return '';
|
|
250
|
+
if (isLevel0Profile(normalized.profile)) return '';
|
|
205
251
|
const baseId = normalizeServiceBaseId(normalized.id);
|
|
206
252
|
if (!baseId) return '';
|
|
207
253
|
const safeWidth = Math.max(1, Math.floor(Number(width) || 0));
|
|
@@ -214,6 +260,7 @@ function buildIiifImageUrlForDimensions(service, width = 1200, height = 630) {
|
|
|
214
260
|
function buildIiifImageSrcset(service, steps = [360, 640, 960, 1280, 1600]) {
|
|
215
261
|
const normalized = normalizeImageServiceCandidate(service);
|
|
216
262
|
if (!normalized || !isIiifImageService(normalized)) return '';
|
|
263
|
+
if (isLevel0Profile(normalized.profile)) return '';
|
|
217
264
|
const uniqueSteps = Array.from(
|
|
218
265
|
new Set(
|
|
219
266
|
(Array.isArray(steps) ? steps : [])
|
|
@@ -354,4 +401,5 @@ module.exports = {
|
|
|
354
401
|
buildIiifImageUrlForDimensions,
|
|
355
402
|
findPrimaryCanvasImage,
|
|
356
403
|
buildIiifImageSrcset,
|
|
404
|
+
isLevel0Service,
|
|
357
405
|
};
|