iiif_manifest 0.2.0 → 0.3.0

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.
Files changed (34) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +0 -0
  3. data/.rspec +0 -0
  4. data/.rubocop.yml +15 -0
  5. data/.rubocop_todo.yml +84 -0
  6. data/.travis.yml +0 -0
  7. data/CODE_OF_CONDUCT.md +0 -0
  8. data/Gemfile +0 -0
  9. data/LICENSE +0 -0
  10. data/README.md +48 -2
  11. data/Rakefile +12 -3
  12. data/bin/console +3 -3
  13. data/iiif_manifest.gemspec +17 -15
  14. data/lib/iiif_manifest/display_image.rb +0 -0
  15. data/lib/iiif_manifest/iiif_collection.rb +1 -0
  16. data/lib/iiif_manifest/iiif_endpoint.rb +1 -1
  17. data/lib/iiif_manifest/manifest_builder/canvas_builder.rb +15 -13
  18. data/lib/iiif_manifest/manifest_builder/canvas_builder_factory.rb +3 -3
  19. data/lib/iiif_manifest/manifest_builder/child_manifest_builder_factory.rb +0 -0
  20. data/lib/iiif_manifest/manifest_builder/composite_builder.rb +0 -0
  21. data/lib/iiif_manifest/manifest_builder/composite_builder_factory.rb +0 -0
  22. data/lib/iiif_manifest/manifest_builder/deep_canvas_builder_factory.rb +6 -6
  23. data/lib/iiif_manifest/manifest_builder/image_builder.rb +14 -12
  24. data/lib/iiif_manifest/manifest_builder/image_service_builder.rb +6 -5
  25. data/lib/iiif_manifest/manifest_builder/record_property_builder.rb +28 -11
  26. data/lib/iiif_manifest/manifest_builder/resource_builder.rb +13 -11
  27. data/lib/iiif_manifest/manifest_builder/sequence_builder.rb +23 -13
  28. data/lib/iiif_manifest/manifest_builder/structure_builder.rb +94 -0
  29. data/lib/iiif_manifest/manifest_builder.rb +9 -8
  30. data/lib/iiif_manifest/manifest_factory.rb +0 -0
  31. data/lib/iiif_manifest/manifest_service_locator.rb +65 -3
  32. data/lib/iiif_manifest/version.rb +1 -1
  33. data/lib/iiif_manifest.rb +1 -1
  34. metadata +48 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d5708ab4381068e5d90cbc1607d2e8dafceb391e
4
- data.tar.gz: 6e064f9d5faa44116fdf986b09c05bf796f5267f
3
+ metadata.gz: 9bf49dd68d7cea2339444aafd8eb4f98ac3cdcd9
4
+ data.tar.gz: ddee2270d2cf0f5098c40ecee97fd696a59a36f1
5
5
  SHA512:
