iiif_manifest 1.1.1 → 1.2.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.
- checksums.yaml +4 -4
- data/README.md +36 -1
- data/lib/iiif_manifest/configuration.rb +68 -0
- data/lib/iiif_manifest/display_image.rb +4 -2
- data/lib/iiif_manifest/manifest_builder/record_property_builder.rb +4 -2
- data/lib/iiif_manifest/v3/display_content.rb +10 -10
- data/lib/iiif_manifest/v3/manifest_builder/canvas_builder.rb +15 -2
- data/lib/iiif_manifest/v3/manifest_builder/content_builder.rb +2 -1
- data/lib/iiif_manifest/v3/manifest_builder/iiif_service.rb +32 -3
- data/lib/iiif_manifest/v3/manifest_builder/image_service_builder.rb +2 -2
- data/lib/iiif_manifest/v3/manifest_builder/record_property_builder.rb +36 -19
- data/lib/iiif_manifest/v3/manifest_builder/thumbnail_builder.rb +66 -0
- data/lib/iiif_manifest/v3/manifest_builder.rb +2 -1
- data/lib/iiif_manifest/v3/manifest_service_locator.rb +16 -2
- data/lib/iiif_manifest/version.rb +1 -1
- data/lib/iiif_manifest.rb +43 -0
- metadata +4 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: d8dd7b48693245057fa3e99f6b3f434da255e4f1e7f26412e1b56937a73dace4
|
|
4
|
+
data.tar.gz: 6b719a4f0b94ed7347420d5c940d8b2244195a201bd2415e9842ee7e55c8afab
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 9f38cc5f1426ea385f128351a3189989cc31a1138faa693b4938f71a8fca3964da01bd1d17c3eff5501060c9483a6a6a95874feea87df1f7d9a35a55e4d3aa93
|
|
7
|
+
data.tar.gz: fb614960e6bcfd54792d061a783cb7f8719a5dddc1d6060b3ba8173136700537715ab2cc48234602c3788fef95d5c2ca8ffd9a505a4ae09c4f6c4fea54554a15
|
data/README.md
CHANGED
|
@@ -144,7 +144,7 @@ Then you can produce the manifest on the book object like this:
|
|
|
144
144
|
|
|
145
145
|
Provisional support for the [3.0 alpha version of the IIIF presentation api spec](https://iiif.io/api/presentation/3.0/) has been added with a focus on audiovisual content. The [change log](https://iiif.io/api/presentation/3.0/change-log/) lists the changes to the specification.
|
|
146
146
|
|
|
147
|
-
The presentation 3.0 support has been contained to the `V3` namespace. Version 2.0 manifests are still
|
|
147
|
+
The presentation 3.0 support has been contained to the `V3` namespace. Version 2.0 manifests are still being built using `IIIFManifest::ManifestFactory` while version 3.0 manifests can now be built using `IIIFManifest::V3::ManifestFactory`.
|
|
148
148
|
|
|
149
149
|
```ruby
|
|
150
150
|
book = Book.new('book-77',[Page.new('page-99')])
|
|
@@ -161,6 +161,41 @@ The presentation 3.0 support has been contained to the `V3` namespace. Version 2
|
|
|
161
161
|
- File set presenters may provide `#display_content` which should return an instance of `IIIFManifest::V3::DisplayContent` (or an array of instances in the case of a user `Choice`). `#display_image` is no longer required but will still work if provided.
|
|
162
162
|
- DisplayContent may provide `#auth_service` which should return a hash containing a IIIF Authentication service definition (<https://iiif.io/api/auth/1.0/>) that will be included on the content resource.
|
|
163
163
|
|
|
164
|
+
## Configuration
|
|
165
|
+
|
|
166
|
+
The `label`, `rights`, `homepage`, `description` (V2 only), and `summary` (V3 only) properties can be configured to pull its information from different attributes.
|
|
167
|
+
|
|
168
|
+
**NOTE:** In the V2 manifest, `label` and `description` is expected to be a string so if the model's attribute is multivalued, only the first value would be used.
|
|
169
|
+
|
|
170
|
+
To enable this, add the following code to a config file at `config/initializers/iiif_manifest_config.rb` in your application.
|
|
171
|
+
```ruby
|
|
172
|
+
# Example: use the default configuration but amend the summary property
|
|
173
|
+
IIIFManifest.config do |config|
|
|
174
|
+
config.manifest_property_to_record_method_name_map.merge!(summary: :abstract, rights: :license)
|
|
175
|
+
end
|
|
176
|
+
```
|
|
177
|
+
In the above example of a V3 manifest (since it is a `summary` instead of `description`), the `summary` property will be using the model's `#abstract` attribute value instead of the default `#description`. The `rights` property will use the model's `#license` attribute instead of the default `#rights_statement`. All other configurable properties will use their defaults.
|
|
178
|
+
|
|
179
|
+
```ruby
|
|
180
|
+
# Example: use this configuration to set the max edge length of thumbnails, default is 200
|
|
181
|
+
IIIFManifest.confg do |config|
|
|
182
|
+
config.max_edge_for_thumbnail = 100
|
|
183
|
+
end
|
|
184
|
+
```
|
|
185
|
+
Thumbnails have been added for version 3 manifests because [Universal Viewer](https://github.com/UniversalViewer/universalviewer/issues/102) currently require them to be explicitly set otherwise they would not show up. The above example is used to configure what the default size for the thumbnails would be.
|
|
186
|
+
|
|
187
|
+
```ruby
|
|
188
|
+
# Example: use this configuration to disable thumbnails to show up by default on the manifest level (version 3 only)
|
|
189
|
+
IIIFManifest.confg do |config|
|
|
190
|
+
config.manifest_thumbnail = false
|
|
191
|
+
end
|
|
192
|
+
```
|
|
193
|
+
According to the Presentation API 3.0 [specifications](https://iiif.io/api/presentation/3.0/#thumbnail):
|
|
194
|
+
> A Manifest *SHOULD* have the `thumbnail` property with at least one item.
|
|
195
|
+
|
|
196
|
+
The above configuration allows you to disable that if desired since it is not a *MUST*.
|
|
197
|
+
|
|
198
|
+
|
|
164
199
|
# Development
|
|
165
200
|
|
|
166
201
|
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.
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module IIIFManifest
|
|
4
|
+
##
|
|
5
|
+
# Handles configuration for the IIIFManifest gem
|
|
6
|
+
#
|
|
7
|
+
# @see IIIFManifest.config
|
|
8
|
+
class Configuration
|
|
9
|
+
DEFAULT_MANIFEST_PROPERTY_TO_RECORD_METHOD_NAME_MAP = {
|
|
10
|
+
summary: :description, # for V3 manifests
|
|
11
|
+
description: :description, # for V2 manifests
|
|
12
|
+
label: :to_s,
|
|
13
|
+
rights: :rights_statement,
|
|
14
|
+
homepage: :homepage
|
|
15
|
+
}.freeze
|
|
16
|
+
|
|
17
|
+
##
|
|
18
|
+
# @!attribute [w] manifest_property_to_record_method_name_map
|
|
19
|
+
# @param value [Hash<Symbol, Symbol>]
|
|
20
|
+
# @return [Hash<Symbol, Symbol>]
|
|
21
|
+
attr_writer :manifest_property_to_record_method_name_map
|
|
22
|
+
# Used to map a record's public method to a manifest property.
|
|
23
|
+
# @see manifest_value_for
|
|
24
|
+
# @see DEFAULT_MANIFEST_PROPERTY_TO_RECORD_METHOD_NAME_MAP DEFAULT_MANIFEST_PROPERTY_TO_RECORD_METHOD_NAME_MAP
|
|
25
|
+
# are the default values
|
|
26
|
+
# @return [Hash<Symbol, Symbol>]
|
|
27
|
+
def manifest_property_to_record_method_name_map
|
|
28
|
+
# the constant is frozen but we need to be able to configure something unfrozen
|
|
29
|
+
@manifest_property_to_record_method_name_map ||= DEFAULT_MANIFEST_PROPERTY_TO_RECORD_METHOD_NAME_MAP.dup
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
##
|
|
33
|
+
# @param value [Integer]
|
|
34
|
+
attr_writer :max_edge_for_thumbnail
|
|
35
|
+
# Used to set max edge length for thumbnail generation.
|
|
36
|
+
# @return [Integer]
|
|
37
|
+
def max_edge_for_thumbnail
|
|
38
|
+
return @max_edge_for_thumbnail unless @max_edge_for_thumbnail.nil?
|
|
39
|
+
@max_edge_for_thumbnail = 200
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
attr_writer :manifest_thumbnail
|
|
43
|
+
# Used to configure whether or not to show the manifest thumbnail property.
|
|
44
|
+
# @return [Boolean]
|
|
45
|
+
def manifest_thumbnail
|
|
46
|
+
return @manifest_thumbnail unless @manifest_thumbnail.nil?
|
|
47
|
+
@manifest_thumbnail = true
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
##
|
|
51
|
+
# @api private
|
|
52
|
+
# @param record [Object] has the value for the :property we want to set
|
|
53
|
+
# @param property [Symbol] IIIF manifest property
|
|
54
|
+
# @return [NilClass] the record does not have a value for the given property
|
|
55
|
+
# @return [#to_s] the record has a value that is "present"
|
|
56
|
+
def manifest_value_for(record, property:)
|
|
57
|
+
method_name = map_property_to_method_name(property: property)
|
|
58
|
+
return nil unless record.respond_to?(method_name)
|
|
59
|
+
record.public_send(method_name)
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
private
|
|
63
|
+
|
|
64
|
+
def map_property_to_method_name(property:)
|
|
65
|
+
manifest_property_to_record_method_name_map.fetch(property)
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
module IIIFManifest
|
|
2
2
|
class DisplayImage
|
|
3
|
-
attr_reader :url, :width, :height, :iiif_endpoint, :format
|
|
4
|
-
def initialize(url, width:, height:, format: nil, iiif_endpoint: nil)
|
|
3
|
+
attr_reader :url, :type, :width, :height, :iiif_endpoint, :format, :thumbnail
|
|
4
|
+
def initialize(url, width:, height:, format: nil, iiif_endpoint: nil, thumbnail: nil)
|
|
5
5
|
@url = url
|
|
6
|
+
@type = 'Image'
|
|
6
7
|
@width = width
|
|
7
8
|
@height = height
|
|
8
9
|
@format = format
|
|
9
10
|
@iiif_endpoint = iiif_endpoint
|
|
11
|
+
@thumbnail = thumbnail
|
|
10
12
|
end
|
|
11
13
|
end
|
|
12
14
|
end
|
|
@@ -10,8 +10,10 @@ module IIIFManifest
|
|
|
10
10
|
|
|
11
11
|
def apply(manifest)
|
|
12
12
|
manifest['@id'] = record.manifest_url.to_s
|
|
13
|
-
|
|
14
|
-
manifest.
|
|
13
|
+
label = Array(::IIIFManifest.config.manifest_value_for(record, property: :label)).first
|
|
14
|
+
manifest.label = label
|
|
15
|
+
description = Array(::IIIFManifest.config.manifest_value_for(record, property: :description)).first
|
|
16
|
+
manifest.description = description
|
|
15
17
|
manifest.viewing_hint = viewing_hint if viewing_hint.present?
|
|
16
18
|
manifest.viewing_direction = viewing_direction if viewing_direction.present?
|
|
17
19
|
manifest.metadata = record.manifest_metadata if valid_metadata?
|
|
@@ -2,18 +2,18 @@ module IIIFManifest
|
|
|
2
2
|
module V3
|
|
3
3
|
class DisplayContent
|
|
4
4
|
attr_reader :url, :width, :height, :duration, :iiif_endpoint, :format, :type,
|
|
5
|
-
:label, :auth_service
|
|
6
|
-
def initialize(url, type:,
|
|
7
|
-
format: nil, iiif_endpoint: nil, auth_service: nil)
|
|
5
|
+
:label, :auth_service, :thumbnail
|
|
6
|
+
def initialize(url, type:, **kwargs)
|
|
8
7
|
@url = url
|
|
9
8
|
@type = type
|
|
10
|
-
@width = width
|
|
11
|
-
@height = height
|
|
12
|
-
@duration = duration
|
|
13
|
-
@label = label
|
|
14
|
-
@format = format
|
|
15
|
-
@iiif_endpoint = iiif_endpoint
|
|
16
|
-
@auth_service = auth_service
|
|
9
|
+
@width = kwargs[:width]
|
|
10
|
+
@height = kwargs[:height]
|
|
11
|
+
@duration = kwargs[:duration]
|
|
12
|
+
@label = kwargs[:label]
|
|
13
|
+
@format = kwargs[:format]
|
|
14
|
+
@iiif_endpoint = kwargs[:iiif_endpoint]
|
|
15
|
+
@auth_service = kwargs[:auth_service]
|
|
16
|
+
@thumbnail = kwargs[:thumbnail]
|
|
17
17
|
end
|
|
18
18
|
end
|
|
19
19
|
end
|
|
@@ -3,20 +3,22 @@ module IIIFManifest
|
|
|
3
3
|
class ManifestBuilder
|
|
4
4
|
class CanvasBuilder
|
|
5
5
|
attr_reader :record, :parent, :iiif_canvas_factory, :content_builder,
|
|
6
|
-
:choice_builder, :iiif_annotation_page_factory
|
|
6
|
+
:choice_builder, :iiif_annotation_page_factory, :thumbnail_builder_factory
|
|
7
7
|
|
|
8
8
|
def initialize(record,
|
|
9
9
|
parent,
|
|
10
10
|
iiif_canvas_factory:,
|
|
11
11
|
content_builder:,
|
|
12
12
|
choice_builder:,
|
|
13
|
-
iiif_annotation_page_factory
|
|
13
|
+
iiif_annotation_page_factory:,
|
|
14
|
+
thumbnail_builder_factory:)
|
|
14
15
|
@record = record
|
|
15
16
|
@parent = parent
|
|
16
17
|
@iiif_canvas_factory = iiif_canvas_factory
|
|
17
18
|
@content_builder = content_builder
|
|
18
19
|
@choice_builder = choice_builder
|
|
19
20
|
@iiif_annotation_page_factory = iiif_annotation_page_factory
|
|
21
|
+
@thumbnail_builder_factory = thumbnail_builder_factory
|
|
20
22
|
apply_record_properties
|
|
21
23
|
# Presentation 2.x approach
|
|
22
24
|
attach_image if display_image
|
|
@@ -45,6 +47,8 @@ module IIIFManifest
|
|
|
45
47
|
record.display_image if record.respond_to?(:display_image)
|
|
46
48
|
end
|
|
47
49
|
|
|
50
|
+
# @return [Array<Object>] if the record has a display content
|
|
51
|
+
# @return [NilClass] if there is no display content
|
|
48
52
|
def display_content
|
|
49
53
|
Array.wrap(record.display_content) if record.respond_to?(:display_content) && record.display_content.present?
|
|
50
54
|
end
|
|
@@ -54,6 +58,15 @@ module IIIFManifest
|
|
|
54
58
|
canvas.label = ManifestBuilder.language_map(record.to_s) if record.to_s.present?
|
|
55
59
|
annotation_page['id'] = "#{path}/annotation_page/#{annotation_page.index}"
|
|
56
60
|
canvas.items = [annotation_page]
|
|
61
|
+
apply_thumbnail_to(canvas)
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def apply_thumbnail_to(canvas)
|
|
65
|
+
if display_image
|
|
66
|
+
canvas.thumbnail = Array(thumbnail_builder_factory.new(display_image).build)
|
|
67
|
+
elsif display_content.try(:first)
|
|
68
|
+
canvas.thumbnail = Array(thumbnail_builder_factory.new(display_content.first).build)
|
|
69
|
+
end
|
|
57
70
|
end
|
|
58
71
|
|
|
59
72
|
def annotation_page
|
|
@@ -11,11 +11,12 @@ module IIIFManifest
|
|
|
11
11
|
end
|
|
12
12
|
|
|
13
13
|
def apply(canvas)
|
|
14
|
+
# Assume first item in canvas is an annotation page
|
|
15
|
+
annotation['id'] = "#{canvas.items.first['id']}/annotation/#{annotation.index}"
|
|
14
16
|
annotation['target'] = canvas['id']
|
|
15
17
|
canvas['width'] = annotation.body['width'] if annotation.body['width'].present?
|
|
16
18
|
canvas['height'] = annotation.body['height'] if annotation.body['height'].present?
|
|
17
19
|
canvas['duration'] = annotation.body['duration'] if annotation.body['duration'].present?
|
|
18
|
-
# Assume first item in canvas is an annotation page
|
|
19
20
|
canvas.items.first.items += [annotation]
|
|
20
21
|
end
|
|
21
22
|
|
|
@@ -65,13 +65,17 @@ module IIIFManifest
|
|
|
65
65
|
end
|
|
66
66
|
|
|
67
67
|
def rights=(rights)
|
|
68
|
-
inner_hash['rights'] = rights
|
|
68
|
+
inner_hash['rights'] = Array(rights).first
|
|
69
69
|
end
|
|
70
70
|
|
|
71
71
|
def homepage=(homepage)
|
|
72
72
|
inner_hash['homepage'] = homepage
|
|
73
73
|
end
|
|
74
74
|
|
|
75
|
+
def thumbnail=(thumbnail)
|
|
76
|
+
inner_hash['thumbnail'] = thumbnail
|
|
77
|
+
end
|
|
78
|
+
|
|
75
79
|
def initial_attributes
|
|
76
80
|
{
|
|
77
81
|
'@context' => [
|
|
@@ -119,6 +123,14 @@ module IIIFManifest
|
|
|
119
123
|
inner_hash['items'] = items
|
|
120
124
|
end
|
|
121
125
|
|
|
126
|
+
def thumbnail
|
|
127
|
+
inner_hash['thumbnail']
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
def thumbnail=(thumbnail)
|
|
131
|
+
inner_hash['thumbnail'] = thumbnail
|
|
132
|
+
end
|
|
133
|
+
|
|
122
134
|
def initial_attributes
|
|
123
135
|
{
|
|
124
136
|
'type' => 'Canvas'
|
|
@@ -191,6 +203,10 @@ module IIIFManifest
|
|
|
191
203
|
inner_hash['body']
|
|
192
204
|
end
|
|
193
205
|
|
|
206
|
+
def index
|
|
207
|
+
@index ||= SecureRandom.uuid
|
|
208
|
+
end
|
|
209
|
+
|
|
194
210
|
def initial_attributes
|
|
195
211
|
{
|
|
196
212
|
'type' => 'Annotation',
|
|
@@ -212,7 +228,8 @@ module IIIFManifest
|
|
|
212
228
|
{
|
|
213
229
|
'@context' => 'http://iiif.io/api/search/1/context.json',
|
|
214
230
|
'profile' => 'http://iiif.io/api/search/1/search',
|
|
215
|
-
'label' => 'Search within this manifest'
|
|
231
|
+
'label' => 'Search within this manifest',
|
|
232
|
+
'type' => 'SearchService1'
|
|
216
233
|
}
|
|
217
234
|
end
|
|
218
235
|
end
|
|
@@ -229,7 +246,19 @@ module IIIFManifest
|
|
|
229
246
|
def initial_attributes
|
|
230
247
|
{
|
|
231
248
|
'profile' => 'http://iiif.io/api/search/1/autocomplete',
|
|
232
|
-
'label' => 'Get suggested words in this manifest'
|
|
249
|
+
'label' => 'Get suggested words in this manifest',
|
|
250
|
+
'type' => 'AutoCompleteService1'
|
|
251
|
+
}
|
|
252
|
+
end
|
|
253
|
+
end
|
|
254
|
+
|
|
255
|
+
class Thumbnail < IIIFService
|
|
256
|
+
def service=(service)
|
|
257
|
+
inner_hash['service'] = service
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
def initial_attributes
|
|
261
|
+
{
|
|
233
262
|
}
|
|
234
263
|
end
|
|
235
264
|
end
|
|
@@ -9,9 +9,9 @@ module IIIFManifest
|
|
|
9
9
|
end
|
|
10
10
|
|
|
11
11
|
def apply(resource)
|
|
12
|
-
service['id'] = iiif_endpoint.url
|
|
12
|
+
service['@id'] = iiif_endpoint.url
|
|
13
13
|
service['profile'] = iiif_endpoint.profile
|
|
14
|
-
service['type'] = determine_type(iiif_endpoint.context)
|
|
14
|
+
service['@type'] = determine_type(iiif_endpoint.context)
|
|
15
15
|
resource.service = [service]
|
|
16
16
|
end
|
|
17
17
|
|
|
@@ -2,36 +2,36 @@ module IIIFManifest
|
|
|
2
2
|
module V3
|
|
3
3
|
class ManifestBuilder
|
|
4
4
|
class RecordPropertyBuilder < ::IIIFManifest::ManifestBuilder::RecordPropertyBuilder
|
|
5
|
-
attr_reader :canvas_builder_factory
|
|
5
|
+
attr_reader :canvas_builder_factory, :thumbnail_builder_factory
|
|
6
6
|
def initialize(record,
|
|
7
7
|
iiif_search_service_factory:,
|
|
8
8
|
iiif_autocomplete_service_factory:,
|
|
9
|
-
canvas_builder_factory
|
|
9
|
+
canvas_builder_factory:,
|
|
10
|
+
thumbnail_builder_factory:)
|
|
10
11
|
super(record,
|
|
11
12
|
iiif_search_service_factory: iiif_search_service_factory,
|
|
12
13
|
iiif_autocomplete_service_factory: iiif_autocomplete_service_factory)
|
|
13
14
|
@canvas_builder_factory = canvas_builder_factory
|
|
15
|
+
@thumbnail_builder_factory = thumbnail_builder_factory
|
|
14
16
|
end
|
|
15
17
|
|
|
16
18
|
def apply(manifest)
|
|
17
19
|
setup_manifest_from_record(manifest, record)
|
|
18
20
|
# Build the items array
|
|
19
21
|
canvas_builder.apply(manifest.items)
|
|
22
|
+
apply_thumbnail_to(manifest) unless manifest_thumbnail?
|
|
20
23
|
manifest
|
|
21
24
|
end
|
|
22
25
|
|
|
23
26
|
def populate_rendering
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
end
|
|
31
|
-
sequence_rendering
|
|
27
|
+
return unless record.respond_to?(:sequence_rendering)
|
|
28
|
+
record.sequence_rendering.collect do |rendering|
|
|
29
|
+
sequence_rendering = rendering.to_h.except('@id', 'label')
|
|
30
|
+
sequence_rendering['id'] = rendering['@id']
|
|
31
|
+
if rendering['label'].present?
|
|
32
|
+
sequence_rendering['label'] = ManifestBuilder.language_map(rendering['label'])
|
|
32
33
|
end
|
|
33
|
-
|
|
34
|
-
[]
|
|
34
|
+
sequence_rendering
|
|
35
35
|
end
|
|
36
36
|
end
|
|
37
37
|
|
|
@@ -41,19 +41,24 @@ module IIIFManifest
|
|
|
41
41
|
canvas_builder_factory.from(record)
|
|
42
42
|
end
|
|
43
43
|
|
|
44
|
-
|
|
44
|
+
# rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity, Metrics/AbcSize, Metrics/MethodLength
|
|
45
45
|
def setup_manifest_from_record(manifest, record)
|
|
46
46
|
manifest['id'] = record.manifest_url.to_s
|
|
47
|
-
|
|
48
|
-
manifest.
|
|
47
|
+
label = ::IIIFManifest.config.manifest_value_for(record, property: :label)
|
|
48
|
+
manifest.label = ManifestBuilder.language_map(label) if label.present?
|
|
49
|
+
summary = ::IIIFManifest.config.manifest_value_for(record, property: :summary)
|
|
50
|
+
manifest.summary = ManifestBuilder.language_map(summary) if summary.present?
|
|
51
|
+
rights = ::IIIFManifest.config.manifest_value_for(record, property: :rights)
|
|
52
|
+
manifest.rights = rights if rights.present?
|
|
49
53
|
manifest.behavior = viewing_hint if viewing_hint.present?
|
|
50
|
-
manifest.metadata = metadata_from_record(record)
|
|
54
|
+
manifest.metadata = metadata_from_record(record) if metadata_from_record(record).present?
|
|
51
55
|
manifest.viewing_direction = viewing_direction if viewing_direction.present?
|
|
52
56
|
manifest.service = services if search_service.present?
|
|
53
|
-
manifest.rendering = populate_rendering
|
|
54
|
-
|
|
57
|
+
manifest.rendering = populate_rendering if populate_rendering.present?
|
|
58
|
+
homepage = ::IIIFManifest.config.manifest_value_for(record, property: :homepage)
|
|
59
|
+
manifest.homepage = homepage if homepage.present?
|
|
55
60
|
end
|
|
56
|
-
|
|
61
|
+
# rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity, Metrics/AbcSize, Metrics/MethodLength
|
|
57
62
|
|
|
58
63
|
def metadata_from_record(record)
|
|
59
64
|
if valid_v3_metadata?
|
|
@@ -94,6 +99,18 @@ module IIIFManifest
|
|
|
94
99
|
metadata_field['value'] = ManifestBuilder.language_map(field['value'])
|
|
95
100
|
metadata_field
|
|
96
101
|
end
|
|
102
|
+
|
|
103
|
+
def apply_thumbnail_to(manifest)
|
|
104
|
+
if manifest.is_a? IIIFManifest::Collection
|
|
105
|
+
manifest.thumbnail = manifest.items.collect(&:thumbnail).compact
|
|
106
|
+
elsif manifest.items.first&.thumbnail.present?
|
|
107
|
+
manifest.thumbnail = manifest.items.first&.thumbnail
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def manifest_thumbnail?
|
|
112
|
+
::IIIFManifest.config.manifest_thumbnail == false
|
|
113
|
+
end
|
|
97
114
|
end
|
|
98
115
|
end
|
|
99
116
|
end
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
module IIIFManifest
|
|
2
|
+
module V3
|
|
3
|
+
class ManifestBuilder
|
|
4
|
+
class ThumbnailBuilder
|
|
5
|
+
attr_reader :display_content, :iiif_thumbnail_factory, :image_service_builder_factory
|
|
6
|
+
def initialize(display_content, iiif_thumbnail_factory:, image_service_builder_factory:)
|
|
7
|
+
@display_content = display_content
|
|
8
|
+
@iiif_thumbnail_factory = iiif_thumbnail_factory
|
|
9
|
+
@image_service_builder_factory = image_service_builder_factory
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
# @return [Array<Object>]
|
|
13
|
+
def build
|
|
14
|
+
return Array(display_content.thumbnail.map(&:stringify_keys)) unless display_content.thumbnail.nil?
|
|
15
|
+
return nil if display_content.type != "Image" || iiif_endpoint.nil?
|
|
16
|
+
|
|
17
|
+
build_thumbnail
|
|
18
|
+
image_service_builder.apply(thumbnail)
|
|
19
|
+
[thumbnail]
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
private
|
|
23
|
+
|
|
24
|
+
def build_thumbnail
|
|
25
|
+
thumbnail['id'] = File.join(
|
|
26
|
+
display_content.iiif_endpoint.url,
|
|
27
|
+
'full',
|
|
28
|
+
"!#{max_edge},#{max_edge}",
|
|
29
|
+
'0',
|
|
30
|
+
'default.jpg'
|
|
31
|
+
)
|
|
32
|
+
thumbnail['type'] = display_content.type
|
|
33
|
+
thumbnail['height'] = (display_content.height * reduction_ratio).round
|
|
34
|
+
thumbnail['width'] = (display_content.width * reduction_ratio).round
|
|
35
|
+
thumbnail['format'] = display_content.format
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def reduction_ratio
|
|
39
|
+
width = display_content.width
|
|
40
|
+
height = display_content.height
|
|
41
|
+
max_edge = @max_edge.to_f
|
|
42
|
+
return 1 if width <= max_edge && height <= max_edge
|
|
43
|
+
|
|
44
|
+
long_edge = [height, width].max
|
|
45
|
+
max_edge / long_edge
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def max_edge
|
|
49
|
+
@max_edge = ::IIIFManifest.config.max_edge_for_thumbnail
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def thumbnail
|
|
53
|
+
@thumbnail ||= iiif_thumbnail_factory.new
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def iiif_endpoint
|
|
57
|
+
display_content.try(:iiif_endpoint)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def image_service_builder
|
|
61
|
+
image_service_builder_factory.new(iiif_endpoint)
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
@@ -6,6 +6,7 @@ require_relative 'manifest_builder/content_builder'
|
|
|
6
6
|
require_relative 'manifest_builder/body_builder'
|
|
7
7
|
require_relative 'manifest_builder/structure_builder'
|
|
8
8
|
require_relative 'manifest_builder/image_service_builder'
|
|
9
|
+
require_relative 'manifest_builder/thumbnail_builder'
|
|
9
10
|
|
|
10
11
|
module IIIFManifest
|
|
11
12
|
module V3
|
|
@@ -28,7 +29,7 @@ module IIIFManifest
|
|
|
28
29
|
|
|
29
30
|
def obj_to_language_map(obj)
|
|
30
31
|
return nil unless obj.is_a?(String) || (obj.is_a?(Array) && obj.all? { |o| o.is_a?(String) })
|
|
31
|
-
{ '
|
|
32
|
+
{ 'none' => Array(obj) }
|
|
32
33
|
end
|
|
33
34
|
end
|
|
34
35
|
|
|
@@ -29,7 +29,8 @@ module IIIFManifest
|
|
|
29
29
|
ManifestBuilder::RecordPropertyBuilder,
|
|
30
30
|
iiif_search_service_factory: iiif_search_service_factory,
|
|
31
31
|
iiif_autocomplete_service_factory: iiif_autocomplete_service_factory,
|
|
32
|
-
canvas_builder_factory: deep_canvas_builder_factory
|
|
32
|
+
canvas_builder_factory: deep_canvas_builder_factory,
|
|
33
|
+
thumbnail_builder_factory: thumbnail_builder_factory
|
|
33
34
|
# canvas_builder_factory: canvas_builder_factory
|
|
34
35
|
)
|
|
35
36
|
end
|
|
@@ -55,7 +56,8 @@ module IIIFManifest
|
|
|
55
56
|
iiif_canvas_factory: iiif_canvas_factory,
|
|
56
57
|
content_builder: content_builder,
|
|
57
58
|
choice_builder: choice_builder,
|
|
58
|
-
iiif_annotation_page_factory: iiif_annotation_page_factory
|
|
59
|
+
iiif_annotation_page_factory: iiif_annotation_page_factory,
|
|
60
|
+
thumbnail_builder_factory: thumbnail_builder_factory
|
|
59
61
|
)
|
|
60
62
|
end
|
|
61
63
|
|
|
@@ -84,6 +86,14 @@ module IIIFManifest
|
|
|
84
86
|
)
|
|
85
87
|
end
|
|
86
88
|
|
|
89
|
+
def thumbnail_builder_factory
|
|
90
|
+
IIIFManifest::ManifestServiceLocator::InjectedFactory.new(
|
|
91
|
+
ManifestBuilder::ThumbnailBuilder,
|
|
92
|
+
iiif_thumbnail_factory: iiif_thumbnail_factory,
|
|
93
|
+
image_service_builder_factory: image_service_builder_factory
|
|
94
|
+
)
|
|
95
|
+
end
|
|
96
|
+
|
|
87
97
|
def image_service_builder_factory
|
|
88
98
|
IIIFManifest::ManifestServiceLocator::InjectedFactory.new(
|
|
89
99
|
ManifestBuilder::ImageServiceBuilder,
|
|
@@ -142,6 +152,10 @@ module IIIFManifest
|
|
|
142
152
|
def iiif_autocomplete_service_factory
|
|
143
153
|
IIIFManifest::V3::ManifestBuilder::IIIFManifest::AutocompleteService
|
|
144
154
|
end
|
|
155
|
+
|
|
156
|
+
def iiif_thumbnail_factory
|
|
157
|
+
IIIFManifest::V3::ManifestBuilder::IIIFManifest::Thumbnail
|
|
158
|
+
end
|
|
145
159
|
end
|
|
146
160
|
end
|
|
147
161
|
end
|
data/lib/iiif_manifest.rb
CHANGED
|
@@ -5,6 +5,7 @@ require 'active_support/core_ext/object'
|
|
|
5
5
|
|
|
6
6
|
module IIIFManifest
|
|
7
7
|
extend ActiveSupport::Autoload
|
|
8
|
+
autoload :Configuration
|
|
8
9
|
autoload :ManifestBuilder
|
|
9
10
|
autoload :ManifestFactory
|
|
10
11
|
autoload :ManifestServiceLocator
|
|
@@ -12,4 +13,46 @@ module IIIFManifest
|
|
|
12
13
|
autoload :IIIFCollection
|
|
13
14
|
autoload :IIIFEndpoint
|
|
14
15
|
autoload :V3
|
|
16
|
+
|
|
17
|
+
##
|
|
18
|
+
# @api public
|
|
19
|
+
#
|
|
20
|
+
# Exposes the IIIFManifest configuration.
|
|
21
|
+
#
|
|
22
|
+
# In the below examples, you would add the code to a `config/initializers/iiif_manifest_config.rb` file
|
|
23
|
+
# in your application.
|
|
24
|
+
#
|
|
25
|
+
# @example
|
|
26
|
+
# # obliterate the default configuration and only use the one we gave
|
|
27
|
+
# IIIFManifest.config do |config|
|
|
28
|
+
# config.manifest_property_to_record_method_name_map = { summary: :abstract }
|
|
29
|
+
# end
|
|
30
|
+
#
|
|
31
|
+
# # use the default configuration but amend the summary property
|
|
32
|
+
# IIIFManifest.config do |config|
|
|
33
|
+
# config.manifest_property_to_record_method_name_map.merge!(summary: :abstract)
|
|
34
|
+
# end
|
|
35
|
+
#
|
|
36
|
+
# # set max edge length for thumbnail images
|
|
37
|
+
# # the below example will set the max edge to 100px
|
|
38
|
+
# IIIFManifest.confg do |config|
|
|
39
|
+
# config.max_edge_for_thumbnail = 100
|
|
40
|
+
# end
|
|
41
|
+
#
|
|
42
|
+
# # disable the thumbnail property on the manifest level
|
|
43
|
+
# # since it will be shown by default
|
|
44
|
+
# IIIFManifest.confg do |config|
|
|
45
|
+
# config.manifest_thumbnail = false
|
|
46
|
+
# end
|
|
47
|
+
#
|
|
48
|
+
# @yield [IIIFManifest::Configuration] if a block is passed
|
|
49
|
+
# @return [IIIFManifest::Configuration]
|
|
50
|
+
# @see IIIFManifest::Configuration for configuration options
|
|
51
|
+
def self.config(&block)
|
|
52
|
+
@config ||= IIIFManifest::Configuration.new
|
|
53
|
+
|
|
54
|
+
yield @config if block
|
|
55
|
+
|
|
56
|
+
@config
|
|
57
|
+
end
|
|
15
58
|
end
|
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: 1.
|
|
4
|
+
version: 1.2.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: 2022-
|
|
12
|
+
date: 2022-11-09 00:00:00.000000000 Z
|
|
13
13
|
dependencies:
|
|
14
14
|
- !ruby/object:Gem::Dependency
|
|
15
15
|
name: activesupport
|
|
@@ -138,6 +138,7 @@ files:
|
|
|
138
138
|
- bin/setup
|
|
139
139
|
- iiif_manifest.gemspec
|
|
140
140
|
- lib/iiif_manifest.rb
|
|
141
|
+
- lib/iiif_manifest/configuration.rb
|
|
141
142
|
- lib/iiif_manifest/display_image.rb
|
|
142
143
|
- lib/iiif_manifest/iiif_collection.rb
|
|
143
144
|
- lib/iiif_manifest/iiif_endpoint.rb
|
|
@@ -168,6 +169,7 @@ files:
|
|
|
168
169
|
- lib/iiif_manifest/v3/manifest_builder/image_service_builder.rb
|
|
169
170
|
- lib/iiif_manifest/v3/manifest_builder/record_property_builder.rb
|
|
170
171
|
- lib/iiif_manifest/v3/manifest_builder/structure_builder.rb
|
|
172
|
+
- lib/iiif_manifest/v3/manifest_builder/thumbnail_builder.rb
|
|
171
173
|
- lib/iiif_manifest/v3/manifest_factory.rb
|
|
172
174
|
- lib/iiif_manifest/v3/manifest_service_locator.rb
|
|
173
175
|
- lib/iiif_manifest/version.rb
|