iiif_manifest 0.3.0 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +4 -0
- data/.rubocop_todo.yml +1 -0
- data/README.md +11 -1
- data/iiif_manifest.gemspec +1 -2
- data/lib/iiif_manifest.rb +0 -1
- data/lib/iiif_manifest/manifest_builder.rb +1 -0
- data/lib/iiif_manifest/manifest_builder/iiif_service.rb +197 -0
- data/lib/iiif_manifest/manifest_builder/record_property_builder.rb +39 -2
- data/lib/iiif_manifest/manifest_factory.rb +9 -3
- data/lib/iiif_manifest/manifest_service_locator.rb +21 -9
- data/lib/iiif_manifest/version.rb +1 -1
- metadata +13 -26
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c9bfc627db90ac1d23556a85e962f89447195fb7
|
4
|
+
data.tar.gz: b59e46225bae67ddfc5e2460b3672d4be113e4b6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 64f3b567ca52687d5fd6fe889bc085ed8850b69a343220819a5296c5ecce3d7d1a1aa7de386ca5f2ef82a3aedbac0a3b078c19c280c1e22ba7fc42effbf1234c
|
7
|
+
data.tar.gz: f550acc4ad049b10514d2c68333db4256ee0ac6e79bc4d995a9024681824bda83ac060d7fbbb9697f01e33e5eae5900c0e429212ed178133d0d9fb2f659e35d4
|
data/.rubocop.yml
CHANGED
data/.rubocop_todo.yml
CHANGED
@@ -65,6 +65,7 @@ Style/Documentation:
|
|
65
65
|
- 'lib/iiif_manifest/manifest_factory.rb'
|
66
66
|
- 'lib/iiif_manifest/manifest_service_locator.rb'
|
67
67
|
- 'lib/iiif_manifest.rb'
|
68
|
+
- 'lib/iiif_manifest/manifest_builder/iiif_service.rb'
|
68
69
|
- 'spec/lib/iiif_manifest/manifest_factory_spec.rb'
|
69
70
|
|
70
71
|
# Offense count: 1
|
data/README.md
CHANGED
@@ -13,7 +13,9 @@ Additionally it ***should*** implement `#manifest_url` that shows where the mani
|
|
13
13
|
|
14
14
|
Additionally it ***should*** implement `#manifest_metadata` to provide an array containing hashes of metadata Label/Value pairs.
|
15
15
|
|
16
|
-
Additionally it ***may*** implement `#
|
16
|
+
Additionally it ***may*** implement `#search_service` to contain the url for an IIIF search api compliant search endpoint and `#autocomplete_service` to contain the url for an IIIF search api compliant autocomplete endpoint. Please note, the autocomplete service is embedded within the search service description so if an autocomplete_service is supplied without a search_service it will be ignored. The IIIF `profile` added to the service descriptions is version 0 as this is the version supported by the current version of Universal Viewer. Only include a search_service within the manifest if your application has impelmented an IIIF search service at the endpoint specified in the manifest.
|
17
|
+
|
18
|
+
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
19
|
|
18
20
|
Finally, It ***may*** implement `ranges`, which returns an array of objects which
|
19
21
|
represent a table of contents or similar structure, each of which responds to
|
@@ -50,6 +52,14 @@ For example:
|
|
50
52
|
{ "label" => "Creator", "value" => "Morrissey, Stephen Patrick" }
|
51
53
|
]
|
52
54
|
end
|
55
|
+
|
56
|
+
def search_service
|
57
|
+
"http://test.host/books/#{@id}/search"
|
58
|
+
end
|
59
|
+
|
60
|
+
def autocomplete_service
|
61
|
+
"http://test.host/books/#{@id}/autocomplete"
|
62
|
+
end
|
53
63
|
|
54
64
|
def sequence_rendering
|
55
65
|
[{"@id" => "http://test.host/file_set/id/download", "format" => "application/pdf", "label" => "Download"}]
|
data/iiif_manifest.gemspec
CHANGED
@@ -18,12 +18,11 @@ Gem::Specification.new do |spec|
|
|
18
18
|
spec.require_paths = ['lib']
|
19
19
|
|
20
20
|
spec.add_dependency 'activesupport', '>= 4'
|
21
|
-
spec.add_dependency 'iiif-presentation', '~> 0.2.0'
|
22
21
|
|
23
22
|
spec.add_development_dependency 'bundler', '~> 1.11'
|
23
|
+
spec.add_development_dependency 'pry-byebug'
|
24
24
|
spec.add_development_dependency 'rake', '~> 10.0'
|
25
25
|
spec.add_development_dependency 'rspec', '~> 3.0'
|
26
26
|
spec.add_development_dependency 'rubocop'
|
27
27
|
spec.add_development_dependency 'rubocop-rspec'
|
28
|
-
spec.add_development_dependency 'pry-byebug'
|
29
28
|
end
|
data/lib/iiif_manifest.rb
CHANGED
@@ -0,0 +1,197 @@
|
|
1
|
+
module IIIFManifest
|
2
|
+
class ManifestBuilder
|
3
|
+
class IIIFService
|
4
|
+
attr_reader :inner_hash
|
5
|
+
def initialize
|
6
|
+
@inner_hash = initial_attributes
|
7
|
+
end
|
8
|
+
|
9
|
+
delegate :[]=, :[], :as_json, :to_json, :has_key?, to: :inner_hash
|
10
|
+
|
11
|
+
def initial_attributes
|
12
|
+
{}
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
class IIIFManifest < IIIFService
|
17
|
+
def label
|
18
|
+
inner_hash['label']
|
19
|
+
end
|
20
|
+
|
21
|
+
def label=(label)
|
22
|
+
inner_hash['label'] = label
|
23
|
+
end
|
24
|
+
|
25
|
+
def description=(description)
|
26
|
+
return unless description.present?
|
27
|
+
inner_hash['description'] = description
|
28
|
+
end
|
29
|
+
|
30
|
+
def viewing_hint=(viewing_hint)
|
31
|
+
return unless viewing_hint.present?
|
32
|
+
inner_hash['viewingHint'] = viewing_hint
|
33
|
+
end
|
34
|
+
|
35
|
+
def viewing_direction=(viewing_direction)
|
36
|
+
return unless viewing_direction.present?
|
37
|
+
inner_hash['viewingDirection'] = viewing_direction
|
38
|
+
end
|
39
|
+
|
40
|
+
def viewingDirection
|
41
|
+
inner_hash['viewingDirection']
|
42
|
+
end
|
43
|
+
|
44
|
+
def sequences
|
45
|
+
inner_hash['sequences'] || []
|
46
|
+
end
|
47
|
+
|
48
|
+
def sequences=(sequences)
|
49
|
+
inner_hash['sequences'] = sequences
|
50
|
+
end
|
51
|
+
|
52
|
+
def metadata=(metadata)
|
53
|
+
inner_hash['metadata'] = metadata
|
54
|
+
end
|
55
|
+
|
56
|
+
def service
|
57
|
+
inner_hash['service'] || []
|
58
|
+
end
|
59
|
+
|
60
|
+
def service=(service)
|
61
|
+
inner_hash['service'] = service
|
62
|
+
end
|
63
|
+
|
64
|
+
def see_also=(see_also)
|
65
|
+
inner_hash['seeAlso'] = see_also
|
66
|
+
end
|
67
|
+
|
68
|
+
def license=(license)
|
69
|
+
inner_hash['license'] = license
|
70
|
+
end
|
71
|
+
|
72
|
+
def initial_attributes
|
73
|
+
{
|
74
|
+
'@context' => 'http://iiif.io/api/presentation/2/context.json',
|
75
|
+
'@type' => 'sc:Manifest'
|
76
|
+
}
|
77
|
+
end
|
78
|
+
|
79
|
+
class Collection < IIIFManifest
|
80
|
+
def initial_attributes
|
81
|
+
{
|
82
|
+
'@context' => 'http://iiif.io/api/presentation/2/context.json',
|
83
|
+
'@type' => 'sc:Collection'
|
84
|
+
}
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
class Sequence < IIIFService
|
89
|
+
def canvases
|
90
|
+
inner_hash['canvases'] || []
|
91
|
+
end
|
92
|
+
|
93
|
+
def canvases=(canvases)
|
94
|
+
inner_hash['canvases'] = canvases
|
95
|
+
end
|
96
|
+
|
97
|
+
def initial_attributes
|
98
|
+
{
|
99
|
+
'@type' => 'sc:Sequence'
|
100
|
+
}
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
class Canvas < IIIFService
|
105
|
+
def label=(label)
|
106
|
+
inner_hash['label'] = label
|
107
|
+
end
|
108
|
+
|
109
|
+
def images
|
110
|
+
inner_hash['images'] || []
|
111
|
+
end
|
112
|
+
|
113
|
+
def images=(images)
|
114
|
+
inner_hash['images'] = images
|
115
|
+
end
|
116
|
+
|
117
|
+
def initial_attributes
|
118
|
+
{
|
119
|
+
'@type' => 'sc:Canvas'
|
120
|
+
}
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
class Range < IIIFService
|
125
|
+
def initial_attributes
|
126
|
+
{
|
127
|
+
'@type' => 'sc:Range'
|
128
|
+
}
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
class Resource < IIIFService
|
133
|
+
def service=(service)
|
134
|
+
inner_hash['service'] = service
|
135
|
+
end
|
136
|
+
|
137
|
+
def initial_attributes
|
138
|
+
{
|
139
|
+
'@type' => 'sc:Range'
|
140
|
+
}
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
class Annotation < IIIFService
|
145
|
+
def resource=(resource)
|
146
|
+
inner_hash['resource'] = resource
|
147
|
+
end
|
148
|
+
|
149
|
+
def resource
|
150
|
+
inner_hash['resource']
|
151
|
+
end
|
152
|
+
|
153
|
+
def initial_attributes
|
154
|
+
{
|
155
|
+
'@type' => 'oa:Annotation',
|
156
|
+
'motivation' => 'sc:painting'
|
157
|
+
}
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
class SearchService < IIIFService
|
162
|
+
def service=(service)
|
163
|
+
inner_hash['service'] = service
|
164
|
+
end
|
165
|
+
|
166
|
+
def search_service=(search_service)
|
167
|
+
inner_hash['@id'] = search_service
|
168
|
+
end
|
169
|
+
|
170
|
+
def initial_attributes
|
171
|
+
{
|
172
|
+
'@context' => 'http://iiif.io/api/search/0/context.json',
|
173
|
+
'profile' => 'http://iiif.io/api/search/0/search',
|
174
|
+
'label' => 'Search within this manifest'
|
175
|
+
}
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
class AutocompleteService < IIIFService
|
180
|
+
def autocomplete_service
|
181
|
+
inner_hash['@id']
|
182
|
+
end
|
183
|
+
|
184
|
+
def autocomplete_service=(autocomplete_service)
|
185
|
+
inner_hash['@id'] = autocomplete_service
|
186
|
+
end
|
187
|
+
|
188
|
+
def initial_attributes
|
189
|
+
{
|
190
|
+
'profile' => 'http://iiif.io/api/search/0/autocomplete',
|
191
|
+
'label' => 'Get suggested words in this manifest'
|
192
|
+
}
|
193
|
+
end
|
194
|
+
end
|
195
|
+
end
|
196
|
+
end
|
197
|
+
end
|
@@ -1,19 +1,25 @@
|
|
1
1
|
module IIIFManifest
|
2
2
|
class ManifestBuilder
|
3
3
|
class RecordPropertyBuilder
|
4
|
-
attr_reader :record, :
|
5
|
-
def initialize(record)
|
4
|
+
attr_reader :record, :iiif_search_service_factory, :iiif_autocomplete_service_factory
|
5
|
+
def initialize(record, iiif_search_service_factory:, iiif_autocomplete_service_factory:)
|
6
6
|
@record = record
|
7
|
+
@iiif_search_service_factory = iiif_search_service_factory
|
8
|
+
@iiif_autocomplete_service_factory = iiif_autocomplete_service_factory
|
7
9
|
end
|
8
10
|
|
11
|
+
# rubocop:disable Metrics/AbcSize
|
9
12
|
def apply(manifest)
|
10
13
|
manifest['@id'] = record.manifest_url.to_s
|
11
14
|
manifest.label = record.to_s
|
12
15
|
manifest.description = record.description
|
13
16
|
manifest.viewing_hint = viewing_hint if viewing_hint.present?
|
17
|
+
manifest.viewing_direction = viewing_direction if viewing_direction.present?
|
14
18
|
manifest.metadata = record.manifest_metadata if valid_metadata?
|
19
|
+
manifest.service = services if search_service.present?
|
15
20
|
manifest
|
16
21
|
end
|
22
|
+
# rubocop:enable Metrics/AbcSize
|
17
23
|
|
18
24
|
private
|
19
25
|
|
@@ -21,6 +27,37 @@ module IIIFManifest
|
|
21
27
|
(record.respond_to?(:viewing_hint) && record.send(:viewing_hint))
|
22
28
|
end
|
23
29
|
|
30
|
+
def viewing_direction
|
31
|
+
(record.respond_to?(:viewing_direction) && record.send(:viewing_direction))
|
32
|
+
end
|
33
|
+
|
34
|
+
def autocomplete_service
|
35
|
+
(record.respond_to?(:autocomplete_service) && record.send(:autocomplete_service))
|
36
|
+
end
|
37
|
+
|
38
|
+
def search_service
|
39
|
+
(record.respond_to?(:search_service) && record.send(:search_service))
|
40
|
+
end
|
41
|
+
|
42
|
+
def iiif_search_service
|
43
|
+
@iiif_search_service ||= iiif_search_service_factory.new
|
44
|
+
end
|
45
|
+
|
46
|
+
def iiif_autocomplete_service
|
47
|
+
@iiif_autocomplete_service ||= iiif_autocomplete_service_factory.new
|
48
|
+
end
|
49
|
+
|
50
|
+
# Build services. Currently supported:
|
51
|
+
# search_service, with (optional) embedded autocomplete service
|
52
|
+
#
|
53
|
+
# @return [Array] array of services
|
54
|
+
def services
|
55
|
+
iiif_search_service.search_service = search_service
|
56
|
+
iiif_autocomplete_service.autocomplete_service = autocomplete_service
|
57
|
+
iiif_search_service.service = iiif_autocomplete_service if autocomplete_service.present?
|
58
|
+
[iiif_search_service]
|
59
|
+
end
|
60
|
+
|
24
61
|
# Validate manifest_metadata against the IIIF spec format for metadata
|
25
62
|
#
|
26
63
|
# @return [Boolean]
|
@@ -16,15 +16,21 @@ module IIIFManifest
|
|
16
16
|
|
17
17
|
def new(work)
|
18
18
|
if !work.work_presenters.empty?
|
19
|
-
if work.file_set_presenters.empty?
|
19
|
+
if sammelband?(work) || !work.file_set_presenters.empty?
|
20
|
+
sammelband_manifest_builder.new(work)
|
21
|
+
elsif work.file_set_presenters.empty?
|
20
22
|
work = IIIFCollection.new(work)
|
21
23
|
collection_manifest_builder.new(work)
|
22
|
-
elsif !work.file_set_presenters.empty?
|
23
|
-
sammelband_manifest_builder.new(work)
|
24
24
|
end
|
25
25
|
else
|
26
26
|
manifest_builder.new(work)
|
27
27
|
end
|
28
28
|
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def sammelband?(work)
|
33
|
+
work.respond_to?(:sammelband?) && work.sammelband?
|
34
|
+
end
|
29
35
|
end
|
30
36
|
end
|
@@ -68,7 +68,7 @@ module IIIFManifest
|
|
68
68
|
end
|
69
69
|
|
70
70
|
def iiif_collection_factory
|
71
|
-
|
71
|
+
IIIFManifest::ManifestBuilder::IIIFManifest::Collection
|
72
72
|
end
|
73
73
|
|
74
74
|
def composite_builder
|
@@ -80,7 +80,11 @@ module IIIFManifest
|
|
80
80
|
end
|
81
81
|
|
82
82
|
def record_property_builder
|
83
|
-
|
83
|
+
InjectedFactory.new(
|
84
|
+
ManifestBuilder::RecordPropertyBuilder,
|
85
|
+
iiif_search_service_factory: iiif_search_service_factory,
|
86
|
+
iiif_autocomplete_service_factory: iiif_autocomplete_service_factory
|
87
|
+
)
|
84
88
|
end
|
85
89
|
|
86
90
|
def structure_builder
|
@@ -108,7 +112,7 @@ module IIIFManifest
|
|
108
112
|
end
|
109
113
|
|
110
114
|
def sequence_factory
|
111
|
-
|
115
|
+
IIIFManifest::ManifestBuilder::IIIFManifest::Sequence
|
112
116
|
end
|
113
117
|
|
114
118
|
def canvas_builder_factory
|
@@ -157,27 +161,35 @@ module IIIFManifest
|
|
157
161
|
end
|
158
162
|
|
159
163
|
def iiif_service_factory
|
160
|
-
|
164
|
+
IIIFManifest::ManifestBuilder::IIIFService
|
161
165
|
end
|
162
166
|
|
163
167
|
def iiif_resource_factory
|
164
|
-
|
168
|
+
IIIFManifest::ManifestBuilder::IIIFManifest::Resource
|
165
169
|
end
|
166
170
|
|
167
171
|
def iiif_annotation_factory
|
168
|
-
|
172
|
+
IIIFManifest::ManifestBuilder::IIIFManifest::Annotation
|
169
173
|
end
|
170
174
|
|
171
175
|
def iiif_manifest_factory
|
172
|
-
|
176
|
+
IIIFManifest::ManifestBuilder::IIIFManifest
|
173
177
|
end
|
174
178
|
|
175
179
|
def iiif_canvas_factory
|
176
|
-
|
180
|
+
IIIFManifest::ManifestBuilder::IIIFManifest::Canvas
|
177
181
|
end
|
178
182
|
|
179
183
|
def iiif_range_factory
|
180
|
-
|
184
|
+
IIIFManifest::ManifestBuilder::IIIFManifest::Range
|
185
|
+
end
|
186
|
+
|
187
|
+
def iiif_search_service_factory
|
188
|
+
IIIFManifest::ManifestBuilder::IIIFManifest::SearchService
|
189
|
+
end
|
190
|
+
|
191
|
+
def iiif_autocomplete_service_factory
|
192
|
+
IIIFManifest::ManifestBuilder::IIIFManifest::AutocompleteService
|
181
193
|
end
|
182
194
|
end
|
183
195
|
|
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.
|
4
|
+
version: 0.4.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:
|
12
|
+
date: 2018-02-28 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activesupport
|
@@ -26,33 +26,33 @@ dependencies:
|
|
26
26
|
- !ruby/object:Gem::Version
|
27
27
|
version: '4'
|
28
28
|
- !ruby/object:Gem::Dependency
|
29
|
-
name:
|
29
|
+
name: bundler
|
30
30
|
requirement: !ruby/object:Gem::Requirement
|
31
31
|
requirements:
|
32
32
|
- - "~>"
|
33
33
|
- !ruby/object:Gem::Version
|
34
|
-
version:
|
35
|
-
type: :
|
34
|
+
version: '1.11'
|
35
|
+
type: :development
|
36
36
|
prerelease: false
|
37
37
|
version_requirements: !ruby/object:Gem::Requirement
|
38
38
|
requirements:
|
39
39
|
- - "~>"
|
40
40
|
- !ruby/object:Gem::Version
|
41
|
-
version:
|
41
|
+
version: '1.11'
|
42
42
|
- !ruby/object:Gem::Dependency
|
43
|
-
name:
|
43
|
+
name: pry-byebug
|
44
44
|
requirement: !ruby/object:Gem::Requirement
|
45
45
|
requirements:
|
46
|
-
- - "
|
46
|
+
- - ">="
|
47
47
|
- !ruby/object:Gem::Version
|
48
|
-
version: '
|
48
|
+
version: '0'
|
49
49
|
type: :development
|
50
50
|
prerelease: false
|
51
51
|
version_requirements: !ruby/object:Gem::Requirement
|
52
52
|
requirements:
|
53
|
-
- - "
|
53
|
+
- - ">="
|
54
54
|
- !ruby/object:Gem::Version
|
55
|
-
version: '
|
55
|
+
version: '0'
|
56
56
|
- !ruby/object:Gem::Dependency
|
57
57
|
name: rake
|
58
58
|
requirement: !ruby/object:Gem::Requirement
|
@@ -109,20 +109,6 @@ dependencies:
|
|
109
109
|
- - ">="
|
110
110
|
- !ruby/object:Gem::Version
|
111
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'
|
126
112
|
description: IIIF http://iiif.io/ defines an API for presenting related images in
|
127
113
|
a viewer. This transforms Hydra::Works objects into that format usable by players
|
128
114
|
such as http://universalviewer.io/
|
@@ -156,6 +142,7 @@ files:
|
|
156
142
|
- lib/iiif_manifest/manifest_builder/composite_builder.rb
|
157
143
|
- lib/iiif_manifest/manifest_builder/composite_builder_factory.rb
|
158
144
|
- lib/iiif_manifest/manifest_builder/deep_canvas_builder_factory.rb
|
145
|
+
- lib/iiif_manifest/manifest_builder/iiif_service.rb
|
159
146
|
- lib/iiif_manifest/manifest_builder/image_builder.rb
|
160
147
|
- lib/iiif_manifest/manifest_builder/image_service_builder.rb
|
161
148
|
- lib/iiif_manifest/manifest_builder/record_property_builder.rb
|
@@ -184,7 +171,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
184
171
|
version: '0'
|
185
172
|
requirements: []
|
186
173
|
rubyforge_project:
|
187
|
-
rubygems_version: 2.6.
|
174
|
+
rubygems_version: 2.6.14
|
188
175
|
signing_key:
|
189
176
|
specification_version: 4
|
190
177
|
summary: Generate IIIF presentation manifests for Hydra::Works
|