6
- metadata.gz: b736502a559e0a94918587c3ca9d94e3584050ad619431795b19be30e038b79a62e2272d14abcfe144f7324f33ec841018dccffd80faa1546e6642b9dac97774
7
- data.tar.gz: 4e6415c54ee2c842f98492259f1be5326947414d312b949f30c71b67a9893c2847c8dfd0003c0af310f3206543d457ace81a35f484245b211aacebdbdc6c06b9
6
+ metadata.gz: ef3820b328e75af3da30aee55bafd526ae0d6ae7c7533cc53bf0ae743d61d83cf027cca5048a70460a02eb39103c94c2e03e900be19ffe29b57e3cee3b61b4bc
7
+ data.tar.gz: 5c948e5dc59e0926ce983c9ba6445d4f7011f342eae3bd18cff854a5183687affb78e396e2498c54f8be240268b6774d415be69ec38fa77fe2526df8f2916908
data/.gitignore CHANGED
File without changes
data/.rspec CHANGED
File without changes
data/.rubocop.yml ADDED
@@ -0,0 +1,15 @@
1
+ require: rubocop-rspec
2
+ inherit_from: .rubocop_todo.yml
3
+
4
+ AllCops:
5
+ DisplayCopNames: true
6
+
7
+ Metrics/LineLength:
8
+ Max: 120
9
+
10
+ Metrics/BlockLength:
11
+ Exclude:
12
+ - 'spec/**/*.rb'
13
+
14
+ RSpec/MultipleExpectations:
15
+ Enabled: false
data/.rubocop_todo.yml ADDED
@@ -0,0 +1,84 @@
1
+ # This configuration was generated by
2
+ # `rubocop --auto-gen-config`
3
+ # on 2017-07-26 10:46:37 -0500 using RuboCop version 0.49.1.
4
+ # The point is for the user to remove these configuration records
5
+ # one by one as the offenses are removed from the code base.
6
+ # Note that changes in the inspected code, or installation of new
7
+ # versions of RuboCop, may require this file to be generated again.
8
+
9
+ # Offense count: 2
10
+ Metrics/AbcSize:
11
+ Exclude:
12
+ - 'lib/iiif_manifest/manifest_builder/resource_builder.rb'
13
+ - 'lib/iiif_manifest/manifest_factory.rb'
14
+
15
+ # Offense count: 1
16
+ # Configuration parameters: AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns.
17
+ # URISchemes: http, https
18
+ Metrics/LineLength:
19
+ Exclude:
20
+ - 'iiif_manifest.gemspec'
21
+
22
+ # Offense count: 1
23
+ # Configuration parameters: AssignmentOnly.
24
+ RSpec/InstanceVariable:
25
+ Exclude:
26
+ - 'spec/lib/iiif_manifest/manifest_factory_spec.rb'
27
+
28
+ # Offense count: 8
29
+ RSpec/NamedSubject:
30
+ Exclude:
31
+ - 'spec/lib/iiif_manifest/display_image_spec.rb'
32
+ - 'spec/lib/iiif_manifest/iiif_endpoint_spec.rb'
33
+ - 'spec/lib/iiif_manifest/manifest_builder/resource_builder_spec.rb'
34
+
35
+ # Offense count: 1
36
+ # Configuration parameters: IgnoreSymbolicNames.
37
+ RSpec/VerifiedDoubles:
38
+ Exclude:
39
+ - 'spec/lib/iiif_manifest/display_image_spec.rb'
40
+
41
+ RSpec/ExampleLength:
42
+ Exclude:
43
+ - 'spec/lib/iiif_manifest/manifest_factory_spec.rb'
44
+
45
+ # Offense count: 20
46
+ Style/Documentation:
47
+ Exclude:
48
+ - 'lib/iiif_manifest/display_image.rb'
49
+ - 'lib/iiif_manifest/iiif_collection.rb'
50
+ - 'lib/iiif_manifest/iiif_endpoint.rb'
51
+ - 'lib/iiif_manifest/manifest_builder/canvas_builder.rb'
52
+ - 'lib/iiif_manifest/manifest_builder/canvas_builder.rb'
53
+ - 'lib/iiif_manifest/manifest_builder/canvas_builder_factory.rb'
54
+ - 'lib/iiif_manifest/manifest_builder/child_manifest_builder_factory.rb'
55
+ - 'lib/iiif_manifest/manifest_builder/composite_builder.rb'
56
+ - 'lib/iiif_manifest/manifest_builder/composite_builder_factory.rb'
57
+ - 'lib/iiif_manifest/manifest_builder/deep_canvas_builder_factory.rb'
58
+ - 'lib/iiif_manifest/manifest_builder/image_builder.rb'
59
+ - 'lib/iiif_manifest/manifest_builder/image_service_builder.rb'
60
+ - 'lib/iiif_manifest/manifest_builder/record_property_builder.rb'
61
+ - 'lib/iiif_manifest/manifest_builder/resource_builder.rb'
62
+ - 'lib/iiif_manifest/manifest_builder/sequence_builder.rb'
63
+ - 'lib/iiif_manifest/manifest_builder/structure_builder.rb'
64
+ - 'lib/iiif_manifest/manifest_builder.rb'
65
+ - 'lib/iiif_manifest/manifest_factory.rb'
66
+ - 'lib/iiif_manifest/manifest_service_locator.rb'
67
+ - 'lib/iiif_manifest.rb'
68
+ - 'spec/lib/iiif_manifest/manifest_factory_spec.rb'
69
+
70
+ # Offense count: 1
71
+ Style/MethodMissing:
72
+ Exclude:
73
+ - 'lib/iiif_manifest/manifest_builder/composite_builder.rb'
74
+
75
+ Metrics/ClassLength:
76
+ Exclude:
77
+ - 'lib/iiif_manifest/manifest_service_locator.rb'
78
+
79
+ # Offense count: 1
80
+ # Cop supports --auto-correct.
81
+ # Configuration parameters: MinSize, SupportedStyles.
82
+ # SupportedStyles: percent, brackets
83
+ Style/SymbolArray:
84
+ EnforcedStyle: brackets
data/.travis.yml CHANGED
File without changes
data/CODE_OF_CONDUCT.md CHANGED
File without changes
data/Gemfile CHANGED
File without changes
data/LICENSE CHANGED
File without changes
data/README.md CHANGED
@@ -5,11 +5,23 @@ IIIF http://iiif.io/ defines an API for presenting related images in a viewer. T
5
5
 
6
6
  ## Usage
7
7
 
