iiif-presentation 1.4.0 → 1.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8d5fac69b52d8f3510fa40fc221882302736f9b4afe8b55b1330497ab11d8033
4
- data.tar.gz: 9156c96e93409320cddde7d86bb78894b6351cd2c291ab6bdca39958d3f27bbc
3
+ metadata.gz: 8e5872ac7de857fa05e0181916f712460413e5b08b09d0b99867cc14ae39e0e5
4
+ data.tar.gz: 213166e3e00800955380ed432a1b10fce3a497011af92db4657474ef56e4b2aa
5
5
  SHA512:
6
- metadata.gz: 85f3b92e738793e5360cdff614c6f50fd271cb7b1033a6df1de8452603a18b4aa6cb0c6e4c9e5639f0587c6d1666cb47054c4b99894e398ee4a3c1fcfa08bd09
7
- data.tar.gz: be3fc1d37352d21c018cffc8c2315d221aadcd00fad0c46847ffe1d68b131b6bc3844abf08ba6bd5cf56c049df706a31e1300c3279fa98b3fb1e43d267a34187
6
+ metadata.gz: 840576064059d424a68fc9917e30a6a2bc120fb7157691fae70edadaa705711301fd175a3942ce227298086c934ae0f0f471b8379a00314da9aea7b068643b07
7
+ data.tar.gz: 308dd4b3bcd7b4dfbfaa5147a4d0208dfaedaa69265577b43fd46e04e59be8f95f12a92667a12c935d07a534e6ef271ea2ce9d50dbc449b5a2af1a800b0a51d9
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.4.0
1
+ 1.4.2
@@ -31,11 +31,11 @@ module IIIF
31
31
  end
32
32
 
33
33
  def string_only_keys
34
- %w{ nav_date type format viewing_direction start_canvas }
34
+ %w{ nav_date type format rights viewing_direction start_canvas }
35
35
  end
36
36
 
37
37
  def array_only_keys
38
- %w{ metadata rights thumbnail rendering first last next prev items service }
38
+ %w{ metadata thumbnail rendering first last next prev items service }
39
39
  end
40
40
 
41
41
  def hash_only_keys
@@ -122,10 +122,9 @@ module IIIF
122
122
  end
123
123
  end
124
124
 
125
- self.uri_only_keys.each do |k|
125
+ uri_only_keys.each do |k|
126
126
  if self[k]
127
- vals = *self[k]
128
- vals.each { |val| validate_uri(val, k) }
127
+ Array(self[k]).each { |val| validate_uri(val, k) }
129
128
  end
130
129
  end
131
130
 
@@ -187,20 +186,12 @@ module IIIF
187
186
  raise IIIF::V3::Presentation::IllegalValueError, m
188
187
  end
189
188
  end
190
- # rights is Array; each entry is a Hash containing 'id' with a URI value
191
- if self.has_key?('rights')
192
- unless self['rights'].all? { |entry| entry.kind_of?(Hash) }
193
- m = 'rights must be an Array with Hash members'
194
- raise IIIF::V3::Presentation::IllegalValueError, m
195
- end
196
- self['rights'].each do |entry|
197
- unless entry.keys.include?('id')
198
- m = 'rights members must be a Hash including "id"'
199
- raise IIIF::V3::Presentation::IllegalValueError, m
200
- end
201
- validate_uri(entry['id'], 'id') # raises IllegalValueError
202
- end
189
+
190
+ if key?('rights') && !self['rights'].kind_of?(String)
191
+ m = 'rights must be a String'
192
+ raise IIIF::V3::Presentation::IllegalValueError, m
203
193
  end
194
+
204
195
  # rendering is Array; each entry is a Hash containing 'label' and 'format' keys
205
196
  if self.has_key?('rendering') && self['rendering']
206
197
  unless self['rendering'].all? { |entry| entry.kind_of?(Hash) }
@@ -347,7 +338,9 @@ module IIIF
347
338
  hsh.keys.each do |key|
348
339
  new_key = key.underscore == key ? key : key.underscore
349
340
  if new_key == 'service'
350
- new_object[new_key] = IIIF::V3::AbstractResource.from_ordered_hash(hsh[key], IIIF::V3::Presentation::Service)
341
+ new_object[new_key] = hsh[key].map do |entry|
342
+ IIIF::V3::AbstractResource.from_ordered_hash(entry, IIIF::V3::Presentation::Service)
343
+ end
351
344
  elsif new_key == 'body'
352
345
  new_object[new_key] = IIIF::V3::AbstractResource.from_ordered_hash(hsh[key], IIIF::V3::Presentation::Resource)
