Skip to content

Commit e23d096

Browse files
authored
Merge pull request #58 from IIIF-Commons/st-andrews-manifest-fix
st andrews manifest fix
2 parents 57fdfec + c0f1591 commit e23d096

File tree

3 files changed

+68
-1
lines changed

3 files changed

+68
-1
lines changed

__tests__/presentation-2-parser/upgrade.test.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import stanfordManifest from '../../fixtures/presentation-2/stanford-manifest.js
3333
import goettingen from '../../fixtures/presentation-2/uni-goettingen.json';
3434
import villanovaManifest from '../../fixtures/presentation-2/villanova-manifest.json';
3535
import wikimediaProxy from '../../fixtures/presentation-2/wikimedia-proxy.json';
36+
import malformedImageAnnotation from '../../fixtures/presentation-2/malformed-image-annotation.json';
3637
import { convertPresentation2, presentation2to3 } from '../../src/presentation-2';
3738

3839
describe('Presentation 2 to 3', () => {
@@ -2615,4 +2616,24 @@ describe('Presentation 2 to 3', () => {
26152616
}
26162617
`);
26172618
});
2619+
2620+
test('Malformed annotation with dctypes:Image instead of oa:Annotation', () => {
2621+
// Some manifests (e.g., St. Andrews) have @type: "dctypes:Image" on annotations
2622+
// instead of the correct @type: "oa:Annotation". The converter should fix this.
2623+
const result = presentation2to3.traverseManifest(malformedImageAnnotation as any);
2624+
const isValid = validator.validateManifest(result);
2625+
2626+
expect(validator.validators.manifest!.errors).toEqual(null);
2627+
expect(isValid).toEqual(true);
2628+
2629+
// Verify the annotation was correctly converted
2630+
const canvas = result.items?.[0];
2631+
const annotationPage = canvas?.items?.[0];
2632+
const annotation = annotationPage?.items?.[0];
2633+
2634+
expect(annotation).toBeDefined();
2635+
expect(annotation?.type).toEqual('Annotation');
2636+
expect(annotation?.motivation).toEqual('painting');
2637+
expect(annotation?.body).toBeDefined();
2638+
});
26182639
});
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
{
2+
"@context": "http://iiif.io/api/presentation/2/context.json",
3+
"@type": "sc:Manifest",
4+
"@id": "https://example.org/manifest",
5+
"label": "Test manifest with malformed annotation @type",
6+
"sequences": [
7+
{
8+
"@type": "sc:Sequence",
9+
"canvases": [
10+
{
11+
"@type": "sc:Canvas",
12+
"@id": "https://example.org/canvas/1",
13+
"label": "Canvas 1",
14+
"width": 1000,
15+
"height": 800,
16+
"images": [
17+
{
18+
"@type": "dctypes:Image",
19+
"motivation": "sc:painting",
20+
"on": "https://example.org/canvas/1",
21+
"resource": {
22+
"@type": "dctypes:Image",
23+
"@id": "https://example.org/image/1/full/full/0/default.jpg",
24+
"format": "image/jpeg",
25+
"width": 1000,
26+
"height": 800,
27+
"service": {
28+
"@context": "http://iiif.io/api/image/2/context.json",
29+
"@id": "https://example.org/image/1",
30+
"profile": "http://iiif.io/api/image/2/level1.json"
31+
}
32+
}
33+
}
34+
]
35+
}
36+
]
37+
}
38+
]
39+
}

src/presentation-2/traverse.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,14 @@ export class Traverse<
261261

262262
traverseCanvasItems(canvas: Canvas): Canvas {
263263
if (canvas.images) {
264-
canvas.images = canvas.images.map((image) => this.traverseAnnotation(image));
264+
canvas.images = canvas.images.map((image) => {
265+
// Fix malformed annotations where @type is missing or incorrect (e.g., "dctypes:Image" instead of "oa:Annotation").
266+
// Detect by presence of "on" property which is unique to annotations.
267+
if (image.on && image['@type'] !== 'oa:Annotation' && image['@type'] !== 'Annotation') {
268+
image['@type'] = 'oa:Annotation';
269+
}
270+
return this.traverseAnnotation(image);
271+
});
265272
}
266273
if (canvas.otherContent) {
267274
canvas.otherContent = canvas.otherContent.map((annotationList) => this.traverseAnnotationList(annotationList));

0 commit comments

Comments
 (0)