8
- You application must have an object that implements `#file_set_presenters` and `#work_presenters`. The former method should return as set of leaf nodes and the later any interstitial nodes. If none are found an empty array should be returned. Additionally it should implement `#manifest_url` that shows where the manifest can be found. Finally, it must have a `#description` method that returns a string.
8
+ Your application ***must*** have an object that implements `#file_set_presenters` and `#work_presenters`. The former method should return as set of leaf nodes and the later any interstitial nodes. If none are found an empty array should be returned.
9
+
10
+ Additionally, it ***must*** have a `#description` method that returns a string.
11
+
12
+ Additionally it ***should*** implement `#manifest_url` that shows where the manifest can be found.
13
+
14
+ Additionally it ***should*** implement `#manifest_metadata` to provide an array containing hashes of metadata Label/Value pairs.
15
+
16
+ Additionally it ***may*** implement `#sequence_rendering` to contain an array of hashes for file downloads to be offered at sequences level. Each hash must contain "@id", "format" (mime type) and "label" (eg. `{ "@id" => "download url", "format" => "application/pdf", "label" => "user friendly label" }`).
17
+
18
+ Finally, It ***may*** implement `ranges`, which returns an array of objects which
19
+ represent a table of contents or similar structure, each of which responds to
20
+ `label`, `ranges`, and `file_set_presenters`.
9
21
 
10
22
  For example:
11
23
 
12
- ```ruby
24
+ ```ruby
13
25
  class Book
14
26
  def initialize(id, pages = [])
15
27
  @id = id
@@ -31,6 +43,40 @@ For example:
31
43
  def description
32
44
  'a brief description'
33
45
  end
46
+
47
+ def manifest_metadata
48
+ [
49
+ { "label" => "Title", "value" => "Title of the Item" },
50
+ { "label" => "Creator", "value" => "Morrissey, Stephen Patrick" }
51
+ ]
52
+ end
53
+
54
+ def sequence_rendering
55
+ [{"@id" => "http://test.host/file_set/id/download", "format" => "application/pdf", "label" => "Download"}]
56
+ end
57
+
58
+ def ranges
59
+ [
60
+ ManifestRange.new(
61
+ label: "Table of Contents",
62
+ ranges: [
63
+ ManifestRange.new(
64
+ label: "Chapter 1",
65
+ file_set_presenters: @pages
66
+ )
67
+ ]
68
+ )
69
+ ]
70
+ end
71
+ end
72
+
73
+ class ManifestRange
74
+ attr_reader :label, :ranges, :file_set_presenters
75
+ def initialize(label:, ranges: [], file_set_presenters: [])
76
+ @label = label
77
+ @ranges = ranges
78
+ @file_set_presenters = file_set_presenters
79
+ end
34
80
  end