353
346
  elsif hsh[key].kind_of?(Hash)
@@ -63,8 +63,6 @@ module IIIF
63
63
  end
64
64
  end
65
65
 
66
- # NOTE: allowing 'items' or 'sequences' as Universal Viewer currently only accepts sequences
67
- # see https://github.com/sul-dlss/osullivan/issues/27, sul-dlss/purl/issues/167
68
66
  def validate_items_list(items_array)
69
67
  unless items_array.size >= 1
70
68
  m = 'The items list must have at least one entry (and it must be a IIIF::V3::Presentation::Canvas)'
@@ -28,11 +28,13 @@
28
28
  "description": "A longer description of this example book. It should give some real information.",
29
29
  "rights": "http://www.example.org/license.html",
30
30
  "attribution": "Provided by Example Organization",
31
- "service": {
32
- "@context": "http://example.org/ns/jsonld/context.json",
33
- "id": "http://example.org/service/example",
34
- "profile": "http://example.org/docs/example-service.html"
35
- },
31
+ "service": [
32
+ {
33
+ "@context": "http://example.org/ns/jsonld/context.json",
34
+ "id": "http://example.org/service/example",
35
+ "profile": "http://example.org/docs/example-service.html"
36
+ }
37
+ ],
36
38
  "seeAlso": {
37
39
  "id": "http://www.example.org/library/catalog/book1.marc",
38
40
  "format": "application/marc"
@@ -67,11 +69,13 @@
67
69
  "format": "image/jpeg",
68
70
  "height": 2000,
69
71
  "width": 1500,
70
- "service": {
71
- "@context": "http://iiif.io/api/image/2/context.json",
72
- "id": "http://www.example.org/images/book1-page1",
73
- "profile": "http://iiif.io/api/image/2/level1.json"
74
- }
72
+ "service": [
73
+ {
74
+ "@context": "http://iiif.io/api/image/2/context.json",
75
+ "id": "http://www.example.org/images/book1-page1",
76
+ "profile": "http://iiif.io/api/image/2/level1.json"
77
+ }
78
+ ]
75
79
  }
76
80
  }
77
81
  ]
@@ -102,25 +106,27 @@
102
106
  "format": "image/jpeg",
103
107
  "height": 2000,
104
108
  "width": 1500,
105
- "service": {
106
- "@context": "http://iiif.io/api/image/2/context.json",
107
- "id": "http://www.example.org/images/book1-page2",
108
- "profile": "http://iiif.io/api/image/2/level1.json",
109
- "height": 8000,
110
- "width": 6000,
111
- "tiles": [
112
- {
113
- "width": 512,
114
- "scaleFactors": [
115
- 1,
116
- 2,
117
- 4,
118
- 8,
119
- 16
120
- ]
121
- }
122
- ]
123
- }
109
+ "service": [
110
+ {
111
+ "@context": "http://iiif.io/api/image/2/context.json",
112
+ "id": "http://www.example.org/images/book1-page2",
113
+ "profile": "http://iiif.io/api/image/2/level1.json",
114
+ "height": 8000,
115
+ "width": 6000,
116
+ "tiles": [
117
+ {
118
+ "width": 512,
119
+ "scaleFactors": [
120
+ 1,
121
+ 2,
122
+ 4,
123
+ 8,
124
+ 16
125
+ ]
126
+ }
127
+ ]
128
+ }
129
+ ]
124
130
  },
125
131
  "target": "http://www.example.org/iiif/book1/canvas/p2"
126
132
  }
@@ -153,11 +159,13 @@
153
159
  "format": "image/jpeg",
154
160
  "height": 2000,
155
161
  "width": 1500,
156
- "service": {
157
- "@context": "http://iiif.io/api/image/2/context.json",
158
- "id": "http://www.example.org/images/book1-page3",
159
- "profile": "http://iiif.io/api/image/2/level1.json"
160
- }
162
+ "service": [
163
+ {
164
+ "@context": "http://iiif.io/api/image/2/context.json",
165
+ "id": "http://www.example.org/images/book1-page3",
166
+ "profile": "http://iiif.io/api/image/2/level1.json"
167
+ }
168
+ ]
161
169
  }
162
170
  }
163
171
  ]
@@ -32,11 +32,13 @@
32
32
  "format": "image/jpeg",
33
33
  "height": 2000,
34
34
  "width": 1500,
