From 793036d8349a1bf48d6a0140a04315b6f4e44948 Mon Sep 17 00:00:00 2001 From: Stephen Fraser Date: Thu, 19 Mar 2026 20:11:10 +0000 Subject: [PATCH] Fix for collection items without a type --- .../presentation-2-parser/upgrade.test.ts | 16 +- .../presentation-2/biblissima-collection.json | 381 ++++++++++++++++++ src/presentation-2/traverse.ts | 21 +- 3 files changed, 410 insertions(+), 8 deletions(-) create mode 100644 fixtures/presentation-2/biblissima-collection.json diff --git a/__tests__/presentation-2-parser/upgrade.test.ts b/__tests__/presentation-2-parser/upgrade.test.ts index ebbf288..180f256 100644 --- a/__tests__/presentation-2-parser/upgrade.test.ts +++ b/__tests__/presentation-2-parser/upgrade.test.ts @@ -2,6 +2,7 @@ import { Validator } from '@hyperion-framework/validator'; import { expect } from 'vitest'; import choiceAnnoList from '../../fixtures/presentation-2/anno_list_choice.json'; import artic from '../../fixtures/presentation-2/artic-manifest.json'; +import biblissimaCollection from '../../fixtures/presentation-2/biblissima-collection.json'; import iiifManifest2 from '../../fixtures/presentation-2/biblissima-manifest.json'; import blManifest from '../../fixtures/presentation-2/bl-manifest.json'; import bodleianManifest from '../../fixtures/presentation-2/bodleian-manifest.json'; @@ -17,6 +18,7 @@ import iiifManifest from '../../fixtures/presentation-2/iiif-fixture-manifest.js import iiifManifestInvalid from '../../fixtures/presentation-2/iiif-fixture-manifest.json'; import withDimensions from '../../fixtures/presentation-2/iiif-fixture-manifest-with-dimensions.json'; import loc from '../../fixtures/presentation-2/loc.json'; +import malformedImageAnnotation from '../../fixtures/presentation-2/malformed-image-annotation.json'; import level0manifest from '../../fixtures/presentation-2/manifest-l0.json'; import nestedRanges from '../../fixtures/presentation-2/nested-ranges.json'; import ngaManifest from '../../fixtures/presentation-2/nga-manifest.json'; @@ -33,7 +35,6 @@ import stanfordManifest from '../../fixtures/presentation-2/stanford-manifest.js import goettingen from '../../fixtures/presentation-2/uni-goettingen.json'; import villanovaManifest from '../../fixtures/presentation-2/villanova-manifest.json'; import wikimediaProxy from '../../fixtures/presentation-2/wikimedia-proxy.json'; -import malformedImageAnnotation from '../../fixtures/presentation-2/malformed-image-annotation.json'; import { convertPresentation2, presentation2to3 } from '../../src/presentation-2'; describe('Presentation 2 to 3', () => { @@ -2636,4 +2637,17 @@ describe('Presentation 2 to 3', () => { expect(annotation?.motivation).toEqual('painting'); expect(annotation?.body).toBeDefined(); }); + + test('automatic @type=sc:Manifest for Biblissima Collection', () => { + const result = presentation2to3.traverseCollection(biblissimaCollection as any); + const isValid = validator.validateCollection(result); + + expect(validator.validators.collection!.errors).toEqual(null); + expect(validator.validators.manifest!.errors).toEqual(null); + expect(isValid).toEqual(true); + + const collection = result as any; + expect(collection.type).toEqual('Collection'); + expect(collection.items?.[0].type).toEqual('Manifest'); + }); }); diff --git a/fixtures/presentation-2/biblissima-collection.json b/fixtures/presentation-2/biblissima-collection.json new file mode 100644 index 0000000..df3c749 --- /dev/null +++ b/fixtures/presentation-2/biblissima-collection.json @@ -0,0 +1,381 @@ +{ + "@context": "http://iiif.io/api/presentation/2/context.json", + "@id": "https://biblissima.fr/iiif/collection/gallica-bnf/manuscripts-department/allemand/", + "label": "Allemand", + "@type": "sc:Collection", + "attribution": "IIIF Collection provided by Biblissima.", + "manifests": [ + { + "@id": "https://gallica.bnf.fr/iiif/ark:/12148/btv1b7200024s/manifest.json", + "label": "BnF, Manuscrits, Allemand 305", + "thumbnail": "https://gallica.bnf.fr/ark:/12148/btv1b7200024s/f1.thumbnail", + "related": [ + { + "@id": "https://gallica.bnf.fr/ark:/12148/btv1b7200024s", + "format": "text/html", + "label": "Digital object in Gallica" + }, + { + "@id": "http://archivesetmanuscrits.bnf.fr/ead.html?id=FRBNFEAD000013689", + "format": "text/html", + "label": "Record in BnF Archives and Manuscripts Catalog" + } + ], + "seeAlso": { + "@id": "http://oai.bnf.fr/oai2/OAIHandler?verb=GetRecord&metadataPrefix=oai_dc&identifier=oai:bnf.fr:gallica/ark:/12148/btv1b7200024s", + "format": "application/xml" + }, + "metadata": [ + { + "label": "Repository", + "value": "Bibliothèque nationale de France, Département des Manuscrits" + }, + { + "label": "Complete shelfmark", + "value": "France, Paris, Bibliothèque nationale de France, Département des Manuscrits, Allemand 305" + } + ] + }, + { + "@id": "https://gallica.bnf.fr/iiif/ark:/12148/btv1b525006620/manifest.json", + "label": "BnF, Manuscrits, Allemand 127", + "thumbnail": "https://gallica.bnf.fr/ark:/12148/btv1b525006620/f1.thumbnail", + "related": [ + { + "@id": "https://gallica.bnf.fr/ark:/12148/btv1b525006620", + "format": "text/html", + "label": "Digital object in Gallica" + }, + { + "@id": "http://archivesetmanuscrits.bnf.fr/ead.html?id=FRBNFEAD000025622", + "format": "text/html", + "label": "Record in BnF Archives and Manuscripts Catalog" + } + ], + "seeAlso": { + "@id": "http://oai.bnf.fr/oai2/OAIHandler?verb=GetRecord&metadataPrefix=oai_dc&identifier=oai:bnf.fr:gallica/ark:/12148/btv1b525006620", + "format": "application/xml" + }, + "metadata": [ + { + "label": "Repository", + "value": "Bibliothèque nationale de France, Département des Manuscrits" + }, + { + "label": "Complete shelfmark", + "value": "France, Paris, Bibliothèque nationale de France, Département des Manuscrits, Allemand 127" + } + ] + }, + { + "@id": "https://gallica.bnf.fr/iiif/ark:/12148/btv1b85409527/manifest.json", + "label": "BnF, Manuscrits, Allemand 150", + "thumbnail": "https://gallica.bnf.fr/ark:/12148/btv1b85409527/f1.thumbnail", + "related": [ + { + "@id": "https://gallica.bnf.fr/ark:/12148/btv1b85409527", + "format": "text/html", + "label": "Digital object in Gallica" + }, + { + "@id": "http://archivesetmanuscrits.bnf.fr/ead.html?id=FRBNFEAD000025646", + "format": "text/html", + "label": "Record in BnF Archives and Manuscripts Catalog" + } + ], + "seeAlso": { + "@id": "http://oai.bnf.fr/oai2/OAIHandler?verb=GetRecord&metadataPrefix=oai_dc&identifier=oai:bnf.fr:gallica/ark:/12148/btv1b85409527", + "format": "application/xml" + }, + "metadata": [ + { + "label": "Repository", + "value": "Bibliothèque nationale de France, Département des Manuscrits" + }, + { + "label": "Complete shelfmark", + "value": "France, Paris, Bibliothèque nationale de France, Département des Manuscrits, Allemand 150" + } + ] + }, + { + "@id": "https://gallica.bnf.fr/iiif/ark:/12148/btv1b52504171f/manifest.json", + "label": "BnF, Manuscrits, Allemand 232", + "thumbnail": "https://gallica.bnf.fr/ark:/12148/btv1b52504171f/f1.thumbnail", + "related": [ + { + "@id": "https://gallica.bnf.fr/ark:/12148/btv1b52504171f", + "format": "text/html", + "label": "Digital object in Gallica" + }, + { + "@id": "http://archivesetmanuscrits.bnf.fr/ead.html?id=FRBNFEAD000025712", + "format": "text/html", + "label": "Record in BnF Archives and Manuscripts Catalog" + } + ], + "seeAlso": { + "@id": "http://oai.bnf.fr/oai2/OAIHandler?verb=GetRecord&metadataPrefix=oai_dc&identifier=oai:bnf.fr:gallica/ark:/12148/btv1b52504171f", + "format": "application/xml" + }, + "metadata": [ + { + "label": "Repository", + "value": "Bibliothèque nationale de France, Département des Manuscrits" + }, + { + "label": "Complete shelfmark", + "value": "France, Paris, Bibliothèque nationale de France, Département des Manuscrits, Allemand 232" + } + ] + }, + { + "@id": "https://gallica.bnf.fr/iiif/ark:/12148/btv1b525046413/manifest.json", + "label": "BnF, Manuscrits, Allemand 236", + "thumbnail": "https://gallica.bnf.fr/ark:/12148/btv1b525046413/f1.thumbnail", + "related": [ + { + "@id": "https://gallica.bnf.fr/ark:/12148/btv1b525046413", + "format": "text/html", + "label": "Digital object in Gallica" + }, + { + "@id": "http://archivesetmanuscrits.bnf.fr/ead.html?id=FRBNFEAD000025712", + "format": "text/html", + "label": "Record in BnF Archives and Manuscripts Catalog" + } + ], + "seeAlso": { + "@id": "http://oai.bnf.fr/oai2/OAIHandler?verb=GetRecord&metadataPrefix=oai_dc&identifier=oai:bnf.fr:gallica/ark:/12148/btv1b525046413", + "format": "application/xml" + }, + "metadata": [ + { + "label": "Repository", + "value": "Bibliothèque nationale de France, Département des Manuscrits" + }, + { + "label": "Complete shelfmark", + "value": "France, Paris, Bibliothèque nationale de France, Département des Manuscrits, Allemand 236" + } + ] + }, + { + "@id": "https://gallica.bnf.fr/iiif/ark:/12148/btv1b525037219/manifest.json", + "label": "BnF, Manuscrits, Allemand 259", + "thumbnail": "https://gallica.bnf.fr/ark:/12148/btv1b525037219/f1.thumbnail", + "related": [ + { + "@id": "https://gallica.bnf.fr/ark:/12148/btv1b525037219", + "format": "text/html", + "label": "Digital object in Gallica" + }, + { + "@id": "http://archivesetmanuscrits.bnf.fr/ead.html?id=FRBNFEAD000025726", + "format": "text/html", + "label": "Record in BnF Archives and Manuscripts Catalog" + } + ], + "seeAlso": { + "@id": "http://oai.bnf.fr/oai2/OAIHandler?verb=GetRecord&metadataPrefix=oai_dc&identifier=oai:bnf.fr:gallica/ark:/12148/btv1b525037219", + "format": "application/xml" + }, + "metadata": [ + { + "label": "Repository", + "value": "Bibliothèque nationale de France, Département des Manuscrits" + }, + { + "label": "Complete shelfmark", + "value": "France, Paris, Bibliothèque nationale de France, Département des Manuscrits, Allemand 259" + } + ] + }, + { + "@id": "https://gallica.bnf.fr/iiif/ark:/12148/btv1b10512750r/manifest.json", + "label": "BnF, Manuscrits, Allemand 33", + "thumbnail": "https://gallica.bnf.fr/ark:/12148/btv1b10512750r/f1.thumbnail", + "related": [ + { + "@id": "https://gallica.bnf.fr/ark:/12148/btv1b10512750r", + "format": "text/html", + "label": "Digital object in Gallica" + }, + { + "@id": "http://archivesetmanuscrits.bnf.fr/ead.html?id=FRBNFEAD000025784", + "format": "text/html", + "label": "Record in BnF Archives and Manuscripts Catalog" + } + ], + "seeAlso": { + "@id": "http://oai.bnf.fr/oai2/OAIHandler?verb=GetRecord&metadataPrefix=oai_dc&identifier=oai:bnf.fr:gallica/ark:/12148/btv1b10512750r", + "format": "application/xml" + }, + "metadata": [ + { + "label": "Repository", + "value": "Bibliothèque nationale de France, Département des Manuscrits" + }, + { + "label": "Complete shelfmark", + "value": "France, Paris, Bibliothèque nationale de France, Département des Manuscrits, Allemand 33" + } + ] + }, + { + "@id": "https://gallica.bnf.fr/iiif/ark:/12148/btv1b10527637q/manifest.json", + "label": "BnF, Manuscrits, Allemand 34", + "thumbnail": "https://gallica.bnf.fr/ark:/12148/btv1b10527637q/f1.thumbnail", + "related": [ + { + "@id": "https://gallica.bnf.fr/ark:/12148/btv1b10527637q", + "format": "text/html", + "label": "Digital object in Gallica" + }, + { + "@id": "http://archivesetmanuscrits.bnf.fr/ead.html?id=FRBNFEAD000025789", + "format": "text/html", + "label": "Record in BnF Archives and Manuscripts Catalog" + } + ], + "seeAlso": { + "@id": "http://oai.bnf.fr/oai2/OAIHandler?verb=GetRecord&metadataPrefix=oai_dc&identifier=oai:bnf.fr:gallica/ark:/12148/btv1b10527637q", + "format": "application/xml" + }, + "metadata": [ + { + "label": "Repository", + "value": "Bibliothèque nationale de France, Département des Manuscrits" + }, + { + "label": "Complete shelfmark", + "value": "France, Paris, Bibliothèque nationale de France, Département des Manuscrits, Allemand 34" + } + ] + }, + { + "@id": "https://gallica.bnf.fr/iiif/ark:/12148/btv1b8452670s/manifest.json", + "label": "BnF, Manuscrits, Allemand 76", + "thumbnail": "https://gallica.bnf.fr/ark:/12148/btv1b8452670s/f1.thumbnail", + "related": [ + { + "@id": "https://gallica.bnf.fr/ark:/12148/btv1b8452670s", + "format": "text/html", + "label": "Digital object in Gallica" + }, + { + "@id": "http://archivesetmanuscrits.bnf.fr/ead.html?id=FRBNFEAD000025830", + "format": "text/html", + "label": "Record in BnF Archives and Manuscripts Catalog" + } + ], + "seeAlso": { + "@id": "http://oai.bnf.fr/oai2/OAIHandler?verb=GetRecord&metadataPrefix=oai_dc&identifier=oai:bnf.fr:gallica/ark:/12148/btv1b8452670s", + "format": "application/xml" + }, + "metadata": [ + { + "label": "Repository", + "value": "Bibliothèque nationale de France, Département des Manuscrits" + }, + { + "label": "Complete shelfmark", + "value": "France, Paris, Bibliothèque nationale de France, Département des Manuscrits, Allemand 76" + } + ] + }, + { + "@id": "https://gallica.bnf.fr/iiif/ark:/12148/btv1b52000978v/manifest.json", + "label": "BnF, Manuscrits, Allemand 84", + "thumbnail": "https://gallica.bnf.fr/ark:/12148/btv1b52000978v/f1.thumbnail", + "related": [ + { + "@id": "https://gallica.bnf.fr/ark:/12148/btv1b52000978v", + "format": "text/html", + "label": "Digital object in Gallica" + }, + { + "@id": "http://archivesetmanuscrits.bnf.fr/ead.html?id=FRBNFEAD000025837", + "format": "text/html", + "label": "Record in BnF Archives and Manuscripts Catalog" + } + ], + "seeAlso": { + "@id": "http://oai.bnf.fr/oai2/OAIHandler?verb=GetRecord&metadataPrefix=oai_dc&identifier=oai:bnf.fr:gallica/ark:/12148/btv1b52000978v", + "format": "application/xml" + }, + "metadata": [ + { + "label": "Repository", + "value": "Bibliothèque nationale de France, Département des Manuscrits" + }, + { + "label": "Complete shelfmark", + "value": "France, Paris, Bibliothèque nationale de France, Département des Manuscrits, Allemand 84" + } + ] + }, + { + "@id": "https://gallica.bnf.fr/iiif/ark:/12148/btv1b52500138j/manifest.json", + "label": "BnF, Manuscrits, Allemand 381", + "thumbnail": "https://gallica.bnf.fr/ark:/12148/btv1b52500138j/f1.thumbnail", + "related": [ + { + "@id": "https://gallica.bnf.fr/ark:/12148/btv1b52500138j", + "format": "text/html", + "label": "Digital object in Gallica" + }, + { + "@id": "http://archivesetmanuscrits.bnf.fr/ead.html?id=FRBNFEAD000091535", + "format": "text/html", + "label": "Record in BnF Archives and Manuscripts Catalog" + } + ], + "seeAlso": { + "@id": "http://oai.bnf.fr/oai2/OAIHandler?verb=GetRecord&metadataPrefix=oai_dc&identifier=oai:bnf.fr:gallica/ark:/12148/btv1b52500138j", + "format": "application/xml" + }, + "metadata": [ + { + "label": "Repository", + "value": "Bibliothèque nationale de France, Département des Manuscrits" + }, + { + "label": "Complete shelfmark", + "value": "France, Paris, Bibliothèque nationale de France, Département des Manuscrits, Allemand 381" + } + ] + }, + { + "@id": "https://gallica.bnf.fr/iiif/ark:/12148/btv1b525031211/manifest.json", + "label": "BnF, Manuscrits, Allemand 334", + "thumbnail": "https://gallica.bnf.fr/ark:/12148/btv1b525031211/f1.thumbnail", + "related": [ + { + "@id": "https://gallica.bnf.fr/ark:/12148/btv1b525031211", + "format": "text/html", + "label": "Digital object in Gallica" + }, + { + "@id": "http://archivesetmanuscrits.bnf.fr/ead.html?id=FRBNFEAD000096440", + "format": "text/html", + "label": "Record in BnF Archives and Manuscripts Catalog" + } + ], + "seeAlso": { + "@id": "http://oai.bnf.fr/oai2/OAIHandler?verb=GetRecord&metadataPrefix=oai_dc&identifier=oai:bnf.fr:gallica/ark:/12148/btv1b525031211", + "format": "application/xml" + }, + "metadata": [ + { + "label": "Repository", + "value": "Bibliothèque nationale de France, Département des Manuscrits" + }, + { + "label": "Complete shelfmark", + "value": "France, Paris, Bibliothèque nationale de France, Département des Manuscrits, Allemand 334" + } + ] + } + ] +} diff --git a/src/presentation-2/traverse.ts b/src/presentation-2/traverse.ts index 20b501c..4e73a88 100644 --- a/src/presentation-2/traverse.ts +++ b/src/presentation-2/traverse.ts @@ -158,6 +158,9 @@ export class Traverse< if (typeof manifest === 'string') { return { '@id': manifest, '@type': 'sc:Manifest' }; } + if (!manifest['@type']) { + manifest['@type'] = 'sc:Manifest'; + } return manifest; }), ...(collection.collections || []).map((subCollection) => { @@ -184,13 +187,17 @@ export class Traverse< } if (collection.manifests) { - collection.manifests = collection.manifests.map((manifest) => - this.traverseManifest( - typeof manifest === 'string' - ? ({ '@id': manifest, '@type': 'sc:Manifest' } as Manifest) - : (manifest as Manifest) - ) - ); + collection.manifests = collection.manifests.map((manifest) => { + let _manifest = manifest; + if (typeof manifest === 'string') { + _manifest = { '@id': manifest, '@type': 'sc:Manifest' } as Manifest; + } + if (!(_manifest as any)['@type']) { + (_manifest as any)['@type'] = 'sc:Manifest'; + } + + return this.traverseManifest(_manifest as Manifest); + }); } if (collection.collections) {