iiif-presentation 1.1.0 → 1.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/ruby.yml +2 -2
- data/.gitignore +1 -0
- data/Gemfile +2 -0
- data/README.md +22 -1
- data/VERSION +1 -1
- data/iiif-presentation.gemspec +2 -1
- data/lib/iiif/presentation/canvas.rb +4 -0
- data/lib/iiif/presentation/service.rb +12 -0
- data/lib/iiif/presentation.rb +5 -4
- data/lib/iiif/service.rb +38 -103
- data/lib/iiif/v3/abstract_resource.rb +491 -0
- data/lib/iiif/v3/presentation/annotation.rb +74 -0
- data/lib/iiif/v3/presentation/annotation_collection.rb +38 -0
- data/lib/iiif/v3/presentation/annotation_page.rb +53 -0
- data/lib/iiif/v3/presentation/canvas.rb +82 -0
- data/lib/iiif/v3/presentation/choice.rb +51 -0
- data/lib/iiif/v3/presentation/collection.rb +52 -0
- data/lib/iiif/v3/presentation/image_resource.rb +110 -0
- data/lib/iiif/v3/presentation/manifest.rb +82 -0
- data/lib/iiif/v3/presentation/nav_place.rb +109 -0
- data/lib/iiif/v3/presentation/range.rb +39 -0
- data/lib/iiif/v3/presentation/resource.rb +30 -0
- data/lib/iiif/v3/presentation/sequence.rb +66 -0
- data/lib/iiif/v3/presentation/service.rb +51 -0
- data/lib/iiif/v3/presentation.rb +37 -0
- data/spec/fixtures/v3/manifests/complete_from_spec.json +195 -0
- data/spec/fixtures/v3/manifests/minimal.json +49 -0
- data/spec/fixtures/v3/manifests/service_only.json +14 -0
- data/spec/fixtures/vcr_cassettes/pul_loris_cassette.json +1 -1
- data/spec/fixtures/vcr_cassettes/pul_loris_cassette_v3.json +1 -0
- data/spec/integration/iiif/presentation/image_resource_spec.rb +0 -1
- data/spec/integration/iiif/service_spec.rb +17 -32
- data/spec/integration/iiif/v3/abstract_resource_spec.rb +202 -0
- data/spec/integration/iiif/v3/presentation/image_resource_spec.rb +118 -0
- data/spec/spec_helper.rb +6 -0
- data/spec/unit/iiif/presentation/canvas_spec.rb +0 -1
- data/spec/unit/iiif/presentation/manifest_spec.rb +1 -1
- data/spec/unit/iiif/v3/abstract_resource_define_methods_for_spec.rb +78 -0
- data/spec/unit/iiif/v3/abstract_resource_spec.rb +293 -0
- data/spec/unit/iiif/v3/presentation/annotation_collection_spec.rb +36 -0
- data/spec/unit/iiif/v3/presentation/annotation_page_spec.rb +131 -0
- data/spec/unit/iiif/v3/presentation/annotation_spec.rb +389 -0
- data/spec/unit/iiif/v3/presentation/canvas_spec.rb +337 -0
- data/spec/unit/iiif/v3/presentation/choice_spec.rb +120 -0
- data/spec/unit/iiif/v3/presentation/collection_spec.rb +55 -0
- data/spec/unit/iiif/v3/presentation/image_resource_spec.rb +189 -0
- data/spec/unit/iiif/v3/presentation/manifest_spec.rb +370 -0
- data/spec/unit/iiif/v3/presentation/nav_place_spec.rb +80 -0
- data/spec/unit/iiif/v3/presentation/range_spec.rb +54 -0
- data/spec/unit/iiif/v3/presentation/resource_spec.rb +174 -0
- data/spec/unit/iiif/v3/presentation/sequence_spec.rb +222 -0
- data/spec/unit/iiif/v3/presentation/service_spec.rb +220 -0
- data/spec/unit/iiif/v3/presentation/shared_examples/abstract_resource_only_keys.rb +41 -0
- data/spec/unit/iiif/v3/presentation/shared_examples/any_type_keys.rb +31 -0
- data/spec/unit/iiif/v3/presentation/shared_examples/array_only_keys.rb +40 -0
- data/spec/unit/iiif/v3/presentation/shared_examples/hash_only_keys.rb +40 -0
- data/spec/unit/iiif/v3/presentation/shared_examples/int_only_keys.rb +45 -0
- data/spec/unit/iiif/v3/presentation/shared_examples/numeric_only_keys.rb +45 -0
- data/spec/unit/iiif/v3/presentation/shared_examples/string_only_keys.rb +26 -0
- data/spec/unit/iiif/v3/presentation/shared_examples/uri_only_keys.rb +31 -0
- metadata +93 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 55260d04809482b5ebd267655c07543d4c97e2d5166bdca7b26eff5b22725fe6
|
4
|
+
data.tar.gz: 616cb247a11b55e56aac745508e5aa5000cae11c47b3e384d37ca2011b187c55
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e83acf715f8b6bf0513d1211ce5797237f28e9cead4c2cf3446b150ba496df81e16ba7b0d7ffae04aebe9cb40a4b84098c8d184e493f1259419cd0f9d99fae0b
|
7
|
+
data.tar.gz: 2221b5bcfc51cabfefc039584a58b93bd16fa95f7729e7921017bdac46b6d71e8cea6cbcc687e38f96a903386d4b7daf56d66693868e719b7cb6944ccc1067a3
|
data/.github/workflows/ruby.yml
CHANGED
data/.gitignore
CHANGED
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# O'Sullivan: A Ruby API for working with IIIF Presentation manifests
|
2
2
|
|
3
3
|
[![Coverage Status](https://coveralls.io/repos/github/iiif-prezi/osullivan/badge.svg?branch=development)](https://coveralls.io/github/iiif-prezi/osullivan?branch=development)
|
4
|
+
[![Gem Version](https://badge.fury.io/rb/iiif-presentation.svg)](https://badge.fury.io/rb/iiif-presentation)
|
4
5
|
|
5
6
|
|
6
7
|
## Installation
|
@@ -24,6 +25,11 @@ seed = {
|
|
24
25
|
# Any options you add are added to the object
|
25
26
|
manifest = IIIF::Presentation::Manifest.new(seed)
|
26
27
|
|
28
|
+
# sequences array is generated for you, but let's add a sequence object
|
29
|
+
sequence = IIIF::Presentation::Sequence.new()
|
30
|
+
sequence['@id'] = "http://example.com/manifest/seq/"
|
31
|
+
manifest.sequences << sequence
|
32
|
+
|
27
33
|
canvas = IIIF::Presentation::Canvas.new()
|
28
34
|
# All classes act like `ActiveSupport::OrderedHash`es, for the most part.
|
29
35
|
# Use `[]=` to set JSON-LD properties...
|
@@ -34,10 +40,25 @@ canvas.width = 10
|
|
34
40
|
canvas.height = 20
|
35
41
|
canvas.label = 'My Canvas'
|
36
42
|
|
43
|
+
# Add images
|
44
|
+
service = IIIF::Presentation::Resource.new('@context' => 'http://iiif.io/api/image/2/context.json', 'profile' => 'http://iiif.io/api/image/2/level2.json', '@id' => "http://images.exampl.com/loris2/my-image")
|
45
|
+
|
46
|
+
image = IIIF::Presentation::ImageResource.new()
|
47
|
+
i['@id'] = "http://images.exampl.com/loris2/my-image/full/#{canvas.width},#{canvas.height}/0/default.jpg"
|
48
|
+
i.format = "image/jpeg"
|
49
|
+
i.width = canvas.width
|
50
|
+
i.height = canvas.height
|
51
|
+
i.service = service
|
52
|
+
|
53
|
+
images = IIIF::Presentation::Resource.new('@type' => 'oa:Annotation', 'motivation' => 'sc:painting', '@id' => "#{canvas['@id']}/images", 'resource' => i)
|
54
|
+
|
55
|
+
canvas.images << images
|
56
|
+
|
57
|
+
# Add other content resources
|
37
58
|
oc = IIIF::Presentation::Resource.new('@id' => 'http://example.com/content')
|
38
59
|
canvas.other_content << oc
|
39
60
|
|
40
|
-
manifest.sequences << canvas
|
61
|
+
manifest.sequences.first.canvases << canvas
|
41
62
|
|
42
63
|
puts manifest.to_json(pretty: true)
|
43
64
|
```
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.
|
1
|
+
1.3.0
|
data/iiif-presentation.gemspec
CHANGED
data/lib/iiif/presentation.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
require File.join(File.dirname(__FILE__), 'service')
|
2
2
|
%w{
|
3
|
-
abstract_resource
|
3
|
+
abstract_resource
|
4
4
|
annotation
|
5
5
|
annotation_list
|
6
6
|
canvas
|
@@ -8,9 +8,10 @@ abstract_resource
|
|
8
8
|
layer
|
9
9
|
manifest
|
10
10
|
resource
|
11
|
-
|
12
|
-
sequence
|
13
|
-
|
11
|
+
image_resource
|
12
|
+
sequence
|
13
|
+
service
|
14
|
+
range
|
14
15
|
}.each do |f|
|
15
16
|
require File.join(File.dirname(__FILE__), 'presentation', f)
|
16
17
|
end
|
data/lib/iiif/service.rb
CHANGED
@@ -17,6 +17,7 @@ module IIIF
|
|
17
17
|
def abstract_resource_only_keys; %w{ }; end
|
18
18
|
def hash_only_keys; %w{ }; end
|
19
19
|
def int_only_keys; %w{ }; end
|
20
|
+
def numeric_only_keys; %w{ }; end
|
20
21
|
|
21
22
|
def initialize(hsh={})
|
22
23
|
@data = IIIF::OrderedHash[hsh]
|
@@ -24,6 +25,7 @@ module IIIF
|
|
24
25
|
self.define_methods_for_array_only_keys
|
25
26
|
self.define_methods_for_string_only_keys
|
26
27
|
self.define_methods_for_int_only_keys
|
28
|
+
self.define_methods_for_numeric_only_keys
|
27
29
|
self.define_methods_for_abstract_resource_only_keys
|
28
30
|
self.snakeize_keys
|
29
31
|
end
|
@@ -210,7 +212,7 @@ module IIIF
|
|
210
212
|
new_object[new_key] = []
|
211
213
|
hsh[key].each do |member|
|
212
214
|
if new_key == 'service'
|
213
|
-
new_object[new_key] << IIIF::Service.from_ordered_hash(member, IIIF::Service)
|
215
|
+
new_object[new_key] << IIIF::Service.from_ordered_hash(member, IIIF::Presentation::Service)
|
214
216
|
elsif new_key == 'resource'
|
215
217
|
new_object[new_key] << IIIF::Service.from_ordered_hash(hsh[key], IIIF::Presentation::Resource)
|
216
218
|
elsif member.kind_of?(Hash)
|
@@ -221,7 +223,7 @@ module IIIF
|
|
221
223
|
end
|
222
224
|
end
|
223
225
|
elsif new_key == 'service'
|
224
|
-
new_object[new_key] = IIIF::Service.from_ordered_hash(hsh[key], IIIF::Service)
|
226
|
+
new_object[new_key] = IIIF::Service.from_ordered_hash(hsh[key], IIIF::Presentation::Service)
|
225
227
|
elsif new_key == 'resource'
|
226
228
|
new_object[new_key] = IIIF::Service.from_ordered_hash(hsh[key], IIIF::Presentation::Resource)
|
227
229
|
elsif hsh[key].kind_of?(Hash)
|
@@ -255,56 +257,22 @@ module IIIF
|
|
255
257
|
end
|
256
258
|
|
257
259
|
def define_methods_for_any_type_keys
|
260
|
+
define_accessor_methods(*any_type_keys)
|
261
|
+
|
262
|
+
# override the getter defined by define_accessor_methods to avoid returning
|
263
|
+
# an array for empty values.
|
258
264
|
any_type_keys.each do |key|
|
259
|
-
# Setters
|
260
|
-
define_singleton_method("#{key}=") do |arg|
|
261
|
-
self.send('[]=', key, arg)
|
262
|
-
end
|
263
|
-
if key.camelize(:lower) != key
|
264
|
-
define_singleton_method("#{key.camelize(:lower)}=") do |arg|
|
265
|
-
self.send('[]=', key, arg)
|
266
|
-
end
|
267
|
-
end
|
268
|
-
# Getters
|
269
265
|
define_singleton_method(key) do
|
270
266
|
self.send('[]', key)
|
271
267
|
end
|
272
|
-
if key.camelize(:lower) != key
|
273
|
-
define_singleton_method(key.camelize(:lower)) do
|
274
|
-
self.send('[]', key)
|
275
|
-
end
|
276
|
-
end
|
277
268
|
end
|
278
269
|
end
|
279
270
|
|
280
271
|
def define_methods_for_array_only_keys
|
281
|
-
array_only_keys
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
m = "#{key} must be an Array."
|
286
|
-
raise IIIF::Presentation::IllegalValueError, m
|
287
|
-
end
|
288
|
-
self.send('[]=', key, arg)
|
289
|
-
end
|
290
|
-
if key.camelize(:lower) != key
|
291
|
-
define_singleton_method("#{key.camelize(:lower)}=") do |arg|
|
292
|
-
unless arg.kind_of?(Array)
|
293
|
-
m = "#{key} must be an Array."
|
294
|
-
raise IIIF::Presentation::IllegalValueError, m
|
295
|
-
end
|
296
|
-
self.send('[]=', key, arg)
|
297
|
-
end
|
298
|
-
end
|
299
|
-
# Getters
|
300
|
-
define_singleton_method(key) do
|
301
|
-
self[key] ||= []
|
302
|
-
self[key]
|
303
|
-
end
|
304
|
-
if key.camelize(:lower) != key
|
305
|
-
define_singleton_method(key.camelize(:lower)) do
|
306
|
-
self.send('[]', key)
|
307
|
-
end
|
272
|
+
define_accessor_methods(*array_only_keys) do |key, arg|
|
273
|
+
unless arg.kind_of?(Array)
|
274
|
+
m = "#{key} must be an Array."
|
275
|
+
raise IIIF::Presentation::IllegalValueError, m
|
308
276
|
end
|
309
277
|
end
|
310
278
|
end
|
@@ -314,85 +282,53 @@ module IIIF
|
|
314
282
|
abstract_resource_only_keys.each do |hsh|
|
315
283
|
key = hsh[:key]
|
316
284
|
type = hsh[:type]
|
317
|
-
|
318
|
-
|
285
|
+
|
286
|
+
define_accessor_methods(key) do |key, arg|
|
319
287
|
unless arg.kind_of?(type)
|
320
288
|
m = "#{key} must be an #{type}."
|
321
289
|
raise IIIF::Presentation::IllegalValueError, m
|
322
290
|
end
|
323
|
-
self.send('[]=', key, arg)
|
324
|
-
end
|
325
|
-
if key.camelize(:lower) != key
|
326
|
-
define_singleton_method("#{key.camelize(:lower)}=") do |arg|
|
327
|
-
unless arg.kind_of?(type)
|
328
|
-
m = "#{key} must be an #{type}."
|
329
|
-
raise IIIF::Presentation::IllegalValueError, m
|
330
|
-
end
|
331
|
-
self.send('[]=', key, arg)
|
332
|
-
end
|
333
|
-
end
|
334
|
-
# Getters
|
335
|
-
define_singleton_method(key) do
|
336
|
-
self[key] ||= []
|
337
|
-
self[key]
|
338
|
-
end
|
339
|
-
if key.camelize(:lower) != key
|
340
|
-
define_singleton_method(key.camelize(:lower)) do
|
341
|
-
self.send('[]', key)
|
342
|
-
end
|
343
291
|
end
|
344
292
|
end
|
345
293
|
end
|
346
294
|
|
347
|
-
|
348
295
|
def define_methods_for_string_only_keys
|
349
|
-
string_only_keys
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
m = "#{key} must be an String."
|
354
|
-
raise IIIF::Presentation::IllegalValueError, m
|
355
|
-
end
|
356
|
-
self.send('[]=', key, arg)
|
357
|
-
end
|
358
|
-
if key.camelize(:lower) != key
|
359
|
-
define_singleton_method("#{key.camelize(:lower)}=") do |arg|
|
360
|
-
unless arg.kind_of?(String)
|
361
|
-
m = "#{key} must be an String."
|
362
|
-
raise IIIF::Presentation::IllegalValueError, m
|
363
|
-
end
|
364
|
-
self.send('[]=', key, arg)
|
365
|
-
end
|
296
|
+
define_accessor_methods(*string_only_keys) do |key, arg|
|
297
|
+
unless arg.kind_of?(String)
|
298
|
+
m = "#{key} must be an String."
|
299
|
+
raise IIIF::Presentation::IllegalValueError, m
|
366
300
|
end
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
301
|
+
end
|
302
|
+
end
|
303
|
+
|
304
|
+
def define_methods_for_int_only_keys
|
305
|
+
define_accessor_methods(*int_only_keys) do |key, arg|
|
306
|
+
unless arg.kind_of?(Integer) && arg > 0
|
307
|
+
m = "#{key} must be a positive Integer."
|
308
|
+
raise IIIF::Presentation::IllegalValueError, m
|
371
309
|
end
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
310
|
+
end
|
311
|
+
end
|
312
|
+
|
313
|
+
def define_methods_for_numeric_only_keys
|
314
|
+
define_accessor_methods(*numeric_only_keys) do |key, arg|
|
315
|
+
unless arg.kind_of?(Numeric) && arg > 0
|
316
|
+
m = "#{key} must be a positive Integer or Float."
|
317
|
+
raise IIIF::Presentation::IllegalValueError, m
|
376
318
|
end
|
377
319
|
end
|
378
320
|
end
|
379
321
|
|
380
|
-
def
|
381
|
-
|
322
|
+
def define_accessor_methods(*keys, &validation)
|
323
|
+
keys.each do |key|
|
382
324
|
# Setter
|
383
325
|
define_singleton_method("#{key}=") do |arg|
|
384
|
-
|
385
|
-
m = "#{key} must be a positive Integer."
|
386
|
-
raise IIIF::Presentation::IllegalValueError, m
|
387
|
-
end
|
326
|
+
validation.call(key, arg) if block_given?
|
388
327
|
self.send('[]=', key, arg)
|
389
328
|
end
|
390
329
|
if key.camelize(:lower) != key
|
391
330
|
define_singleton_method("#{key.camelize(:lower)}=") do |arg|
|
392
|
-
|
393
|
-
m = "#{key} must be a positive Integer."
|
394
|
-
raise IIIF::Presentation::IllegalValueError, m
|
395
|
-
end
|
331
|
+
validation.call(key, arg) if block_given?
|
396
332
|
self.send('[]=', key, arg)
|
397
333
|
end
|
398
334
|
end
|
@@ -408,6 +344,5 @@ module IIIF
|
|
408
344
|
end
|
409
345
|
end
|
410
346
|
end
|
411
|
-
|
412
347
|
end
|
413
348
|
end
|