35
- "service": {
36
- "@context": "http://iiif.io/api/image/2/context.json",
37
- "id": "http://www.example.org/images/book1-page1",
38
- "profile": "http://iiif.io/api/image/2/level1.json"
39
- }
35
+ "service": [
36
+ {
37
+ "@context": "http://iiif.io/api/image/2/context.json",
38
+ "id": "http://www.example.org/images/book1-page1",
39
+ "profile": "http://iiif.io/api/image/2/level1.json"
40
+ }
41
+ ]
40
42
  }
41
43
  }
42
44
  ]
@@ -6,9 +6,11 @@
6
6
  "type": "Manifest",
7
7
  "id": "http://www.example.org/iiif/book1/manifest",
8
8
  "label": "Book 1",
9
- "service": {
10
- "@context": "http://example.org/ns/jsonld/context.json",
11
- "id": "http://example.org/service/example",
12
- "profile": "http://example.org/docs/example-service.html"
13
- }
9
+ "service": [
10
+ {
11
+ "@context": "http://example.org/ns/jsonld/context.json",
12
+ "id": "http://example.org/service/example",
13
+ "profile": "http://example.org/docs/example-service.html"
14
+ }
15
+ ]
14
16
  }
@@ -46,13 +46,16 @@ describe IIIF::V3::AbstractResource do
46
46
  ],
47
47
  "id": "http://example.com/manifest",
48
48
  "type": "Manifest",
49
+ "rights": "http://creativecommons.org/licenses/by/4.0/",
49
50
  "label": "My Manifest",
50
- "service": {
51
- "@context": "http://iiif.io/api/image/2/context.json",
52
- "@id":"http://www.example.org/images/book1-page1",
53
- "id":"http://www.example.org/images/book1-page1",
54
- "profile":"http://iiif.io/api/image/2/profiles/level2.json"
55
- },
51
+ "service": [
52
+ {
53
+ "@context": "http://iiif.io/api/image/2/context.json",
54
+ "@id":"http://www.example.org/images/book1-page1",
55
+ "id":"http://www.example.org/images/book1-page1",
56
+ "profile":"http://iiif.io/api/image/2/profiles/level2.json"
57
+ }
58
+ ],
56
59
  "some_other_thing": {
57
60
  "foo" : "bar"
58
61
  },
@@ -95,7 +98,7 @@ describe IIIF::V3::AbstractResource do
95
98
  it 'turns services into Services' do
96
99
  expected_klass = IIIF::V3::Presentation::Service
97
100
  parsed = described_class.from_ordered_hash(fixture)
98
- expect(parsed['service'].class).to be expected_klass
101
+ expect(parsed['service'].map(&:class).uniq).to contain_exactly expected_klass
99
102
  end
100
103
 
101
104
  it 'round-trips' do
@@ -139,27 +139,19 @@ describe IIIF::V3::AbstractResource do
139
139
  expect { subject.validate }.to raise_error(IIIF::V3::Presentation::IllegalValueError, exp_err_msg)
140
140
  end
141
141
  end
142
+
142
143
  describe 'rights' do
143
- it 'raises IllegalValueError for entry that is not a Hash' do
144
+ it 'raises IllegalValueError for entry that is not a string' do
144
145
  subject['rights'] = ['error']
145
- exp_err_msg = "rights must be an Array with Hash members"
146
- expect { subject.validate }.to raise_error(IIIF::V3::Presentation::IllegalValueError, exp_err_msg)
146
+ expect { subject.validate }.to raise_error(IIIF::V3::Presentation::IllegalValueError)
147
147
  end
148
- it 'does not raise error for entry with "id" that is URI' do
149
- subject['rights'] = [{ 'id' => 'http://example.org/rights', 'format' => 'text/html' }]
148
+
149
+ it 'does not raise error for entry that is string' do
150
+ subject['rights'] = 'http://example.org/rights'
150
151
  expect { subject.validate }.not_to raise_error
151
152
  end
152
- it 'raises IllegalValueError for entry with "id" that is not URI' do
153
- subject['rights'] = [{ 'id' => 'bar', 'format' => 'text/html' }]
154
- exp_err_msg = "id value must be a String containing a URI for #{subject.class}"
155
- expect { subject.validate }.to raise_error(IIIF::V3::Presentation::IllegalValueError, exp_err_msg)
156
- end
157
- it 'raises IllegalValueError for entry that does not contain "id"' do
158
- subject['rights'] = [{ 'whoops' => 'http://example.org/rights' }]
159
- exp_err_msg = 'rights members must be a Hash including "id"'
160
- expect { subject.validate }.to raise_error(IIIF::V3::Presentation::IllegalValueError, exp_err_msg)
161
- end
162
153
  end
154
+
163
155
  describe 'rendering' do
164
156
  it 'raises IllegalValueError for entry that is not a Hash' do
