Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/samvera/iiif_manifest
https://github.com/samvera/iiif_manifest
core-components samvera-community
Last synced: 3 days ago
JSON representation
- Host: GitHub
- URL: https://github.com/samvera/iiif_manifest
- Owner: samvera
- License: other
- Created: 2016-05-13T13:06:19.000Z (over 8 years ago)
- Default Branch: main
- Last Pushed: 2024-07-17T19:13:46.000Z (6 months ago)
- Last Synced: 2025-01-10T05:13:27.708Z (10 days ago)
- Topics: core-components, samvera-community
- Language: Ruby
- Homepage:
- Size: 295 KB
- Stars: 10
- Watchers: 73
- Forks: 10
- Open Issues: 8
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- Contributing: CONTRIBUTING.md
- License: LICENSE
- Code of conduct: CODE_OF_CONDUCT.md
- Support: SUPPORT.md
Awesome Lists containing this project
README
# IIIFManifest
Code:
[![CircleCI](https://circleci.com/gh/samvera/iiif_manifest.svg?style=svg)](https://circleci.com/gh/samvera/iiif_manifest) [![Coverage Status](https://coveralls.io/repos/github/samvera/iiif_manifest/badge.svg)](https://coveralls.io/github/samvera/iiif_manifest)Docs:
[![Contribution Guidelines](http://img.shields.io/badge/CONTRIBUTING-Guidelines-blue.svg)](./CONTRIBUTING.md) [![Apache 2.0 License](http://img.shields.io/badge/APACHE2-license-blue.svg)](./LICENSE)Community Support: [![Samvera Community Slack](https://img.shields.io/badge/samvera-slack-blueviolet)](http://slack.samvera.org/)
# What is IIIFManifest
IIIF defines an API for presenting related images in a viewer. This transforms Hydra::Works objects into that format usable by players such as
## Product Owner & Maintenance
`iiif_manifest` is a Core Component of the Samvera Community. The documentation for what this means can be found [here](http://samvera.github.io/core_components.html#requirements-for-a-core-component).
### Product Owner
[kdid](https://github.com/kdid)
# Usage
Your 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 **_must_** have a `#description` method that returns a string.
Additionally it **_should_** implement `#manifest_url` that shows where the manifest can be found.
Additionally it **_should_** implement `#manifest_metadata` to provide an array containing hashes of metadata Label/Value pairs.
Additionally it **_may_** implement `#search_service` to contain the url for a IIIF search api compliant search endpoint and `#autocomplete_service` to contain the url for a 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 implemented a IIIF search service at the endpoint specified in the manifest.
Additionally it **_may_** implement `#service` to contain an array of hashes for services other than `search_service` or `autocomplete_service`. Each must contain "@id" (V2) or "id" (V3) and "@context" (V2) or "type" (V3) and may contain any other arbitrary properties.
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" }`).
Finally, it **_may_** implement `ranges`, which returns an array of objects which represent a table of contents or similar structure, each of which responds to `label`, `ranges`, and `file_set_presenters`.
For example:
```ruby
class Book
def initialize(id, pages = [])
@id = id
@pages = pages
enddef file_set_presenters
@pages
enddef work_presenters
[]
enddef manifest_url
"http://test.host/books/#{@id}/manifest"
enddef description
'a brief description'
enddef manifest_metadata
[
{ "label" => "Title", "value" => "Title of the Item" },
{ "label" => "Creator", "value" => "Morrissey, Stephen Patrick" }
]
enddef search_service
"http://test.host/books/#{@id}/search"
enddef autocomplete_service
"http://test.host/books/#{@id}/autocomplete"
enddef service
[
{
"@context" => "http://iiif.io/api/annext/services/example/context.json",
"@id" => "https://example.org/service",
"profile" => "https://example.org/docs/service"
}
]
enddef sequence_rendering
[{"@id" => "http://test.host/file_set/id/download", "format" => "application/pdf", "label" => "Download"}]
enddef ranges
[
ManifestRange.new(
label: "Table of Contents",
ranges: [
ManifestRange.new(
label: "Chapter 1",
file_set_presenters: @pages
)
]
)
]
end
endclass ManifestRange
attr_reader :label, :ranges, :file_set_presenters
def initialize(label:, ranges: [], file_set_presenters: [])
@label = label
@ranges = ranges
@file_set_presenters = file_set_presenters
end
end
```The class that represents the leaf nodes, must implement `#id`. It must also implement `#display_image` which returns an instance of `IIIFManifest::DisplayImage`
In Presentation 3.0, additionally it **_may_** implement;
- `#item_metadata` to contain an array of hashes for metadata to be displayed at each leaf node. Items must contain "label" and "value" properties.
- `#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
- `#see_also` to contain an array of hashes for related resources to be offered at each leaf node. Items must contain "id" and "type" properties. Items should contain "label", "format", and "profile" properties.
- `#part_of` to contain an array of hashes for parent resources to be offered at each leaf node. Items must contain "id" and "type" properties. Items should contain "label".
- `#homepage` to contain an array of hashes for homepage resources to be offered at each leaf node. Items must contain "id", "type", and "label" properties. Items should contain a "format" property and may contain a "language" property.
- `#placeholder_content` to contain an instance of `IIIFManifest::V3::DisplayContent` for [`placeholderCanvas`](https://iiif.io/api/presentation/3.0/#placeholdercanvas) at each leaf node
- `#service` to contain an array of hashes for services. Each must contain "id" and "type" and may contain any other arbitrary properties.```ruby
class Page
def initialize(id)
@id = id
enddef id
@id
enddef display_image
IIIFManifest::DisplayImage.new(id,
width: 100,
height: 100,
format: "image/jpeg",
iiif_endpoint: endpoint
)
end# --------------------------------------- Presentation 3.0 ---------------------------------------
def sequence_rendering
[{"@id" => "http://test.host/display_image/id/download", "format" => "application/pdf", "label" => "Download"}]
enddef see_also
[{"id" => "http://test.host/display_image/id/image.json", "type" => "dataset", "format" => "application/json", "label" => "Related Resource"}]
enddef part_of
[{"id" => "http://test.host/display_image/id/parent.json", "type" => "manifest"}]
enddef homepage
[{"id" => "http://test.host/display_image/id/homepage", "type" => "Text", "label" => "Item Homepage"}]
enddef placeholder_content
IIIFManifest::V3::DisplayContent.new(id,
width: 100,
height: 100,
type: "Image",
format: "image/jpeg")
enddef service
[
{
"@context" => "http://iiif.io/api/annext/services/example/context.json",
"@id" => "https://example.org/service",
"profile" => "https://example.org/docs/service"
}
]
end
# --------------------------------------- Presentation 3.0 ---------------------------------------private
def endpoint
IIIFManifest::IIIFEndpoint.new("http://test.host/images/#{id}",
profile: "http://iiif.io/api/image/2/level2.json")
end
end
```Then you can produce the manifest on the book object like this:
```ruby
book = Book.new('book-77',[Page.new('page-99')])
IIIFManifest::ManifestFactory.new(book).to_h.to_json
```## Presentation 3.0
Provisional support for the [3.0 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.
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`.
```ruby
book = Book.new('book-77',[Page.new('page-99')])
IIIFManifest::V3::ManifestFactory.new(book).to_h.to_json
```### Notable changes for Presentation 3.0
- Presenters must still define `#description` but it is now serialized as `summary`. ()
- All textual strings, including metadata labels and values, are now serialized as language maps and may be provided as a hash with language code keys with string values. Values not provided in this format are automatically converted so no change to `#description`, `#manifest_metadata`, range labels, or other fields are required. ()
- Presenters **_may_** implement `#homepage` to contain a hash for linking back to a repository webpage for this manifest. The hash must contain "id", "format" (mime type), "type", and "label" (eg. `{ "id" => "repository url", "format" => "text/html", "type" => "Text", "label" => { "en": ["View in repository"] }`).
- File set presenters may target a fragment of its content by providing `#media_fragment` which will be appended to its `id`.
- Range objects may now implement `#items` instead of `#ranges` and `#file_set_presenters` to allow for interleaving these objects. `#items` is not required and existing range objects should continue to work.
- 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`)
- `#annotation_content` which should return an instance of `IIIFManifest::V3::AnnotationContent` (or an array of instances in the case of a canvas having multiple annotations)
- `#display_image` is no longer required but will still work if provided
- `#sequence_rendering` is supported at leaf node level, to present an array of file downloads available at each leaf node
- `#part_of` is supported at leaf node level, to present an array of parent resources available at each leaf node.
- `#homepage` is supported at leaf node level, to present an array of homepage resources available at each leaf node.
- `#placeholder_content` which returns an instance of `IIIFManifest::V3::DisplayContent` presents a [`placeholderCanvas`](https://iiif.io/api/presentation/3.0/#placeholdercanvas) at leaf node level
- DisplayContent may provide `#auth_service` which should return a hash containing a IIIF Authentication service definition () that will be included on the content resource.## Configuration
The `label`, `rights`, `homepage`, `description` (V2 only), and `summary` (V3 only) properties can be configured to pull its information from different attributes.
**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.
To enable this, add the following code to a config file at `config/initializers/iiif_manifest_config.rb` in your application.
```ruby
# Example: use the default configuration but amend the summary property
IIIFManifest.config do |config|
config.manifest_property_to_record_method_name_map.merge!(summary: :abstract, rights: :license)
end
```
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.```ruby
# Example: use this configuration to set the max edge length of thumbnails, default is 200
IIIFManifest.confg do |config|
config.max_edge_for_thumbnail = 100
end
```
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.```ruby
# Example: use this configuration to disable thumbnails to show up by default on the manifest level (version 3 only)
IIIFManifest.confg do |config|
config.manifest_thumbnail = false
end
```
According to the Presentation API 3.0 [specifications](https://iiif.io/api/presentation/3.0/#thumbnail):
> A Manifest *SHOULD* have the `thumbnail` property with at least one item.The above configuration allows you to disable that if desired since it is not a *MUST*.
# Development
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.
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).
## Contributing
Bug reports and pull requests are welcome on GitHub at . 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.
If you're working on PR for this project, create a feature branch off of `main`.
This repository follows the [Samvera Community Code of Conduct](https://samvera.atlassian.net/wiki/spaces/samvera/pages/405212316/Code+of+Conduct) and [language recommendations](https://github.com/samvera/maintenance/blob/master/templates/CONTRIBUTING.md#language). Please ***do not*** create a branch called `master` for this repository or as part of your pull request; the branch will either need to be removed or renamed before it can be considered for inclusion in the code base and history of this repository.
## Help
The Samvera community is here to help. Please see our [support guide](./SUPPORT.md).
# Acknowledgments
This software has been developed by and is brought to you by the Samvera community. Learn more at the [Samvera website](http://samvera.org/).
![Samvera Logo](https://raw.githubusercontent.com/samvera/maintenance/main/assets/samvera_tree.png)