1- import { readFileSync } from 'node:fs' ;
2- import { join } from 'node:path' ;
3- import { cwd } from 'node:process' ;
4- import { describe , expect , test } from 'vitest' ;
5- import {
6- normalize ,
7- serialize ,
8- serializeConfigPresentation3 ,
9- } from '../../src/presentation-4' ;
1+ import { readFileSync } from "node:fs" ;
2+ import { join } from "node:path" ;
3+ import { cwd } from "node:process" ;
4+ import { describe , expect , test } from "vitest" ;
5+ import { normalize , serialize , serializeConfigPresentation3 } from "../../src/presentation-4" ;
106
11- describe ( 'presentation-4 to presentation-3 downgrade serializer' , ( ) => {
12- test ( 'downgrades Timeline to Canvas with minimal dimensions' , ( ) => {
7+ describe ( "presentation-4 to presentation-3 downgrade serializer" , ( ) => {
8+ test ( "serializes annotation targets by unwrapping List, compressing SpecificResource, and mapping Timeline/Scene to Canvas" , ( ) => {
9+ const manifest = {
10+ "@context" : "http://iiif.io/api/presentation/4/context.json" ,
11+ id : "https://example.org/iiif/target-manifest" ,
12+ type : "Manifest" ,
13+ label : { en : [ "Target test" ] } ,
14+ items : [
15+ {
16+ id : "https://example.org/iiif/canvas/1" ,
17+ type : "Canvas" ,
18+ width : 1000 ,
19+ height : 1000 ,
20+ items : [
21+ {
22+ id : "https://example.org/iiif/canvas/1/page/1" ,
23+ type : "AnnotationPage" ,
24+ items : [
25+ {
26+ id : "https://example.org/iiif/canvas/1/page/1/anno/1" ,
27+ type : "Annotation" ,
28+ motivation : [ "painting" ] ,
29+ body : {
30+ id : "https://example.org/iiif/image/1.jpg" ,
31+ type : "Image" ,
32+ format : "image/jpeg" ,
33+ } ,
34+ target : {
35+ type : "List" ,
36+ items : [
37+ {
38+ type : "SpecificResource" ,
39+ source : {
40+ id : "https://example.org/iiif/timeline/1" ,
41+ type : "Timeline" ,
42+ } ,
43+ selector : {
44+ type : "FragmentSelector" ,
45+ value : "t=0,10" ,
46+ } ,
47+ } ,
48+ {
49+ id : "https://example.org/iiif/scene/1" ,
50+ type : "Scene" ,
51+ } ,
52+ ] ,
53+ } ,
54+ } ,
55+ ] ,
56+ } ,
57+ ] ,
58+ } ,
59+ ] ,
60+ } ;
61+
62+ const normalized = normalize ( manifest ) ;
63+ const serialized = serialize < any > (
64+ {
65+ entities : normalized . entities as any ,
66+ mapping : normalized . mapping as any ,
67+ requests : { } ,
68+ } ,
69+ normalized . resource ,
70+ serializeConfigPresentation3
71+ ) ;
72+
73+ expect ( serialized . items [ 0 ] . items [ 0 ] . items [ 0 ] . target ) . toEqual ( [
74+ "https://example.org/iiif/timeline/1#t=0,10" ,
75+ {
76+ id : "https://example.org/iiif/scene/1" ,
77+ type : "Canvas" ,
78+ } ,
79+ ] ) ;
80+ } ) ;
81+
82+ test ( "downgrades Timeline to Canvas with minimal dimensions" , ( ) => {
1383 const timelineManifest = {
14- ' @context' : ' http://iiif.io/api/presentation/4/context.json' ,
15- id : ' https://example.org/iiif/timeline-manifest' ,
16- type : ' Manifest' ,
17- label : { en : [ ' Timeline' ] } ,
84+ " @context" : " http://iiif.io/api/presentation/4/context.json" ,
85+ id : " https://example.org/iiif/timeline-manifest" ,
86+ type : " Manifest" ,
87+ label : { en : [ " Timeline" ] } ,
1888 items : [
1989 {
20- id : ' https://example.org/iiif/timeline-1' ,
21- type : ' Timeline' ,
90+ id : " https://example.org/iiif/timeline-1" ,
91+ type : " Timeline" ,
2292 duration : 20 ,
2393 items : [
2494 {
25- id : ' https://example.org/iiif/timeline-1/page' ,
26- type : ' AnnotationPage' ,
95+ id : " https://example.org/iiif/timeline-1/page" ,
96+ type : " AnnotationPage" ,
2797 items : [
2898 {
29- id : ' https://example.org/iiif/timeline-1/painting' ,
30- type : ' Annotation' ,
31- motivation : [ ' painting' ] ,
99+ id : " https://example.org/iiif/timeline-1/painting" ,
100+ type : " Annotation" ,
101+ motivation : [ " painting" ] ,
32102 body : [
33103 {
34- id : ' https://example.org/audio.mp3' ,
35- type : ' Sound' ,
36- format : ' audio/mp3' ,
104+ id : " https://example.org/audio.mp3" ,
105+ type : " Sound" ,
106+ format : " audio/mp3" ,
37107 } ,
38108 ] ,
39- target : [ ' https://example.org/iiif/timeline-1' ] ,
109+ target : [ " https://example.org/iiif/timeline-1" ] ,
40110 } ,
41111 ] ,
42112 } ,
@@ -56,17 +126,15 @@ describe('presentation-4 to presentation-3 downgrade serializer', () => {
56126 serializeConfigPresentation3
57127 ) ;
58128
59- expect ( serialized [ ' @context' ] ) . toEqual ( ' http://iiif.io/api/presentation/3/context.json' ) ;
60- expect ( serialized . items [ 0 ] . type ) . toEqual ( ' Canvas' ) ;
61- expect ( serialized . items [ 0 ] . width ) . toEqual ( 1 ) ;
62- expect ( serialized . items [ 0 ] . height ) . toEqual ( 1 ) ;
129+ expect ( serialized [ " @context" ] ) . toEqual ( " http://iiif.io/api/presentation/3/context.json" ) ;
130+ expect ( serialized . items [ 0 ] . type ) . toEqual ( " Canvas" ) ;
131+ expect ( serialized . items [ 0 ] . width ) . not . toBeDefined ( ) ;
132+ expect ( serialized . items [ 0 ] . height ) . not . toBeDefined ( ) ;
63133 expect ( serialized . items [ 0 ] . duration ) . toEqual ( 20 ) ;
64134 } ) ;
65135
66- test ( 'fails downgrade when Scene is present' , ( ) => {
67- const fixture = JSON . parse (
68- readFileSync ( join ( cwd ( ) , 'fixtures/presentation-4/01-model-in-scene.json' ) , 'utf8' )
69- ) ;
136+ test ( "fails downgrade when Scene is present" , ( ) => {
137+ const fixture = JSON . parse ( readFileSync ( join ( cwd ( ) , "fixtures/presentation-4/01-model-in-scene.json" ) , "utf8" ) ) ;
70138 const normalized = normalize ( fixture ) ;
71139
72140 expect ( ( ) =>
@@ -82,35 +150,35 @@ describe('presentation-4 to presentation-3 downgrade serializer', () => {
82150 ) . toThrow ( / u n s u p p o r t e d / i) ;
83151 } ) ;
84152
85- test ( ' fails downgrade when activating annotations are present' , ( ) => {
153+ test ( " fails downgrade when activating annotations are present" , ( ) => {
86154 const manifest = {
87- ' @context' : ' http://iiif.io/api/presentation/4/context.json' ,
88- id : ' https://example.org/iiif/activating-manifest' ,
89- type : ' Manifest' ,
90- label : { en : [ ' Activating' ] } ,
155+ " @context" : " http://iiif.io/api/presentation/4/context.json" ,
156+ id : " https://example.org/iiif/activating-manifest" ,
157+ type : " Manifest" ,
158+ label : { en : [ " Activating" ] } ,
91159 items : [
92160 {
93- id : ' https://example.org/iiif/canvas/1' ,
94- type : ' Canvas' ,
161+ id : " https://example.org/iiif/canvas/1" ,
162+ type : " Canvas" ,
95163 width : 1000 ,
96164 height : 1000 ,
97165 items : [
98166 {
99- id : ' https://example.org/iiif/canvas/1/page/1' ,
100- type : ' AnnotationPage' ,
167+ id : " https://example.org/iiif/canvas/1/page/1" ,
168+ type : " AnnotationPage" ,
101169 items : [
102170 {
103- id : ' https://example.org/iiif/canvas/1/page/1/anno/1' ,
104- type : ' Annotation' ,
105- motivation : [ ' activating' ] ,
171+ id : " https://example.org/iiif/canvas/1/page/1/anno/1" ,
172+ type : " Annotation" ,
173+ motivation : [ " activating" ] ,
106174 body : [
107175 {
108- id : ' https://example.org/iiif/image/1.jpg' ,
109- type : ' Image' ,
110- format : ' image/jpeg' ,
176+ id : " https://example.org/iiif/image/1.jpg" ,
177+ type : " Image" ,
178+ format : " image/jpeg" ,
111179 } ,
112180 ] ,
113- target : [ ' https://example.org/iiif/canvas/1' ] ,
181+ target : [ " https://example.org/iiif/canvas/1" ] ,
114182 } ,
115183 ] ,
116184 } ,
@@ -134,41 +202,41 @@ describe('presentation-4 to presentation-3 downgrade serializer', () => {
134202 ) . toThrow ( / a c t i v a t i n g / i) ;
135203 } ) ;
136204
137- test ( ' fails downgrade when content has transform metadata' , ( ) => {
205+ test ( " fails downgrade when content has transform metadata" , ( ) => {
138206 const manifest = {
139- ' @context' : ' http://iiif.io/api/presentation/4/context.json' ,
140- id : ' https://example.org/iiif/transform-manifest' ,
141- type : ' Manifest' ,
142- label : { en : [ ' Transform' ] } ,
207+ " @context" : " http://iiif.io/api/presentation/4/context.json" ,
208+ id : " https://example.org/iiif/transform-manifest" ,
209+ type : " Manifest" ,
210+ label : { en : [ " Transform" ] } ,
143211 items : [
144212 {
145- id : ' https://example.org/iiif/canvas/2' ,
146- type : ' Canvas' ,
213+ id : " https://example.org/iiif/canvas/2" ,
214+ type : " Canvas" ,
147215 width : 1000 ,
148216 height : 1000 ,
149217 items : [
150218 {
151- id : ' https://example.org/iiif/canvas/2/page/1' ,
152- type : ' AnnotationPage' ,
219+ id : " https://example.org/iiif/canvas/2/page/1" ,
220+ type : " AnnotationPage" ,
153221 items : [
154222 {
155- id : ' https://example.org/iiif/canvas/2/page/1/anno/1' ,
156- type : ' Annotation' ,
157- motivation : [ ' painting' ] ,
223+ id : " https://example.org/iiif/canvas/2/page/1/anno/1" ,
224+ type : " Annotation" ,
225+ motivation : [ " painting" ] ,
158226 body : [
159227 {
160- id : ' https://example.org/iiif/image/2.jpg' ,
161- type : ' Image' ,
162- format : ' image/jpeg' ,
228+ id : " https://example.org/iiif/image/2.jpg" ,
229+ type : " Image" ,
230+ format : " image/jpeg" ,
163231 transform : [
164232 {
165- type : ' RotateTransform' ,
233+ type : " RotateTransform" ,
166234 angle : 90 ,
167235 } ,
168236 ] ,
169237 } ,
170238 ] ,
171- target : [ ' https://example.org/iiif/canvas/2' ] ,
239+ target : [ " https://example.org/iiif/canvas/2" ] ,
172240 } ,
173241 ] ,
174242 } ,
0 commit comments