165
157
  subject['rendering'] = ['error']
@@ -12,7 +12,7 @@ describe IIIF::V3::Presentation::Annotation do
12
12
  'id' => content_id,
13
13
  'type' => content_type,
14
14
  'format' => mimetype,
15
- 'service' => image_2_api_service
15
+ 'service' => [image_2_api_service]
16
16
  )}
17
17
 
18
18
  describe '#required_keys' do
@@ -183,14 +183,16 @@ describe IIIF::V3::Presentation::Annotation do
183
183
  let(:img_mime) { 'image/jpeg' }
184
184
  let(:img_h) { 2000 }
185
185
  let(:img_w) { 1500 }
186
- let(:img_hw_resource) { IIIF::V3::Presentation::ImageResource.new(
187
- 'id' => content_id,
188
- 'type' => img_type,
189
- 'format' => img_mime,
190
- 'height' => img_h,
191
- 'width' => img_w,
192
- 'service' => image_2_api_service
193
- )}
186
+ let(:img_hw_resource) do
187
+ IIIF::V3::Presentation::ImageResource.new(
188
+ 'id' => content_id,
189
+ 'type' => img_type,
190
+ 'format' => img_mime,
191
+ 'height' => img_h,
192
+ 'width' => img_w,
193
+ 'service' => [image_2_api_service]
194
+ )
195
+ end
194
196
  let(:my_anno) {
195
197
  anno = described_class.new
196
198
  anno['id'] = anno_id
@@ -209,22 +211,23 @@ describe IIIF::V3::Presentation::Annotation do
209
211
 
210
212
  describe 'and service with height and width and tiles' do
211
213
  let(:tiles_val) { [{"width" => 512, "scaleFactors" => [1,2,4,8,16]}] }
212
- let(:service) {
214
+ let(:service) do
213
215
  s = image_2_api_service
214
216
  s['height'] = 8000
215
217
  s['width'] = 6000
216
218
  s['tiles'] = tiles_val
217
- s
218
- }
219
+ [s]
220
+ end
219
221
  it 'validates' do
220
222
  img_hw_resource['service'] = service
221
223
  expect{my_anno.validate}.not_to raise_error
222
224
  end
223
225
  it "body['service'] has expected additional values'" do
224
- expect(my_anno['body']['service']).to eq service
225
- expect(my_anno['body']['service']['height']).to eq 8000
226
- expect(my_anno['body']['service']['width']).to eq 6000
227
- expect(my_anno['body']['service']['tiles']).to eq tiles_val
226
+ annotation_service = my_anno['body']['service'].first
227
+ expect(annotation_service).to eq service.first
228
+ expect(annotation_service['height']).to eq 8000
229
+ expect(annotation_service['width']).to eq 6000
230
+ expect(annotation_service['tiles']).to eq tiles_val
228
231
  end
229
232
  end
230
233
  end
@@ -131,7 +131,7 @@ describe IIIF::V3::Presentation::ImageResource do
131
131
  'format' => img_mimetype,
132
132
  'height' => height,
133
133
  'width' => width,
134
- 'service' => image_v2_service
134
+ 'service' => [image_v2_service]
135
135
  })
136
136
  }
137
137
  describe 'simpler' do
@@ -146,7 +146,7 @@ describe IIIF::V3::Presentation::ImageResource do
146
146
  expect(image_object.format).to eq img_mimetype
147
147
  expect(image_object.height).to eq height
148
148
  expect(image_object.width).to eq width
149
- expect(image_object.service).to eq image_v2_service
149
+ expect(image_object.service.first).to eq image_v2_service
150
150
  end
151
151
  end
152
152
  describe 'height and width in service' do
@@ -156,27 +156,27 @@ describe IIIF::V3::Presentation::ImageResource do
156
156
  # "format": "image/jpeg",
157
157
  # "height":2000,
158
158
  # "width":1500,
159
- # "service": {
159
+ # "service": [{
160
160
  # "@context": "http://iiif.io/api/image/2/context.json",
161
161
  # "id": "http://example.org/images/book1-page2",
162
162
  # "profile": "http://iiif.io/api/image/2/level1.json",
163
163
  # "height":8000,
164
164
  # "width":6000,
165
165
  # "tiles": [{"width": 512, "scaleFactors": [1,2,4,8,16]}]
166
- # }
166
+ # }]
167
167
  # }
168
168
  let(:img_obj) {
169
169
  img = image_object
170
- img.service['height'] = 6666
171
- img.service['width'] = 9999
172
- img.service['tiles'] = [{"width" => 512, "scaleFactors" => [1,2,4,8,16]}]
170
+ img.service.first['height'] = 6666
171
+ img.service.first['width'] = 9999
172
+ img.service.first['tiles'] = [{"width" => 512, "scaleFactors" => [1,2,4,8,16]}]
173
173
  img
174
174
  }
