iiif_manifest 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (33) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +9 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +4 -0
  5. data/CODE_OF_CONDUCT.md +49 -0
  6. data/Gemfile +7 -0
  7. data/LICENSE +14 -0
  8. data/README.md +83 -0
  9. data/Rakefile +6 -0
  10. data/bin/console +14 -0
  11. data/bin/setup +8 -0
  12. data/iiif_manifest.gemspec +27 -0
  13. data/lib/iiif_manifest.rb +16 -0
  14. data/lib/iiif_manifest/display_image.rb +12 -0
  15. data/lib/iiif_manifest/iiif_collection.rb +5 -0
  16. data/lib/iiif_manifest/iiif_endpoint.rb +13 -0
  17. data/lib/iiif_manifest/manifest_builder.rb +44 -0
  18. data/lib/iiif_manifest/manifest_builder/canvas_builder.rb +43 -0
  19. data/lib/iiif_manifest/manifest_builder/canvas_builder_factory.rb +25 -0
  20. data/lib/iiif_manifest/manifest_builder/child_manifest_builder_factory.rb +19 -0
  21. data/lib/iiif_manifest/manifest_builder/composite_builder.rb +24 -0
  22. data/lib/iiif_manifest/manifest_builder/composite_builder_factory.rb +18 -0
  23. data/lib/iiif_manifest/manifest_builder/deep_canvas_builder_factory.rb +38 -0
  24. data/lib/iiif_manifest/manifest_builder/image_builder.rb +32 -0
  25. data/lib/iiif_manifest/manifest_builder/image_service_builder.rb +23 -0
  26. data/lib/iiif_manifest/manifest_builder/record_property_builder.rb +33 -0
  27. data/lib/iiif_manifest/manifest_builder/resource_builder.rb +34 -0
  28. data/lib/iiif_manifest/manifest_builder/sequence_builder.rb +37 -0
  29. data/lib/iiif_manifest/manifest_factory.rb +30 -0
  30. data/lib/iiif_manifest/manifest_helper.rb +15 -0
  31. data/lib/iiif_manifest/manifest_service_locator.rb +134 -0
  32. data/lib/iiif_manifest/version.rb +3 -0
  33. metadata +148 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 7834ae5d9816298acd646b85bf5b3dd6e0234fd3