35
81
  ```
36
82
 
data/Rakefile CHANGED
@@ -1,6 +1,15 @@
1
- require "bundler/gem_tasks"
2
- require "rspec/core/rake_task"
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
+ require 'rubocop/rake_task'
3
4
 
4
5
  RSpec::Core::RakeTask.new(:spec)
5
6
 
6
- task :default => :spec
7
+ desc 'Run style checker'
8
+ RuboCop::RakeTask.new(:rubocop) do |task|
9
+ task.fail_on_error = true
10
+ end
11
+
12
+ desc 'Run all checks'
13
+ task ci: [:rubocop, :spec]
14
+
15
+ task default: :ci
data/bin/console CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require "bundler/setup"
4
- require "iiif_manifest"
3
+ require 'bundler/setup'
4
+ require 'iiif_manifest'
5
5
 
6
6
  # You can add fixtures and/or initialization code here to make experimenting
7
7
  # with your gem easier. You can also use a different console, if you like.
@@ -10,5 +10,5 @@ require "iiif_manifest"
10
10
  # require "pry"
11
11
  # Pry.start
12
12
 
13
- require "irb"
13
+ require 'irb'
14
14
  IRB.start
@@ -1,27 +1,29 @@
1
- # coding: utf-8
2
1
  lib = File.expand_path('../lib', __FILE__)
3
2
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
3
  require 'iiif_manifest/version'
5
4
 
6
5
  Gem::Specification.new do |spec|
7
- spec.name = "iiif_manifest"
6
+ spec.name = 'iiif_manifest'
8
7
  spec.version = IIIFManifest::VERSION
9
- spec.authors = ["Justin Coyne", "Trey Pendragon"]
10
- spec.email = ["jcoyne@justincoyne.com"]
8
+ spec.authors = ['Justin Coyne', 'Trey Pendragon']
9
+ spec.email = ['jcoyne@justincoyne.com']
11
10
 
12
- spec.summary = %q{Generate IIIF presentation manifests for Hydra::Works}
13
- spec.description = %q{IIIF http://iiif.io/ defines an API for presenting related images in a viewer. This transforms Hydra::Works objects into that format usable by players such as http://universalviewer.io/}
14
- spec.homepage = "http://github.com/projecthydra-labs/iiif_manifest"
11
+ spec.summary = 'Generate IIIF presentation manifests for Hydra::Works'
12
+ spec.description = 'IIIF http://iiif.io/ defines an API for presenting related images in a viewer. This transforms Hydra::Works objects into that format usable by players such as http://universalviewer.io/'
13
+ spec.homepage = 'http://github.com/projecthydra-labs/iiif_manifest'
15
14
 
16
15
  spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
17
- spec.bindir = "exe"
16
+ spec.bindir = 'exe'
18
17
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
19
- spec.require_paths = ["lib"]
18
+ spec.require_paths = ['lib']
20
19
 
21
- spec.add_dependency "activesupport", ">= 4"
22
- spec.add_dependency "iiif-presentation", '~> 0.2.0'
23
-
24
- spec.add_development_dependency "bundler", "~> 1.11"
25
- spec.add_development_dependency "rake", "~> 10.0"
26
- spec.add_development_dependency "rspec", "~> 3.0"
20
+ spec.add_dependency 'activesupport', '>= 4'
21
+ spec.add_dependency 'iiif-presentation', '~> 0.2.0'
22
+
23
+ spec.add_development_dependency 'bundler', '~> 1.11'
24
+ spec.add_development_dependency 'rake', '~> 10.0'
25
+ spec.add_development_dependency 'rspec', '~> 3.0'
26
+ spec.add_development_dependency 'rubocop'
27
+ spec.add_development_dependency 'rubocop-rspec'
28
+ spec.add_development_dependency 'pry-byebug'
27
29
  end
File without changes
@@ -1,5 +1,6 @@
1
1
  class IIIFCollection < SimpleDelegator
2
2
  def viewing_hint
3
+ return super if __getobj__.respond_to?(:viewing_hint)
3
4
  'multi-part'
4
5
  end
5
6
  end
@@ -7,7 +7,7 @@ module IIIFManifest
7
7
  end
8
8
 
9
9
  def context
10
- "http://iiif.io/api/image/2/context.json"
10
+ 'http://iiif.io/api/image/2/context.json'
11
11
  end
12
12
  end
13
13
  end
@@ -1,17 +1,19 @@
1
1
  module IIIFManifest
2
2
  class ManifestBuilder
3
3
  class CanvasBuilder
4
- attr_reader :record, :parent
4
+ attr_reader :record, :parent, :iiif_canvas_factory, :image_builder
5
5
 
6
- def initialize(record, parent)
6
+ def initialize(record, parent, iiif_canvas_factory:, image_builder:)
7
7
  @record = record
8
8
  @parent = parent
9
+ @iiif_canvas_factory = iiif_canvas_factory
10
+ @image_builder = image_builder
9
11
  apply_record_properties
10
12
  attach_image if display_image
11
13
  end
12
14
 
13
15
  def canvas
14
- @canvas ||= IIIF::Presentation::Canvas.new
16
+ @canvas ||= iiif_canvas_factory.new
15
17
  end
16
18
 
17
19
  def path
@@ -26,18 +28,18 @@ module IIIFManifest
26
28
 
27
29
  private
28
30
 
29
- def display_image
30
- record.display_image if record.respond_to?(:display_image)
31
- end
31
+ def display_image
32
+ record.display_image if record.respond_to?(:display_image)
33
+ end
32
34
 
33
- def apply_record_properties
34
- canvas['@id'] = path
35
- canvas.label = record.to_s
36
- end
35
+ def apply_record_properties
36
+ canvas['@id'] = path
37
+ canvas.label = record.to_s
38
+ end
37
39
 
38
- def attach_image
39
- ImageBuilder.new(display_image).apply(canvas)
40
- end
40
+ def attach_image
41
+ image_builder.new(display_image).apply(canvas)
42
+ end
41
43
  end
42
44
  end
43
45
  end
@@ -17,9 +17,9 @@ module IIIFManifest
17
17
 
18
18
  private
19
19
 
20
- def file_set_presenters(work)
21
- work.file_set_presenters
22
- end
20
+ def file_set_presenters(work)
21
+ work.file_set_presenters
22
+ end
23
23
  end
24
24
  end
25
25
  end
@@ -26,13 +26,13 @@ module IIIFManifest
26
26
 
27
27
  private
28
28
 
29
- def file_set_presenters
30
- work.try(:file_set_presenters) || []
31
- end
29
+ def file_set_presenters
30
+ work.try(:file_set_presenters) || []
31
+ end
32
32
 
33
- def work_presenters
34
- work.try(:work_presenters) || []
35
- end
33
+ def work_presenters
34
+ work.try(:work_presenters) || []
35
+ end
36
36
  end
37
37
  end
38
38
  end
@@ -1,9 +1,11 @@
1
1
  module IIIFManifest
2
2
  class ManifestBuilder
3
3
  class ImageBuilder
4
- attr_reader :display_image
5
- def initialize(display_image)
4
+ attr_reader :display_image, :iiif_annotation_factory, :resource_builder_factory
5
+ def initialize(display_image, iiif_annotation_factory:, resource_builder_factory:)
6
6
  @display_image = display_image
7
+ @iiif_annotation_factory = iiif_annotation_factory
8
+ @resource_builder_factory = resource_builder_factory
7
9
  build_resource
8
10
  end
9
11
 
@@ -11,22 +13,22 @@ module IIIFManifest
11
13
  annotation['on'] = canvas['@id']
12
14
  canvas['width'] = annotation.resource['width']
13
15
  canvas['height'] = annotation.resource['height']
14
- canvas.images << annotation
16
+ canvas.images += [annotation]
15
17
  end
16
18
 
17
19
  private
18
20
 
19
- def build_resource
20
- resource_builder.apply(annotation)
21
- end
21
+ def build_resource
22
+ resource_builder.apply(annotation)
23
+ end
22
24
 
23
- def resource_builder
24
- ResourceBuilder.new(display_image)
25
- end
25
+ def resource_builder
26
+ resource_builder_factory.new(display_image)
27
+ end
26
28
 
27
- def annotation
28
- @annotation ||= IIIF::Presentation::Annotation.new
29
- end
29
+ def annotation
30
+ @annotation ||= iiif_annotation_factory.new
31
+ end
30
32
  end
31
33
  end
32
34
  end
@@ -1,9 +1,10 @@
1
1
  module IIIFManifest
2
2
  class ManifestBuilder
3
3
  class ImageServiceBuilder
4
- attr_reader :iiif_endpoint
5
- def initialize(iiif_endpoint)
4
+ attr_reader :iiif_endpoint, :iiif_service_factory
5
+ def initialize(iiif_endpoint, iiif_service_factory:)
6
6
  @iiif_endpoint = iiif_endpoint
7
+ @iiif_service_factory = iiif_service_factory
7
8
  end
8
9
 
9
10
  def apply(resource)
@@ -15,9 +16,9 @@ module IIIFManifest
15
16
 
16
17
  private
17
18
 
18
- def service
19
- @service ||= IIIF::Service.new
20
- end
19
+ def service
20
+ @service ||= iiif_service_factory.new
21
+ end
21
22
  end
22
23
  end
23
24
  end
@@ -10,24 +10,41 @@ module IIIFManifest
10
10
  manifest['@id'] = record.manifest_url.to_s
11
11
  manifest.label = record.to_s
12
12
  manifest.description = record.description
13
- manifest.viewing_hint = viewing_hint
13
+ manifest.viewing_hint = viewing_hint if viewing_hint.present?
14
+ manifest.metadata = record.manifest_metadata if valid_metadata?
14
15
  manifest
15
- # manifest.try(:viewing_direction=, viewing_direction)
16
16
  end
17
17
 
18
18
  private
19
19
 
20
- def viewing_hint
21
- (record.respond_to?(:viewing_hint) && record.send(:viewing_hint)) || 'individuals'
22
- end
20
+ def viewing_hint
21
+ (record.respond_to?(:viewing_hint) && record.send(:viewing_hint))
22
+ end
23
+
24
+ # Validate manifest_metadata against the IIIF spec format for metadata
25
+ #
26
+ # @return [Boolean]
27
+ def valid_metadata?
28
+ return false unless record.respond_to?(:manifest_metadata)
29
+ metadata = record.manifest_metadata
30
+ valid_metadata_structure?(metadata) && valid_metadata_content?(metadata)
31
+ end
23
32
 
24
- # def viewing_direction
25
- # record.try(:viewing_direction) || "left-to-right"
26
- # end
33
+ # Manifest metadata must be an array containing hashes
27
34
  #
28
- # def viewing_hint
29
- # record.viewing_hint || "individuals"
30
- # end
35
+ # @param metadata [Array<Hash>] a list of metadata with label and value as required keys for each entry
36
+ # @return [Boolean]
37
+ def valid_metadata_structure?(metadata)
38
+ metadata.is_a?(Array) && metadata.all? { |v| v.is_a?(Hash) }
39
+ end
40
+
41
+ # Manifest Metadata Hashes must contain 'label' and 'value' keys
42
+ #
43
+ # @param metadata [Array<Hash>] a list of metadata with label and value as required keys for each entry
44
+ # @return [Boolean]
45
+ def valid_metadata_content?(metadata)
46
+ metadata.all? { |v| v['label'].present? && v['value'].present? }
47
+ end
31
48
  end
32
49
  end
33
50
  end
@@ -1,9 +1,11 @@
1
1
  module IIIFManifest
2
2
  class ManifestBuilder
3
3
  class ResourceBuilder
4
- attr_reader :display_image
5
- def initialize(display_image)
4
+ attr_reader :display_image, :iiif_resource_factory, :image_service_builder_factory
5
+ def initialize(display_image, iiif_resource_factory:, image_service_builder_factory:)
6
6
  @display_image = display_image
7
+ @iiif_resource_factory = iiif_resource_factory
8
+ @image_service_builder_factory = image_service_builder_factory
7
9
  end
8
10
 
9
11
  def apply(annotation)
@@ -18,17 +20,17 @@ module IIIFManifest
18
20
 
19
21
  private
20
22
 
21
- def resource
22
- @resource ||= IIIF::Presentation::Resource.new
23
- end
23
+ def resource
24
+ @resource ||= iiif_resource_factory.new
25
+ end
24
26
 
25
- def iiif_endpoint
26
- display_image.try(:iiif_endpoint)
27
- end
27
+ def iiif_endpoint
28
+ display_image.try(:iiif_endpoint)
29
+ end
28
30
 
29
- def image_service_builder
30
- ImageServiceBuilder.new(iiif_endpoint)
31
- end
31
+ def image_service_builder
32
+ image_service_builder_factory.new(iiif_endpoint)
33
+ end
32
34
  end
33
35
  end
34
36
  end
@@ -1,10 +1,11 @@
1
1
  module IIIFManifest
2
2
  class ManifestBuilder
3
3
  class SequenceBuilder
4
- attr_reader :work, :canvas_builder_factory
5
- def initialize(work, canvas_builder_factory:)
4
+ attr_reader :work, :canvas_builder_factory, :sequence_factory
5
+ def initialize(work, canvas_builder_factory:, sequence_factory:)
6
6
  @work = work
7
7
  @canvas_builder_factory = canvas_builder_factory
8
+ @sequence_factory = sequence_factory
8
9
  end
9
10
 
10
11
  def apply(manifest)
@@ -19,19 +20,28 @@ module IIIFManifest
19
20
 
20
21
  private
21
22
 
22
- def canvas_builder
23
- canvas_builder_factory.from(work)
24
- end
23
+ def canvas_builder
24
+ canvas_builder_factory.from(work)
25
+ end
25
26
 
26
- def sequence
27
- @sequence ||=
28
- begin
29
- sequence = IIIF::Presentation::Sequence.new
30
- sequence["@id"] ||= work.manifest_url + "/sequence/normal"
31
- canvas_builder.apply(sequence)
32
- sequence
33
- end
27
+ def sequence
28
+ @sequence ||=
29
+ begin
30
+ sequence = sequence_factory.new
31
+ sequence['@id'] ||= work.manifest_url + '/sequence/normal'
32
+ sequence['rendering'] ||= populate_sequence_rendering
33
+ canvas_builder.apply(sequence)
34
+ sequence
35
+ end
36
+ end
37
+
38
+ def populate_sequence_rendering
39
+ if work.respond_to?(:sequence_rendering)
40
+ work.sequence_rendering.each(&:to_h)
41
+ else
42
+ []
34
43
  end
44
+ end
35
45
  end
36
46
  end
37
47
  end
@@ -0,0 +1,94 @@
1
+ module IIIFManifest
2
+ class ManifestBuilder
3
+ class StructureBuilder
4
+ attr_reader :record, :canvas_builder_factory, :iiif_range_factory
5
+ def initialize(record, canvas_builder_factory:, iiif_range_factory:)
6
+ @record = record
7
+ @canvas_builder_factory = canvas_builder_factory
8
+ @iiif_range_factory = iiif_range_factory
9
+ end
10
+
11
+ def apply(manifest)
12
+ top_ranges.each do |top_range|
13
+ manifest['structures'] ||= []
14
+ manifest['structures'] = range_builder(top_range).apply(manifest['structures'])
15
+ end
16
+ manifest
17
+ end
18
+
19
+ def range_builder(top_range)
20
+ RangeBuilder.new(
21
+ top_range,
22
+ record, true,
23
+ canvas_builder_factory: canvas_builder_factory,
24
+ iiif_range_factory: iiif_range_factory
25
+ )
26
+ end
27
+
28
+ def top_ranges
29
+ record.try(:ranges) || []
30
+ end
31
+ end
32
+ class RangeBuilder
33
+ attr_reader :record, :parent, :canvas_builder_factory, :iiif_range_factory
34
+ delegate :file_set_presenters, to: :record
35
+ def initialize(record, parent, top = false, canvas_builder_factory:, iiif_range_factory:)
36
+ @record = record
37
+ @parent = parent
38
+ @top = top
39
+ @canvas_builder_factory = canvas_builder_factory
40
+ @iiif_range_factory = iiif_range_factory
41
+ build_range
42
+ end
43
+
44
+ def path
45
+ "#{parent.manifest_url}/range/r#{index}"
46
+ end
47
+
48
+ def index
49
+ @index ||= SecureRandom.uuid
50
+ end
51
+
52
+ def apply(manifest)
53
+ manifest << range
54
+ sub_ranges.map do |sub_range|
55
+ manifest = sub_range.apply(manifest)
56
+ end
57
+ manifest
58
+ end
59
+
60
+ def build_range
61
+ range['@id'] = path
62
+ range['label'] = record.label
63
+ range['viewingHint'] = 'top' if top?
64
+ range['ranges'] = sub_ranges.map(&:path)
65
+ range['canvases'] = canvas_builders.map(&:path)
66
+ end
67
+
68
+ def sub_ranges
69
+ @sub_ranges ||= record.ranges.map do |sub_range|
70
+ RangeBuilder.new(
71
+ sub_range,
72
+ parent,
73
+ canvas_builder_factory: canvas_builder_factory,
74
+ iiif_range_factory: iiif_range_factory
75
+ )
76
+ end
77
+ end
78
+
79
+ def canvas_builders
80
+ @canvas_builders ||= file_set_presenters.map do |file_set_presenter|
81
+ canvas_builder_factory.new(file_set_presenter, parent)
82
+ end
83
+ end
84
+
85
+ def range
86
+ @range ||= iiif_range_factory.new
87
+ end
88
+
89
+ def top?
90
+ @top
91
+ end
92
+ end
93
+ end
94
+ end
@@ -9,6 +9,7 @@ require_relative 'manifest_builder/image_service_builder'
9
9
  require_relative 'manifest_builder/record_property_builder'
10
10
  require_relative 'manifest_builder/resource_builder'
11
11
  require_relative 'manifest_builder/sequence_builder'
12
+ require_relative 'manifest_builder/structure_builder'
12
13
 
13
14
  module IIIFManifest
14
15
  class ManifestBuilder
@@ -22,8 +23,8 @@ module IIIFManifest
22
23
  end
23
24
 
24
25
  def apply(collection)
25
- collection["manifests"] ||= []
26
- collection["manifests"] << to_h
26
+ collection['manifests'] ||= []
27
+ collection['manifests'] << to_h
27
28
  collection
28
29
  end
29
30
 
@@ -33,12 +34,12 @@ module IIIFManifest
33
34
 
34
35
  private
35
36
 
36
- def manifest
37
- @manifest ||= manifest_builder_class
38
- end
37
+ def manifest
38
+ @manifest ||= manifest_builder_class
39
+ end
39
40
 
40
- def top_record
41
- top_record_factory.new
42
- end
41
+ def top_record
42
+ top_record_factory.new
43
+ end
43
44
  end
44
45
  end
File without changes
@@ -39,6 +39,7 @@ module IIIFManifest
39
39
  composite_builder_factory.new(
40
40
  record_property_builder,
41
41
  sequence_builder,
42
+ structure_builder,
42
43
  composite_builder: composite_builder
43
44
  )
44
45
  end
@@ -82,20 +83,34 @@ module IIIFManifest
82
83
  ManifestBuilder::RecordPropertyBuilder
83
84
  end
84
85
 
86
+ def structure_builder
87
+ InjectedFactory.new(
88
+ ManifestBuilder::StructureBuilder,
89
+ canvas_builder_factory: canvas_builder,
90
+ iiif_range_factory: iiif_range_factory
91
+ )
92
+ end
93
+
85
94
  def sequence_builder
86
95
  InjectedFactory.new(
87
96
  ManifestBuilder::SequenceBuilder,
88
- canvas_builder_factory: canvas_builder_factory
97
+ canvas_builder_factory: canvas_builder_factory,
98
+ sequence_factory: sequence_factory
89
99
  )
90
100
  end
91
101
 
92
102
  def sammelband_sequence_builder
93
103
  InjectedFactory.new(
94
104
  ManifestBuilder::SequenceBuilder,
95
- canvas_builder_factory: deep_canvas_builder_factory
105
+ canvas_builder_factory: deep_canvas_builder_factory,
106
+ sequence_factory: sequence_factory
96
107
  )
97
108
  end
98
109
 
110
+ def sequence_factory
111
+ IIIF::Presentation::Sequence
112
+ end
113
+
99
114
  def canvas_builder_factory
100
115
  ManifestBuilder::CanvasBuilderFactory.new(
101
116
  composite_builder: composite_builder,
@@ -111,12 +126,59 @@ module IIIFManifest
111
126
  end
112
127
 
113
128
  def canvas_builder
114
- ManifestBuilder::CanvasBuilder
129
+ InjectedFactory.new(
130
+ ManifestBuilder::CanvasBuilder,
131
+ iiif_canvas_factory: iiif_canvas_factory,
132
+ image_builder: image_builder
133
+ )
134
+ end
135
+
136
+ def image_builder
137
+ InjectedFactory.new(
138
+ ManifestBuilder::ImageBuilder,
139
+ iiif_annotation_factory: iiif_annotation_factory,
140
+ resource_builder_factory: resource_builder_factory
141
+ )
142
+ end
143
+
144
+ def resource_builder_factory
145
+ InjectedFactory.new(
146
+ ManifestBuilder::ResourceBuilder,
147
+ iiif_resource_factory: iiif_resource_factory,
148
+ image_service_builder_factory: image_service_builder_factory
149
+ )
150
+ end
151
+
152
+ def image_service_builder_factory
153
+ InjectedFactory.new(
154
+ ManifestBuilder::ImageServiceBuilder,
155
+ iiif_service_factory: iiif_service_factory
156
+ )
157
+ end
158
+
159
+ def iiif_service_factory
160
+ IIIF::Service
161
+ end
162
+
163
+ def iiif_resource_factory
164
+ IIIF::Presentation::Resource
165
+ end
166
+
167
+ def iiif_annotation_factory
168
+ IIIF::Presentation::Annotation
115
169
  end
116
170
 
117
171
  def iiif_manifest_factory
118
172
  IIIF::Presentation::Manifest
119
173
  end
174
+
175
+ def iiif_canvas_factory
176
+ IIIF::Presentation::Canvas
177
+ end
178
+
179
+ def iiif_range_factory
180
+ IIIF::Presentation::Range
181
+ end
120
182
  end
121
183
 
122
184
  class InjectedFactory
@@ -1,3 +1,3 @@
1
1
  module IIIFManifest
2
- VERSION = "0.2.0"
2
+ VERSION = '0.3.0'.freeze
3
3
  end
data/lib/iiif_manifest.rb CHANGED
@@ -1,4 +1,4 @@
1
- require "iiif_manifest/version"
1
+ require 'iiif_manifest/version'
2
2
  require 'active_support'
3
3
  require 'active_support/core_ext/module'
4
4
  require 'active_support/core_ext/object'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: iiif_manifest
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Justin Coyne
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: exe
11
11
  cert_chain: []
12
- date: 2017-05-03 00:00:00.000000000 Z
12
+ date: 2017-10-02 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activesupport
@@ -81,6 +81,48 @@ dependencies:
81
81
  - - "~>"
82
82
  - !ruby/object:Gem::Version
83
83
  version: '3.0'
84
+ - !ruby/object:Gem::Dependency
85
+ name: rubocop
86
+ requirement: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - ">="
89
+ - !ruby/object:Gem::Version
90
+ version: '0'
91
+ type: :development
92
+ prerelease: false
93
+ version_requirements: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - ">="
96
+ - !ruby/object:Gem::Version
97
+ version: '0'
98
+ - !ruby/object:Gem::Dependency
99
+ name: rubocop-rspec
100
+ requirement: !ruby/object:Gem::Requirement
101
+ requirements:
102
+ - - ">="
103
+ - !ruby/object:Gem::Version
104
+ version: '0'
105
+ type: :development
106
+ prerelease: false
107
+ version_requirements: !ruby/object:Gem::Requirement
108
+ requirements:
109
+ - - ">="
110
+ - !ruby/object:Gem::Version
111
+ version: '0'
112
+ - !ruby/object:Gem::Dependency
113
+ name: pry-byebug
114
+ requirement: !ruby/object:Gem::Requirement
115
+ requirements:
116
+ - - ">="
117
+ - !ruby/object:Gem::Version
118
+ version: '0'
119
+ type: :development
120
+ prerelease: false
121
+ version_requirements: !ruby/object:Gem::Requirement
122
+ requirements:
123
+ - - ">="
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
84
126
  description: IIIF http://iiif.io/ defines an API for presenting related images in
85
127
  a viewer. This transforms Hydra::Works objects into that format usable by players
86
128
  such as http://universalviewer.io/
@@ -92,6 +134,8 @@ extra_rdoc_files: []
92
134
  files:
93
135
  - ".gitignore"
94
136
  - ".rspec"
137
+ - ".rubocop.yml"
138
+ - ".rubocop_todo.yml"
95
139
  - ".travis.yml"
96
140
  - CODE_OF_CONDUCT.md
97
141
  - Gemfile
@@ -117,6 +161,7 @@ files:
117
161
  - lib/iiif_manifest/manifest_builder/record_property_builder.rb
118
162
  - lib/iiif_manifest/manifest_builder/resource_builder.rb
119
163
  - lib/iiif_manifest/manifest_builder/sequence_builder.rb
164
+ - lib/iiif_manifest/manifest_builder/structure_builder.rb
120
165
  - lib/iiif_manifest/manifest_factory.rb
121
166
  - lib/iiif_manifest/manifest_service_locator.rb
122
167
  - lib/iiif_manifest/version.rb
@@ -139,7 +184,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
139
184
  version: '0'
140
185
  requirements: []
141
186
  rubyforge_project:
142
- rubygems_version: 2.6.12
187
+ rubygems_version: 2.6.13
143
188
  signing_key:
144
189
  specification_version: 4
145
190
  summary: Generate IIIF presentation manifests for Hydra::Works