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.
Files changed (62) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ruby.yml +2 -2
  3. data/.gitignore +1 -0
  4. data/Gemfile +2 -0
  5. data/README.md +22 -1
  6. data/VERSION +1 -1
  7. data/iiif-presentation.gemspec +2 -1
  8. data/lib/iiif/presentation/canvas.rb +4 -0
  9. data/lib/iiif/presentation/service.rb +12 -0
  10. data/lib/iiif/presentation.rb +5 -4
  11. data/lib/iiif/service.rb +38 -103
  12. data/lib/iiif/v3/abstract_resource.rb +491 -0
  13. data/lib/iiif/v3/presentation/annotation.rb +74 -0
  14. data/lib/iiif/v3/presentation/annotation_collection.rb +38 -0
  15. data/lib/iiif/v3/presentation/annotation_page.rb +53 -0
  16. data/lib/iiif/v3/presentation/canvas.rb +82 -0
  17. data/lib/iiif/v3/presentation/choice.rb +51 -0
  18. data/lib/iiif/v3/presentation/collection.rb +52 -0
  19. data/lib/iiif/v3/presentation/image_resource.rb +110 -0
  20. data/lib/iiif/v3/presentation/manifest.rb +82 -0
  21. data/lib/iiif/v3/presentation/nav_place.rb +109 -0
  22. data/lib/iiif/v3/presentation/range.rb +39 -0
  23. data/lib/iiif/v3/presentation/resource.rb +30 -0
  24. data/lib/iiif/v3/presentation/sequence.rb +66 -0
  25. data/lib/iiif/v3/presentation/service.rb +51 -0
  26. data/lib/iiif/v3/presentation.rb +37 -0
  27. data/spec/fixtures/v3/manifests/complete_from_spec.json +195 -0
  28. data/spec/fixtures/v3/manifests/minimal.json +49 -0
  29. data/spec/fixtures/v3/manifests/service_only.json +14 -0
  30. data/spec/fixtures/vcr_cassettes/pul_loris_cassette.json +1 -1
  31. data/spec/fixtures/vcr_cassettes/pul_loris_cassette_v3.json +1 -0
  32. data/spec/integration/iiif/presentation/image_resource_spec.rb +0 -1
  33. data/spec/integration/iiif/service_spec.rb +17 -32
  34. data/spec/integration/iiif/v3/abstract_resource_spec.rb +202 -0
  35. data/spec/integration/iiif/v3/presentation/image_resource_spec.rb +118 -0
  36. data/spec/spec_helper.rb +6 -0
  37. data/spec/unit/iiif/presentation/canvas_spec.rb +0 -1
  38. data/spec/unit/iiif/presentation/manifest_spec.rb +1 -1
  39. data/spec/unit/iiif/v3/abstract_resource_define_methods_for_spec.rb +78 -0
  40. data/spec/unit/iiif/v3/abstract_resource_spec.rb +293 -0
  41. data/spec/unit/iiif/v3/presentation/annotation_collection_spec.rb +36 -0
  42. data/spec/unit/iiif/v3/presentation/annotation_page_spec.rb +131 -0
  43. data/spec/unit/iiif/v3/presentation/annotation_spec.rb +389 -0
  44. data/spec/unit/iiif/v3/presentation/canvas_spec.rb +337 -0
  45. data/spec/unit/iiif/v3/presentation/choice_spec.rb +120 -0
  46. data/spec/unit/iiif/v3/presentation/collection_spec.rb +55 -0
  47. data/spec/unit/iiif/v3/presentation/image_resource_spec.rb +189 -0
  48. data/spec/unit/iiif/v3/presentation/manifest_spec.rb +370 -0
  49. data/spec/unit/iiif/v3/presentation/nav_place_spec.rb +80 -0
  50. data/spec/unit/iiif/v3/presentation/range_spec.rb +54 -0
  51. data/spec/unit/iiif/v3/presentation/resource_spec.rb +174 -0
  52. data/spec/unit/iiif/v3/presentation/sequence_spec.rb +222 -0
  53. data/spec/unit/iiif/v3/presentation/service_spec.rb +220 -0
  54. data/spec/unit/iiif/v3/presentation/shared_examples/abstract_resource_only_keys.rb +41 -0
  55. data/spec/unit/iiif/v3/presentation/shared_examples/any_type_keys.rb +31 -0
  56. data/spec/unit/iiif/v3/presentation/shared_examples/array_only_keys.rb +40 -0
  57. data/spec/unit/iiif/v3/presentation/shared_examples/hash_only_keys.rb +40 -0
  58. data/spec/unit/iiif/v3/presentation/shared_examples/int_only_keys.rb +45 -0
  59. data/spec/unit/iiif/v3/presentation/shared_examples/numeric_only_keys.rb +45 -0
  60. data/spec/unit/iiif/v3/presentation/shared_examples/string_only_keys.rb +26 -0
  61. data/spec/unit/iiif/v3/presentation/shared_examples/uri_only_keys.rb +31 -0
  62. metadata +93 -5
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 39369e50dc0a31ebfdac97d49008eb26e020ac21c595c400906dc6a54de45097
4
- data.tar.gz: e127162464e102ef0d2ee9800cf81713e0cd681edde07e3123bf5353b1b1fb90
3
+ metadata.gz: 55260d04809482b5ebd267655c07543d4c97e2d5166bdca7b26eff5b22725fe6
4
+ data.tar.gz: 616cb247a11b55e56aac745508e5aa5000cae11c47b3e384d37ca2011b187c55
5
5
  SHA512:
6
- metadata.gz: 230c5a28d5e5dbc405b32f9e6ca1f3d60e7f8e2d3cbbeab85f9650dbf24bb701d0a1c6af1b29d1cd844ac971e11e1ab8a65644cf10f33778e1465d8b1fcc01ad
7
- data.tar.gz: 0ab62efe7287d7eaae0ae7ab2a569b18cd2238753569e15857478976a834e5746df1dd919befe211299f31fae63822a735e25fe9da22b5e74b7d05b08457e608
6
+ metadata.gz: e83acf715f8b6bf0513d1211ce5797237f28e9cead4c2cf3446b150ba496df81e16ba7b0d7ffae04aebe9cb40a4b84098c8d184e493f1259419cd0f9d99fae0b
7
+ data.tar.gz: 2221b5bcfc51cabfefc039584a58b93bd16fa95f7729e7921017bdac46b6d71e8cea6cbcc687e38f96a903386d4b7daf56d66693868e719b7cb6944ccc1067a3
@@ -9,9 +9,9 @@ name: Ruby
9
9
 
10
10
  on:
11
11
  push:
12
- branches: [ "development" ]
12
+ branches: [ "main" ]
13
13
  pull_request:
14
- branches: [ "development" ]
14
+ branches: [ "main" ]
15
15
 
16
16
  permissions:
17
17
  contents: read
data/.gitignore CHANGED
@@ -1,4 +1,5 @@
1
1
  coverage/
2
2
  pkg/
3
3
  Gemfile.lock
4
+ .pry_history
4
5
 
data/Gemfile CHANGED
@@ -8,3 +8,5 @@ end
8
8
  if ENV['FARADAY_VERSION']
9
9
  gem 'faraday', ENV['FARADAY_VERSION']
10
10
  end
11
+
12
+ gem 'debug'
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.0
1
+ 1.3.0
@@ -24,5 +24,6 @@ Gem::Specification.new do |spec|
24
24
 
25
25
  spec.add_dependency 'json'
26
26
  spec.add_dependency 'activesupport', '>= 3.2.18'
27
- spec.add_dependency 'faraday', '>= 0.9'
27
+ spec.add_dependency 'faraday', '~> 2.7'
28
+ spec.add_dependency 'geo_coord'
28
29
  end
@@ -25,6 +25,10 @@ module IIIF
25
25
  super + %w{ width height }
26
26
  end
27
27
 
28
+ def numeric_only_keys
29
+ super + %w{ duration }
30
+ end
31
+
28
32
  def legal_viewing_hint_values
29
33
  super + %w{ non-paged }
30
34
  end
@@ -0,0 +1,12 @@
1
+ require File.join(File.dirname(__FILE__), 'abstract_resource')
2
+
3
+ module IIIF
4
+ module Presentation
5
+ class Service < AbstractResource
6
+ def required_keys
7
+ []
8
+ end
9
+ end
10
+ end
11
+ end
12
+
@@ -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
- image_resource
12
- sequence
13
- range
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.each do |key|
282
- # Setters
283
- define_singleton_method("#{key}=") do |arg|
284
- unless arg.kind_of?(Array)
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
- # Setters
318
- define_singleton_method("#{key}=") do |arg|
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.each do |key|
350
- # Setter
351
- define_singleton_method("#{key}=") do |arg|
352
- unless arg.kind_of?(String)
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
- # Getter
368
- define_singleton_method(key) do
369
- self[key] ||= []
370
- self[key]
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
- if key.camelize(:lower) != key
373
- define_singleton_method(key.camelize(:lower)) do
374
- self.send('[]', key)
375
- end
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 define_methods_for_int_only_keys
381
- int_only_keys.each do |key|
322
+ def define_accessor_methods(*keys, &validation)
323
+ keys.each do |key|
382
324
  # Setter
383
325
  define_singleton_method("#{key}=") do |arg|
384
- unless arg.kind_of?(Integer) && arg > 0
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
- unless arg.kind_of?(Integer) && arg > 0
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