4
+ data.tar.gz: 23e163a7b4efe629053446e25a4075516657684c
5
+ SHA512:
6
+ metadata.gz: a3efecb2810c8730825302400b3a72e124d79c11ca3d4b92dfc17fd17b95a707cd7ef5677116dba410beffa22d500e122a5ffda00083f45ee4905db02bf095e4
7
+ data.tar.gz: 276192084e9ec82c1dd0a29c75e140fc5cc1e20c22df8a8cdcb2beb2e1ff91773f964dfed4115b848550c155410eeb206e66e4019fbcda44f50f3c6f48967763
data/.gitignore ADDED
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
data/.travis.yml ADDED
@@ -0,0 +1,4 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.3.0
4
+ before_install: gem install bundler -v 1.11.2
@@ -0,0 +1,49 @@
1
+ # Contributor Code of Conduct
2
+
3
+ As contributors and maintainers of this project, and in the interest of
4
+ fostering an open and welcoming community, we pledge to respect all people who
5
+ contribute through reporting issues, posting feature requests, updating
6
+ documentation, submitting pull requests or patches, and other activities.
7
+
8
+ We are committed to making participation in this project a harassment-free
9
+ experience for everyone, regardless of level of experience, gender, gender
10
+ identity and expression, sexual orientation, disability, personal appearance,
11
+ body size, race, ethnicity, age, religion, or nationality.
12
+
13
+ Examples of unacceptable behavior by participants include:
14
+
15
+ * The use of sexualized language or imagery
16
+ * Personal attacks
17
+ * Trolling or insulting/derogatory comments
18
+ * Public or private harassment
19
+ * Publishing other's private information, such as physical or electronic
20
+ addresses, without explicit permission
21
+ * Other unethical or unprofessional conduct
22
+
23
+ Project maintainers have the right and responsibility to remove, edit, or
24
+ reject comments, commits, code, wiki edits, issues, and other contributions
25
+ that are not aligned to this Code of Conduct, or to ban temporarily or
26
+ permanently any contributor for other behaviors that they deem inappropriate,
27
+ threatening, offensive, or harmful.
28
+
29
+ By adopting this Code of Conduct, project maintainers commit themselves to
30
+ fairly and consistently applying these principles to every aspect of managing
31
+ this project. Project maintainers who do not follow or enforce the Code of
32
+ Conduct may be permanently removed from the project team.
33
+
34
+ This code of conduct applies both within project spaces and in public spaces
35
+ when an individual is representing the project or its community.
36
+
37
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be
38
+ reported by contacting a project maintainer at jcoyne@justincoyne.com. All
39
+ complaints will be reviewed and investigated and will result in a response that
40
+ is deemed necessary and appropriate to the circumstances. Maintainers are
41
+ obligated to maintain confidentiality with regard to the reporter of an
42
+ incident.
43
+
44
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage],
45
+ version 1.3.0, available at
46
+ [http://contributor-covenant.org/version/1/3/0/][version]
47
+
48
+ [homepage]: http://contributor-covenant.org
49
+ [version]: http://contributor-covenant.org/version/1/3/0/
data/Gemfile ADDED
@@ -0,0 +1,7 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in iiif_manifest.gemspec
4
+ gemspec
5
+
6
+ gem 'iiif-presentation', github: 'iiif/osullivan'
7
+
data/LICENSE ADDED
@@ -0,0 +1,14 @@
1
+ Copyright 2016 The Board of Trustees of the Leland Stanford Junior University.
2
+ Additional copyright may be held by others, as reflected in the commit history.
3
+
4
+ Licensed under the Apache License, Version 2.0 (the "License");
5
+ you may not use this file except in compliance with the License.
6
+ You may obtain a copy of the License at
7
+
8
+ http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+ Unless required by applicable law or agreed to in writing, software
11
+ distributed under the License is distributed on an "AS IS" BASIS,
12
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ See the License for the specific language governing permissions and
14
+ limitations under the License.
data/README.md ADDED
@@ -0,0 +1,83 @@
1
+ # IIIFManifest
2
+ [![Build Status](https://travis-ci.org/projecthydra-labs/iiif_manifest.svg?branch=master)](https://travis-ci.org/projecthydra-labs/iiif_manifest)
3
+
4
+ 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/
5
+
6
+ ## Usage
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.
9
+
10
+ For example:
11
+
12
+ ```ruby
13
+ class Book
14
+ def initialize(id, pages = [])
15
+ @id = id
16
+ @pages = pages
17
+ end
18
+
19
+ def file_set_presenters
20
+ @pages
21
+ end
22
+
23
+ def work_presenters
24
+ []
25
+ end
26
+
27
+ def manifest_url
28
+ "http://test.host/books/#{@id}/manifest"
29
+ end
30
+
31
+ def description
32
+ 'a brief description'
33
+ end
34
+ end
35
+ ```
36
+
37
+ The class that represents the leaf nodes, must implement `#id`. It must also implement `#display_image` which returns an instance of `IIIFManifest::DisplayImage`
38
+
39
+ ```ruby
40
+ class Page
41
+ def initialize(id)
42
+ @id = id
43
+ end
44
+
45
+ def id
46
+ @id
47
+ end
48
+
49
+ def display_image
50
+ IIIFManifest::DisplayImage.new(id,
51
+ width: 100,
52
+ height: 100,
53
+ format: "image/jpeg",
54
+ iiif_endpoint: endpoint
55
+ )
56
+ end
57
+
58
+ private
59
+
60
+ def endpoint
61
+ IIIFManifest::IIIFEndpoint.new("http://test.host/images/#{id}",
62
+ profile: "http://iiif.io/api/image/2/level2.json")
63
+ end
64
+ end
65
+ ```
66
+
67
+ Then you can produce the manifest on the book object like this:
68
+
69
+ ```ruby
70
+ book = Book.new('book-77',[Page.new('page-99')])
71
+ IIIFManifest::ManifestFactory.new(book).to_h.to_json
72
+ ```
73
+
74
+ ## Development
75
+
76
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
77
+
78
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
79
+
80
+ ## Contributing
81
+
82
+ Bug reports and pull requests are welcome on GitHub at https://github.com/projecthydra-labs/iiif_manifest. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
83
+
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "iiif_manifest"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,27 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'iiif_manifest/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "iiif_manifest"
8
+ spec.version = IIIFManifest::VERSION
9
+ spec.authors = ["Justin Coyne", "Trey Pendragon"]
10
+ spec.email = ["jcoyne@justincoyne.com"]
11
+
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"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
17
+ spec.bindir = "exe"
18
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_dependency "activesupport", ">= 4"
22
+ spec.add_dependency "iiif-presentation"
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"
27
+ end
@@ -0,0 +1,16 @@
1
+ require "iiif_manifest/version"
2
+ require 'active_support'
3
+ require 'active_support/core_ext/module'
4
+ require 'active_support/core_ext/object'
5
+ require 'iiif/presentation' # AKA O'Sullivan
6
+
7
+ module IIIFManifest
8
+ extend ActiveSupport::Autoload
9
+ autoload :ManifestBuilder
10
+ autoload :ManifestFactory
11
+ autoload :ManifestServiceLocator
12
+ autoload :ManifestHelper
13
+ autoload :DisplayImage
14
+ autoload :IIIFCollection
15
+ autoload :IIIFEndpoint
16
+ end
@@ -0,0 +1,12 @@
1
+ module IIIFManifest
2
+ class DisplayImage
3
+ attr_reader :url, :width, :height, :iiif_endpoint, :format
4
+ def initialize(url, width:, height:, format: nil, iiif_endpoint: nil)
5
+ @url = url
6
+ @width = width
7
+ @height = height
8
+ @format = format
9
+ @iiif_endpoint = iiif_endpoint
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,5 @@
1
+ class IIIFCollection < SimpleDelegator
2
+ def viewing_hint
3
+ 'multi-part'
4
+ end
5
+ end
@@ -0,0 +1,13 @@
1
+ module IIIFManifest
2
+ class IIIFEndpoint
3
+ attr_reader :url, :profile
4
+ def initialize(url, profile: nil)
5
+ @url = url
6
+ @profile = profile
7
+ end
8
+
9
+ def context
10
+ "http://iiif.io/api/image/2/context.json"
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,44 @@
1
+ require_relative 'manifest_builder/canvas_builder'
2
+ require_relative 'manifest_builder/canvas_builder_factory'
3
+ require_relative 'manifest_builder/child_manifest_builder_factory'
4
+ require_relative 'manifest_builder/composite_builder'
5
+ require_relative 'manifest_builder/composite_builder_factory'
6
+ require_relative 'manifest_builder/deep_canvas_builder_factory'
7
+ require_relative 'manifest_builder/image_builder'
8
+ require_relative 'manifest_builder/image_service_builder'
9
+ require_relative 'manifest_builder/record_property_builder'
10
+ require_relative 'manifest_builder/resource_builder'
11
+ require_relative 'manifest_builder/sequence_builder'
12
+
13
+ module IIIFManifest
14
+ class ManifestBuilder
15
+ attr_reader :work,
16
+ :builders,
17
+ :top_record_factory
18
+ def initialize(work, builders:, top_record_factory:)
19
+ @work = work
20
+ @builders = builders
21
+ @top_record_factory = top_record_factory
22
+ end
23
+
24
+ def apply(collection)
25
+ collection["manifests"] ||= []
26
+ collection["manifests"] << to_h
27
+ collection
28
+ end
29
+
30
+ def to_h
31
+ @to_h ||= builders.new(work).apply(top_record)
32
+ end
33
+
34
+ private
35
+
36
+ def manifest
37
+ @manifest ||= manifest_builder_class
38
+ end
39
+
40
+ def top_record
41
+ top_record_factory.new
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,43 @@
1
+ module IIIFManifest
2
+ class ManifestBuilder
3
+ class CanvasBuilder
4
+ attr_reader :record, :parent
5
+
6
+ def initialize(record, parent)
7
+ @record = record
8
+ @parent = parent
9
+ apply_record_properties
10
+ attach_image if display_image
11
+ end
12
+
13
+ def canvas
14
+ @canvas ||= IIIF::Presentation::Canvas.new
15
+ end
16
+
17
+ def path
18
+ "#{parent.manifest_url}/canvas/#{record.id}"
19
+ end
20
+
21
+ def apply(sequence)
22
+ return sequence if canvas.images.blank?
23
+ sequence.canvases += [canvas]
24
+ sequence
25
+ end
26
+
27
+ private
28
+
29
+ def display_image
30
+ record.display_image if record.respond_to?(:display_image)
31
+ end
32
+
33
+ def apply_record_properties
34
+ canvas['@id'] = path
35
+ canvas.label = record.to_s
36
+ end
37
+
38
+ def attach_image
39
+ ImageBuilder.new(display_image).apply(canvas)
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,25 @@
1
+ module IIIFManifest
2
+ class ManifestBuilder
3
+ class CanvasBuilderFactory
4
+ attr_reader :composite_builder, :canvas_builder_factory
5
+ def initialize(composite_builder:, canvas_builder_factory:)
6
+ @composite_builder = composite_builder
7
+ @canvas_builder_factory = canvas_builder_factory
8
+ end
9
+
10
+ def from(work)
11
+ composite_builder.new(
12
+ *file_set_presenters(work).map do |presenter|
13
+ canvas_builder_factory.new(presenter, work)
14
+ end
15
+ )
16
+ end
17
+
18
+ private
19
+
20
+ def file_set_presenters(work)
21
+ work.file_set_presenters
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,19 @@
1
+ module IIIFManifest
2
+ class ManifestBuilder
3
+ class ChildManifestBuilderFactory
4
+ attr_reader :child_manifest_builder, :composite_builder
5
+ def initialize(child_manifest_builder:, composite_builder:)
6
+ @child_manifest_builder = child_manifest_builder
7
+ @composite_builder = composite_builder
8
+ end
9
+
10
+ def new(work)
11
+ composite_builder.new(
12
+ *work.work_presenters.map do |work_presenter|
13
+ child_manifest_builder.new(work_presenter)
14
+ end
15
+ )
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,24 @@
1
+ module IIIFManifest
2
+ class ManifestBuilder
3
+ class CompositeBuilder
4
+ attr_reader :services
5
+ delegate :length, to: :services
6
+ def initialize(*services)
7
+ @services = services.compact
8
+ end
9
+
10
+ def apply(manifest)
11
+ services.each do |service|
12
+ manifest = service.apply(manifest)
13
+ end
14
+ manifest
15
+ end
16
+
17
+ def method_missing(meth_name, *args, &block)
18
+ services.map do |service|
19
+ service.__send__(meth_name, *args, &block)
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,18 @@
1
+ module IIIFManifest
2
+ class ManifestBuilder
3
+ class CompositeBuilderFactory
4
+ attr_reader :factories, :composite_builder
5
+ def initialize(*factories, composite_builder:)
6
+ @factories = factories
7
+ @composite_builder = composite_builder
8
+ end
9
+
10
+ def new(*args)
11
+ result = factories.map do |factory|
12
+ factory.new(*args)
13
+ end
14
+ composite_builder.new(*result)
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,38 @@
1
+ module IIIFManifest
2
+ class ManifestBuilder
3
+ class DeepCanvasBuilderFactory < CanvasBuilderFactory
4
+ private
5
+
6
+ def file_set_presenters(work)
7
+ DeepFileSetEnumerator.new(work).to_a
8
+ end
9
+ end
10
+
11
+ class DeepFileSetEnumerator
12
+ attr_reader :work
13
+ include Enumerable
14
+ def initialize(work)
15
+ @work = work
16
+ end
17
+
18
+ def each(&block)
19
+ file_set_presenters.each do |file_set_presenter|
20
+ yield file_set_presenter
21
+ end
22
+ work_presenters.each do |work_presenter|
23
+ self.class.new(work_presenter).each(&block)
24
+ end
25
+ end
26
+
27
+ private
28
+
29
+ def file_set_presenters
30
+ work.try(:file_set_presenters) || []
31
+ end
32
+
33
+ def work_presenters
34
+ work.try(:work_presenters) || []
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,32 @@
1
+ module IIIFManifest
2
+ class ManifestBuilder
3
+ class ImageBuilder
4
+ attr_reader :display_image
5
+ def initialize(display_image)
6
+ @display_image = display_image
7
+ build_resource
8
+ end
9
+
10
+ def apply(canvas)
11
+ annotation['on'] = canvas['@id']
12
+ canvas['width'] = annotation.resource['width']
13
+ canvas['height'] = annotation.resource['height']
14
+ canvas.images << annotation
15
+ end
16
+
17
+ private
18
+
19
+ def build_resource
20
+ resource_builder.apply(annotation)
21
+ end
22
+
23
+ def resource_builder
24
+ ResourceBuilder.new(display_image)
25
+ end
26
+
27
+ def annotation
28
+ @annotation ||= IIIF::Presentation::Annotation.new
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,23 @@
1
+ module IIIFManifest
2
+ class ManifestBuilder
3
+ class ImageServiceBuilder
4
+ attr_reader :iiif_endpoint
5
+ def initialize(iiif_endpoint)
6
+ @iiif_endpoint = iiif_endpoint
7
+ end
8
+
9
+ def apply(resource)
10
+ service['@context'] = iiif_endpoint.context
11
+ service['@id'] = iiif_endpoint.url
12
+ service['profile'] = iiif_endpoint.profile
13
+ resource.service = service
14
+ end
15
+
16
+ private
17
+
18
+ def service
19
+ @service ||= IIIF::Service.new
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,33 @@
1
+ module IIIFManifest
2
+ class ManifestBuilder
3
+ class RecordPropertyBuilder
4
+ attr_reader :record, :path
5
+ def initialize(record)
6
+ @record = record
7
+ end
8
+
9
+ def apply(manifest)
10
+ manifest['@id'] = record.manifest_url.to_s
11
+ manifest.label = record.to_s
12
+ manifest.description = record.description
13
+ manifest.viewing_hint = viewing_hint
14
+ manifest
15
+ # manifest.try(:viewing_direction=, viewing_direction)
16
+ end
17
+
18
+ private
19
+
20
+ def viewing_hint
21
+ (record.respond_to?(:viewing_hint) && record.send(:viewing_hint)) || 'individuals'
22
+ end
23
+
24
+ # def viewing_direction
25
+ # record.try(:viewing_direction) || "left-to-right"
26
+ # end
27
+ #
28
+ # def viewing_hint
29
+ # record.viewing_hint || "individuals"
30
+ # end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,34 @@
1
+ module IIIFManifest
2
+ class ManifestBuilder
3
+ class ResourceBuilder
4
+ attr_reader :display_image
5
+ def initialize(display_image)
6
+ @display_image = display_image
7
+ end
8
+
9
+ def apply(annotation)
10
+ resource['@id'] = display_image.url
11
+ resource['@type'] = 'dctypes:Image'
12
+ resource['height'] = display_image.height
13
+ resource['width'] = display_image.width
14
+ resource['format'] = display_image.format
15
+ image_service_builder.apply(resource) if iiif_endpoint
16
+ annotation.resource = resource
17
+ end
18
+
19
+ private
20
+
21
+ def resource
22
+ @resource ||= IIIF::Presentation::Resource.new
23
+ end
24
+
25
+ def iiif_endpoint
26
+ display_image.try(:iiif_endpoint)
27
+ end
28
+
29
+ def image_service_builder
30
+ ImageServiceBuilder.new(iiif_endpoint)
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,37 @@
1
+ module IIIFManifest
2
+ class ManifestBuilder
3
+ class SequenceBuilder
4
+ attr_reader :work, :canvas_builder_factory
5
+ def initialize(work, canvas_builder_factory:)
6
+ @work = work
7
+ @canvas_builder_factory = canvas_builder_factory
8
+ end
9
+
10
+ def apply(manifest)
11
+ # sequence.viewing_hint = manifest.viewing_hint
12
+ manifest.sequences += [sequence] unless empty?
13
+ manifest
14
+ end
15
+
16
+ def empty?
17
+ sequence.canvases.empty?
18
+ end
19
+
20
+ private
21
+
22
+ def canvas_builder
23
+ canvas_builder_factory.from(work)
24
+ end
25
+
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
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,30 @@
1
+ module IIIFManifest
2
+ class ManifestFactory
3
+ class << self
4
+ def new(work, manifest_service_locator: ManifestServiceLocator)
5
+ super(manifest_service_locator).new(work)
6
+ end
7
+ end
8
+
9
+ delegate :collection_manifest_builder, :manifest_builder, :sammelband_manifest_builder,
10
+ to: :manifest_service_locator
11
+ attr_reader :manifest_service_locator
12
+
13
+ def initialize(manifest_service_locator)
14
+ @manifest_service_locator = manifest_service_locator
15
+ end
16
+
17
+ def new(work)
18
+ if !work.work_presenters.empty?
19
+ if work.file_set_presenters.empty?
20
+ work = IIIFCollection.new(work)
21
+ collection_manifest_builder.new(work)
22
+ elsif !work.file_set_presenters.empty?
23
+ sammelband_manifest_builder.new(work)
24
+ end
25
+ else
26
+ manifest_builder.new(work)
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,15 @@
1
+ module IIIFManifest
2
+ class ManifestHelper
3
+ include Rails.application.routes.url_helpers
4
+ include ActionDispatch::Routing::PolymorphicRoutes
5
+
6
+ def polymorphic_url(record, opts = {})
7
+ opts[:host] ||= host
8
+ super(record, opts)
9
+ end
10
+
11
+ def host
12
+ Rails.application.config.action_mailer.default_url_options[:host]
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,134 @@
1
+ module IIIFManifest
2
+ class ManifestServiceLocator
3
+ class << self
4
+ def collection_manifest_builder
5
+ InjectedFactory.new(
6
+ ManifestBuilder,
7
+ builders: collection_manifest_builders,
8
+ top_record_factory: iiif_collection_factory
9
+ )
10
+ end
11
+
12
+ def manifest_builder
13
+ InjectedFactory.new(
14
+ ManifestBuilder,
15
+ builders: manifest_builders,
16
+ top_record_factory: iiif_manifest_factory
17
+ )
18
+ end
19
+
20
+ def child_manifest_builder
21
+ InjectedFactory.new(
22
+ ManifestBuilder,
23
+ builders: record_property_builder,
24
+ top_record_factory: iiif_manifest_factory
25
+ )
26
+ end
27
+
28
+ def sammelband_manifest_builder
29
+ InjectedFactory.new(
30
+ ManifestBuilder,
31
+ builders: sammelband_manifest_builders,
32
+ top_record_factory: iiif_manifest_factory
33
+ )
34
+ end
35
+
36
+ # Builders which receive a work as an argument to .new and return objects
37
+ # that respond to #apply.
38
+ def manifest_builders
39
+ composite_builder_factory.new(
40
+ record_property_builder,
41
+ sequence_builder,
42
+ composite_builder: composite_builder
43
+ )
44
+ end
45
+
46
+ def sammelband_manifest_builders
47
+ composite_builder_factory.new(
48
+ record_property_builder,
49
+ sammelband_sequence_builder,
50
+ composite_builder: composite_builder
51
+ )
52
+ end
53
+
54
+ def collection_manifest_builders
55
+ composite_builder_factory.new(
56
+ record_property_builder,
57
+ child_manifest_builder_factory,
58
+ composite_builder: composite_builder
59
+ )
60
+ end
61
+
62
+ def child_manifest_builder_factory
63
+ ManifestBuilder::ChildManifestBuilderFactory.new(
64
+ composite_builder: composite_builder,
65
+ child_manifest_builder: child_manifest_builder
66
+ )
67
+ end
68
+
69
+ def iiif_collection_factory
70
+ IIIF::Presentation::Collection
71
+ end
72
+
73
+ def composite_builder
74
+ ManifestBuilder::CompositeBuilder
75
+ end
76
+
77
+ def composite_builder_factory
78
+ ManifestBuilder::CompositeBuilderFactory
79
+ end
80
+
81
+ def record_property_builder
82
+ ManifestBuilder::RecordPropertyBuilder
83
+ end
84
+
85
+ def sequence_builder
86
+ InjectedFactory.new(
87
+ ManifestBuilder::SequenceBuilder,
88
+ canvas_builder_factory: canvas_builder_factory
89
+ )
90
+ end
91
+
92
+ def sammelband_sequence_builder
93
+ InjectedFactory.new(
94
+ ManifestBuilder::SequenceBuilder,
95
+ canvas_builder_factory: deep_canvas_builder_factory
96
+ )
97
+ end
98
+
99
+ def canvas_builder_factory
100
+ ManifestBuilder::CanvasBuilderFactory.new(
101
+ composite_builder: composite_builder,
102
+ canvas_builder_factory: canvas_builder
103
+ )
104
+ end
105
+
106
+ def deep_canvas_builder_factory
107
+ ManifestBuilder::DeepCanvasBuilderFactory.new(
108
+ composite_builder: composite_builder,
109
+ canvas_builder_factory: canvas_builder
110
+ )
111
+ end
112
+
113
+ def canvas_builder
114
+ ManifestBuilder::CanvasBuilder
115
+ end
116
+
117
+ def iiif_manifest_factory
118
+ IIIF::Presentation::Manifest
119
+ end
120
+ end
121
+
122
+ class InjectedFactory
123
+ attr_reader :factory, :hash_args
124
+ def initialize(factory, hash_args)
125
+ @hash_args = hash_args
126
+ @factory = factory
127
+ end
128
+
129
+ def new(*args)
130
+ factory.new(*args, hash_args)
131
+ end
132
+ end
133
+ end
134
+ end
@@ -0,0 +1,3 @@
1
+ module IIIFManifest
2
+ VERSION = "0.1.0"
3
+ end
metadata ADDED
@@ -0,0 +1,148 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: iiif_manifest
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Justin Coyne
8
+ - Trey Pendragon
9
+ autorequire:
10
+ bindir: exe
11
+ cert_chain: []
12
+ date: 2016-05-13 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: activesupport
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - ">="
19
+ - !ruby/object:Gem::Version
20
+ version: '4'
21
+ type: :runtime
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ version: '4'
28
+ - !ruby/object:Gem::Dependency
29
+ name: iiif-presentation
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - ">="
33
+ - !ruby/object:Gem::Version
34
+ version: '0'
35
+ type: :runtime
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ version: '0'
42
+ - !ruby/object:Gem::Dependency
43
+ name: bundler
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - "~>"
47
+ - !ruby/object:Gem::Version
48
+ version: '1.11'
49
+ type: :development
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - "~>"
54
+ - !ruby/object:Gem::Version
55
+ version: '1.11'
56
+ - !ruby/object:Gem::Dependency
57
+ name: rake
58
+ requirement: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - "~>"
61
+ - !ruby/object:Gem::Version
62
+ version: '10.0'
63
+ type: :development
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - "~>"
68
+ - !ruby/object:Gem::Version
69
+ version: '10.0'
70
+ - !ruby/object:Gem::Dependency
71
+ name: rspec
72
+ requirement: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - "~>"
75
+ - !ruby/object:Gem::Version
76
+ version: '3.0'
77
+ type: :development
78
+ prerelease: false
79
+ version_requirements: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - "~>"
82
+ - !ruby/object:Gem::Version
83
+ version: '3.0'
84
+ description: IIIF http://iiif.io/ defines an API for presenting related images in
85
+ a viewer. This transforms Hydra::Works objects into that format usable by players
86
+ such as http://universalviewer.io/
87
+ email:
88
+ - jcoyne@justincoyne.com
89
+ executables: []
90
+ extensions: []
91
+ extra_rdoc_files: []
92
+ files:
93
+ - ".gitignore"
94
+ - ".rspec"
95
+ - ".travis.yml"
96
+ - CODE_OF_CONDUCT.md
97
+ - Gemfile
98
+ - LICENSE
99
+ - README.md
100
+ - Rakefile
101
+ - bin/console
102
+ - bin/setup
103
+ - iiif_manifest.gemspec
104
+ - lib/iiif_manifest.rb
105
+ - lib/iiif_manifest/display_image.rb
106
+ - lib/iiif_manifest/iiif_collection.rb
107
+ - lib/iiif_manifest/iiif_endpoint.rb
108
+ - lib/iiif_manifest/manifest_builder.rb
109
+ - lib/iiif_manifest/manifest_builder/canvas_builder.rb
110
+ - lib/iiif_manifest/manifest_builder/canvas_builder_factory.rb
111
+ - lib/iiif_manifest/manifest_builder/child_manifest_builder_factory.rb
112
+ - lib/iiif_manifest/manifest_builder/composite_builder.rb
113
+ - lib/iiif_manifest/manifest_builder/composite_builder_factory.rb
114
+ - lib/iiif_manifest/manifest_builder/deep_canvas_builder_factory.rb
115
+ - lib/iiif_manifest/manifest_builder/image_builder.rb
116
+ - lib/iiif_manifest/manifest_builder/image_service_builder.rb
117
+ - lib/iiif_manifest/manifest_builder/record_property_builder.rb
118
+ - lib/iiif_manifest/manifest_builder/resource_builder.rb
119
+ - lib/iiif_manifest/manifest_builder/sequence_builder.rb
120
+ - lib/iiif_manifest/manifest_factory.rb
121
+ - lib/iiif_manifest/manifest_helper.rb
122
+ - lib/iiif_manifest/manifest_service_locator.rb
123
+ - lib/iiif_manifest/version.rb
124
+ homepage: http://github.com/projecthydra-labs/iiif_manifest
125
+ licenses: []
126
+ metadata: {}
127
+ post_install_message:
128
+ rdoc_options: []
129
+ require_paths:
130
+ - lib
131
+ required_ruby_version: !ruby/object:Gem::Requirement
132
+ requirements:
133
+ - - ">="
134
+ - !ruby/object:Gem::Version
135
+ version: '0'
136
+ required_rubygems_version: !ruby/object:Gem::Requirement
137
+ requirements:
138
+ - - ">="
139
+ - !ruby/object:Gem::Version
140
+ version: '0'
141
+ requirements: []
142
+ rubyforge_project:
143
+ rubygems_version: 2.5.1
144
+ signing_key:
145
+ specification_version: 4
146
+ summary: Generate IIIF presentation manifests for Hydra::Works
147
+ test_files: []
148
+ has_rdoc: