UNPKG

@allmaps/iiif-parser

Version:

Allmaps IIIF parser

122 lines (121 loc) 4.58 kB
import { Manifest2Schema, Manifest3Schema, ManifestSchema } from '../schemas/iiif.js'; import { Image } from './image.js'; import { Canvas } from './canvas.js'; import { parseVersion2String, parseVersion3String, parseVersion2Metadata, filterInvalidMetadata } from '../lib/strings.js'; const ManifestTypeString = 'manifest'; /** * Parsed IIIF Manifest, embedded in a Collection * @class EmbeddedManifest * @property {boolean} embedded - Whether the Manifest is embedded in a Collection * @property {string} [uri] - URI of Manifest * @property {LanguageString} [label] - Label of Manifest * @property {MajorVersion} [majorVersion] - IIIF API version of Manifest * @property {string} [type] - Resource type, equals 'manifest' */ export class EmbeddedManifest { embedded = true; uri; type = ManifestTypeString; label; majorVersion; constructor(parsedManifest) { if ('@type' in parsedManifest) { // IIIF Presentation API 2.0 this.uri = parsedManifest['@id']; this.majorVersion = 2; if (parsedManifest.label) { this.label = parseVersion2String(parsedManifest.label); } } else if ('type' in parsedManifest) { // IIIF Presentation API 3.0 this.uri = parsedManifest.id; this.majorVersion = 3; this.label = parseVersion3String(parsedManifest.label); } else { throw new Error('Unsupported Manifest'); } } } /** * Parsed IIIF Manifest * @class Manifest * @extends EmbeddedManifest * @property {Canvas[]} canvases - Array of parsed canvases * @property {LanguageString} [description] - Description of Manifest * @property {Metadata} [metadata] - Metadata of Manifest */ export class Manifest extends EmbeddedManifest { canvases = []; description; metadata; embedded = false; constructor(parsedManifest) { super(parsedManifest); if ('@type' in parsedManifest) { // IIIF Presentation API 2.0 if (parsedManifest.description) { this.description = parseVersion2String(parsedManifest.description); } this.metadata = filterInvalidMetadata(parseVersion2Metadata(parsedManifest.metadata)); const sequence = parsedManifest.sequences[0]; this.canvases = sequence.canvases.map((canvas) => new Canvas(canvas)); } else if ('type' in parsedManifest) { // IIIF Presentation API 3.0 this.metadata = filterInvalidMetadata(parsedManifest.metadata); this.canvases = parsedManifest.items.map((canvas) => new Canvas(canvas)); } else { throw new Error('Unsupported Manifest'); } } /** * Parses a IIIF resource and returns a [Manifest](#manifest) containing the parsed version * @param {any} iiifManifest - Source data of IIIF Manifest * @param {MajorVersion} [majorVersion=null] - IIIF API version of Manifest. If not provided, it will be determined automatically * @returns {Manifest} Parsed IIIF Manifest * @static */ static parse(iiifManifest, majorVersion = null) { let parsedManifest; if (majorVersion === 2) { parsedManifest = Manifest2Schema.parse(iiifManifest); } else if (majorVersion === 3) { parsedManifest = Manifest3Schema.parse(iiifManifest); } else { parsedManifest = ManifestSchema.parse(iiifManifest); } return new Manifest(parsedManifest); } async fetchAll(fetchFn = globalThis.fetch) { const results = []; for await (const next of this.fetchNext(fetchFn)) { results.push(next); } return results; } async *fetchNext(fetchFn = globalThis.fetch, depth = 0) { for (const canvasIndex in this.canvases) { const canvas = this.canvases[canvasIndex]; const image = canvas.image; if (image.embedded) { const url = `${image.uri}/info.json`; const iiifManifest = await fetchFn(url).then((response) => response.json()); const newImage = Image.parse(iiifManifest); canvas.image = newImage; yield { item: newImage, depth, parent: { uri: this.uri, type: this.type } }; } } } }