iiif_manifest 1.1.1 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ebfc009f93b6b56223eefbe2387b77b481b0897e74ff06861dd9731f1cb11da4
4
- data.tar.gz: 9db51ecae1599ccf29cfa94d32b73630cb8f29e77909556bf9621224d0d0c728
3
+ metadata.gz: d8dd7b48693245057fa3e99f6b3f434da255e4f1e7f26412e1b56937a73dace4
4
+ data.tar.gz: 6b719a4f0b94ed7347420d5c940d8b2244195a201bd2415e9842ee7e55c8afab
5
5
  SHA512:
6
- metadata.gz: 40acf74c8a9fbab07080e074d24216d705af922ec44bb9c318cd4bf0c74acf1e00ac0a6de22dc737ed678dcbcc172229dc4c5d5dcf5195d94906bfd2fc558321
7
- data.tar.gz: cf16d75f2eab225b03ca7935aa4bf6ec8d22c45f8173a9b9fe654f6db7aaacb97a807b8ec594d7422e29925c4aaeebf45ac81daf781b47a862aaf52b1530d509
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 be built using `IIIFManifest::ManifestFactory` while version 3.0 manifests can now be built using `IIIFManifest::V3::ManifestFactory`.
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
- manifest.label = record.to_s
14
- manifest.description = record.description
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:, width: nil, height: nil, duration: nil, label: nil,
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
- if record.respond_to?(:sequence_rendering)
25
- record.sequence_rendering.collect do |rendering|
26
- sequence_rendering = rendering.to_h.except('@id', 'label')
27
- sequence_rendering['id'] = rendering['@id']
28
- if rendering['label'].present?
29
- sequence_rendering['label'] = ManifestBuilder.language_map(rendering['label'])
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
- else
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
- # rubocop:disable Metrics/CyclomaticComplexity
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
- manifest.label = ManifestBuilder.language_map(record.to_s) if record.to_s.present?
48
- manifest.summary = ManifestBuilder.language_map(record.description) if record.try(:description).present?
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
- manifest.homepage = record.homepage if record.try(:homepage).present?
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
- # rubocop:enable Metrics/CyclomaticComplexity
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
- { '@none' => Array(obj) }
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
@@ -1,3 +1,3 @@
1
1
  module IIIFManifest
2
- VERSION = '1.1.1'.freeze
2
+ VERSION = '1.2.0'.freeze
3
3
  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.1.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-04-07 00:00:00.000000000 Z
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