175
175
  it 'validates' do
176
176
  expect{img_obj.validate}.not_to raise_error
177
177
  end
178
178
  it 'has expected service value' do
179
- service_obj = img_obj.service
179
+ service_obj = img_obj.service.first
180
180
  expect(service_obj.class).to eq IIIF::V3::Presentation::Service
181
181
  expect(service_obj.keys.size).to eq 7
182
182
  expect(service_obj['height']).to eq 6666
@@ -176,7 +176,7 @@ describe IIIF::V3::Presentation::Manifest do
176
176
  let!(:thumbnail_image) { IIIF::V3::Presentation::ImageResource.new({
177
177
  "id" => "https://example.org/image/iiif/abc666_05_0001/full/!400,400/0/default.jpg",
178
178
  "format" => "image/jpeg",
179
- "service" => thumbnail_image_service
179
+ "service" => [thumbnail_image_service]
180
180
  })}
181
181
  let!(:manifest_object) { described_class.new({
182
182
  "id" => "https://example.org/abc666/iiif3/manifest",
@@ -189,7 +189,7 @@ describe IIIF::V3::Presentation::Manifest do
189
189
  "items" => [canvas_object],
190
190
  "logo" => {
191
191
  "id" => "https://example.org/logo/full/400,/0/default.jpg",
192
- "service" => logo_service
192
+ "service" => [logo_service]
193
193
  },
194
194
  "seeAlso" => {
195
195
  "id" => "https://example.org/abc666.mods",
@@ -242,7 +242,7 @@ describe IIIF::V3::Presentation::Manifest do
242
242
  },
243
243
  "logo" => {
244
244
  "id" => "https://example.org/logo/full/400,/0/default.jpg",
245
- "service" => logo_service
245
+ "service" => [logo_service]
246
246
  },
247
247
  "seeAlso" => {
248
248
  "id" => "https://example.org/abc666.mods",
@@ -322,9 +322,7 @@ describe IIIF::V3::Presentation::Manifest do
322
322
  "viewingDirection" => "right-to-left",
323
323
  "viewingHint" => ["paged"],
324
324
  "navDate" => "1856-01-01T00:00:00Z",
325
- "rights" => [{
326
- "id" =>"http://example.org/license.html",
327
- "format" => "text/html"}],
325
+ "rights" => "http://example.org/license.html",
328
326
  "requiredStatement" => {
329
327
  "label": { "en": [ "Attribution" ] },
330
328
  "value": { "en": [ "bleah" ] },
@@ -96,7 +96,7 @@ describe IIIF::V3::Presentation::Sequence do
96
96
  expect(sequence_object.items.first).to eq canvas_object
97
97
  end
98
98
  end
99
-
99
+
100
100
  describe 'example from Stanford purl' do
101
101
  let(:seq_id) { 'https://example.org/abc666#sequence-1' }
102
102
  let(:sequence_object) {
@@ -177,21 +177,21 @@ describe IIIF::V3::Presentation::Sequence do
177
177
  'thumbnail' => [{
178
178
  'id' => 'http://www.example.org/images/book1-page1/full/80,100/0/default.jpg',
179
179
  'type' => 'Image',
180
- 'service'=> {
180
+ 'service'=> [{
181
181
  '@context' => 'http://iiif.io/api/image/2/context.json',
182
182
  'id' => 'http://www.example.org/images/book1-page1',
183
183
  'profile' => 'http://iiif.io/api/image/2/level1.json'
184
- }
184
+ }]
185
185
  }],
186
186
  'attribution' => 'Provided by Example Organization',
187
- 'rights' => [{'id' => 'http://www.example.org/license.html'}],
187
+ 'rights' => 'Sample rights',
188
188
  'logo' => 'http://www.example.org/logos/institution1.jpg',
189
189
  'see_also' => 'http://www.example.org/library/catalog/book1.xml',
190
- 'service' => {
190
+ 'service' => [{
191
191
  '@context' => 'http://example.org/ns/jsonld/context.json',
192
192
  'id' => 'http://example.org/service/example',
193
193
  'profile' => 'http://example.org/docs/example-service.html'
194
- },
194
+ }],
195
195
  'related' => {
196
196
  'id' => 'http://www.example.org/videos/video-book1.mpg',
197
197
  'format' => 'video/mpeg'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: iiif-presentation
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.0
4
+ version: 1.4.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jon Stroop