UNPKG

cozy-iiif

Version:

A developer-friendly collection of abstractions and utilities built on top of @iiif/presentation-3 and @iiif/parser

79 lines (70 loc) 2.83 kB
import type { Annotation, AnnotationPage } from '@iiif/presentation-3'; import pThrottle from 'p-throttle'; import type { CozyCanvas } from '../types'; const throttle = pThrottle({ limit: 4, interval: 1000 }); const fetchAnnotationPage = (page: AnnotationPage, canvasId?: string): Promise<Annotation[]> => { if (page.items) { // Embedded return Promise.resolve(page.items as Annotation[]); } else if (page.partOf) { // Annotation collection const fetchRecursive = throttle((url: string, annotations: Annotation[] = []): Promise<Annotation[]> => fetch(url).then(res => res.json()).then(data => { const all = [...annotations, ...(data.items || [])]; if (data.next) { return fetchRecursive(data.next, all); } else { return all; } })); if (!Array.isArray(page.partOf)) throw new Error('Referenced annotation collection is invalid'); if (page.partOf.length === 0) { console.warn('Annotation page references 0 collections'); return Promise.resolve([]); } return page.partOf.reduce<Promise<Annotation[]>>((promise, page) => promise.then(all => { if (typeof page.first === 'string') { return fetchRecursive(page.first).then(a => ([...all, ...a])); } else { console.warn('Unsupported `first` arg', page.first); return all; } }), Promise.resolve([])) // Note that collections will list all annotations, not just those on this canvas! .then(all => all.filter(a => isOnThisCanvas(a, canvasId))); } else { // Referenced return fetch(page.id) .then(res => res.json()) .then(data => ((data.items || []) as Annotation[]).filter(a => isOnThisCanvas(a, canvasId))) .catch(error => { console.error(error); console.warn(`Could not resolve referenced annotation page: ${page.id}`) return []; }); } } const isOnThisCanvas = (annotation: Annotation, canvasId?: string) => { if (!canvasId || !annotation.target) return true; const targets = Array.isArray(annotation.target) ? annotation.target : [annotation.target]; return targets.some((target: any) => { if (!('source' in target)) return true; if (typeof target.source === 'string') { return target.source === canvasId; } else { return target.source.id === canvasId; } }); } export const fetchAnnotations = (arg: CozyCanvas | AnnotationPage): Promise<Annotation[]> => { if ('type' in arg && arg.type === 'AnnotationPage') { return fetchAnnotationPage(arg); } else { return (arg as CozyCanvas).annotations.reduce<Promise<Annotation[]>>((promise, page) => promise.then(all => { return fetchAnnotationPage(page, arg.id).then(onThisPage => ([...all, ...onThisPage])); }), Promise.resolve([])); } }