diff --git a/README.md b/README.md index bff0bbb..2febb93 100644 --- a/README.md +++ b/README.md @@ -107,6 +107,8 @@ For example: The class that represents the leaf nodes, must implement `#id`. It must also implement `#display_image` which returns an instance of `IIIFManifest::DisplayImage` +Additionally it **_may_** implement `#sequence_rendering` to contain an array of hashes for file downloads to be offered at each leaf node. This follows a similar format as `#sequence_rendering` at sequences level. + ```ruby class Page def initialize(id) @@ -126,6 +128,10 @@ The class that represents the leaf nodes, must implement `#id`. It must also imp ) end + def sequence_rendering + [{"@id" => "http://test.host/display_image/id/download", "format" => "application/pdf", "label" => "Download"}] + end + private def endpoint diff --git a/lib/iiif_manifest/v3/manifest_builder/canvas_builder.rb b/lib/iiif_manifest/v3/manifest_builder/canvas_builder.rb index 11bbea7..88f0bc0 100644 --- a/lib/iiif_manifest/v3/manifest_builder/canvas_builder.rb +++ b/lib/iiif_manifest/v3/manifest_builder/canvas_builder.rb @@ -59,6 +59,7 @@ def apply_record_properties annotation_page['id'] = "#{path}/annotation_page/#{annotation_page.index}" canvas.items = [annotation_page] apply_thumbnail_to(canvas) + canvas.rendering = populate_rendering if populate_rendering.present? end def apply_thumbnail_to(canvas) @@ -84,6 +85,18 @@ def attach_content choice_builder.new(display_content).apply(canvas) end end + + def populate_rendering + return unless record.respond_to?(:sequence_rendering) + record.sequence_rendering.collect do |rendering| + sequence_rendering = rendering.to_h.except('@id', 'label') + sequence_rendering['id'] = rendering['@id'] + if rendering['label'].present? + sequence_rendering['label'] = ManifestBuilder.language_map(rendering['label']) + end + sequence_rendering + end + end end end end diff --git a/lib/iiif_manifest/v3/manifest_builder/iiif_service.rb b/lib/iiif_manifest/v3/manifest_builder/iiif_service.rb index 6585fb5..30ff6b1 100644 --- a/lib/iiif_manifest/v3/manifest_builder/iiif_service.rb +++ b/lib/iiif_manifest/v3/manifest_builder/iiif_service.rb @@ -136,6 +136,10 @@ def initial_attributes 'type' => 'Canvas' } end + + def rendering=(rendering) + inner_hash['rendering'] = rendering + end end class Range < IIIFService diff --git a/spec/lib/iiif_manifest/v3/manifest_builder/canvas_builder_spec.rb b/spec/lib/iiif_manifest/v3/manifest_builder/canvas_builder_spec.rb index 6b9fa3f..7285014 100644 --- a/spec/lib/iiif_manifest/v3/manifest_builder/canvas_builder_spec.rb +++ b/spec/lib/iiif_manifest/v3/manifest_builder/canvas_builder_spec.rb @@ -152,6 +152,24 @@ def id end end + context 'when display content has no rendering sequence' do + let(:display_content) do + IIIFManifest::V3::DisplayContent.new(url, + width: 640, + height: 480, + type: 'Image', + format: 'image/jpeg', + label: 'full', + iiif_endpoint: iiif_endpoint) + end + it 'generates canvas without rendering property' do + canvas = builder.canvas + expect(canvas).to be_a IIIFManifest::V3::ManifestBuilder::IIIFManifest::Canvas + values = canvas.inner_hash + expect(values.key?('rendering')).to be false + end + end + context 'when the display content is empty for an item' do before do class MyWork diff --git a/spec/lib/iiif_manifest/v3/manifest_factory_spec.rb b/spec/lib/iiif_manifest/v3/manifest_factory_spec.rb index bd608e1..d05dd1b 100644 --- a/spec/lib/iiif_manifest/v3/manifest_factory_spec.rb +++ b/spec/lib/iiif_manifest/v3/manifest_factory_spec.rb @@ -499,6 +499,17 @@ def to_s def display_content content end + + def sequence_rendering + [ + { + '@id' => 'http://example.com/file_to_download.json', + 'format' => 'application/json', + 'type' => 'Dataset', + 'label' => 'index.json' + } + ] + end end allow(book_presenter).to receive(:file_set_presenters).and_return([file_presenter]) @@ -525,6 +536,14 @@ def display_content expect(content_annotation_body['width']).to eq 100 expect(content_annotation_body['format']).to eq 'image/jpeg' end + + it 'returns rendering' do + canvas = result['items'].first + expect(canvas.key?('rendering')).to eq true + expect(canvas['rendering'].first['type']).to eq "Dataset" + expect(canvas['rendering'].first['format']).to eq "application/json" + expect(canvas['rendering'].first['label']).to eq({ "none" => ["index.json"] }) + end end context 'with a single file' do @@ -547,6 +566,14 @@ def display_content expect(content_annotation_body['label']).to eq('none' => ['High']) end + it 'returns rendering' do + canvas = result['items'].first + expect(canvas.key?('rendering')).to eq true + expect(canvas['rendering'].first['type']).to eq "Dataset" + expect(canvas['rendering'].first['format']).to eq "application/json" + expect(canvas['rendering'].first['label']).to eq({ "none" => ["index.json"] }) + end + context 'with audio file' do let(:content) do IIIFManifest::V3::DisplayContent.new(SecureRandom.uuid, duration: 100, @@ -637,6 +664,14 @@ def display_content expect(choice['label']['none']).not_to be_empty end end + + it 'returns rendering' do + canvas = result['items'].first + expect(canvas.key?('rendering')).to eq true + expect(canvas['rendering'].first['type']).to eq "Dataset" + expect(canvas['rendering'].first['format']).to eq "application/json" + expect(canvas['rendering'].first['label']).to eq({ "none" => ["index.json"] }) + end end end