We can make the Readium toolkit simpler and safer to use by exposing a single encapsulated Publication, encompassing resources access and services.
For a given publication, we currently have several free-floating objects that a reading app needs to manipulate, such as DRMLicense, Fetcher/Container and Publication. This leads to a lot of housekeeping and fragile code in reading apps.
By exposing a single Publication object as the entry-point for everything related to the publication, we can:
The Publication object is the entry-point for all metadata and services related to a publication. You can use it to:
PublicationThe Publication object is usually created by the Readium toolkit, either from:
r2-streamer, when parsing a publication file, e.g. EPUB or PDFr2-opds, when parsing an OPDS publicationYou are free to create a Publication manually to fit custom needs.
Publication provides access to a publication’s metadata. You can use them, for example, to import a publication in the user’s bookshelf or to browse its table of contents.
database.addPublication({
"title": publication.metadata.title,
"authors": publication.metadata.authors
.map(author => author.name).join(", ")
})
Once you have a Link object targeting a resource, you can call Publication::get() to read it.
let coverLink = publication.linkWithRel("cover")
if (coverLink) {
let coverBytes = publication.get(coverLink).read()
}
To present the publication, create a navigator with the Publication object. It contains everything the navigator needs to render the publication.
While out of scope for this proposal, this example illustrates the feature-rich API we can get from an encapsulated Publication object.
Given a SearchService providing a Publication::search() helper, we can do:
let results = await publication.search("banana")
navigator.goTo(results[0])
This proposal should be a non-breaking change, since it is merely additive.
Container will be deprecated, and forward requests to Publication::get().Manifest ClassHolds the metadata of a Readium publication, as described in the Readium Web Publication Manifest.
Manifest(json: JSONObject)
Manifest(jsonString: String)
Manifest(json:).metadata: Metadata
links: List<Link>
subcollections: Map<String, List<Collection>>
readingOrder: List<Link>
resources: List<Link>
tableOfContents: List<Link>
The readingOrder, resources and tableOfContents properties may be implemented as computed properties using subcollections.
var readingOrder: [Link] {
subcollections["readingOrder"]?.firstOrNull?.links ?? []
}
toJSON() -> String
Publication ClassThe Publication shared model is the entry-point for all the metadata and services related to a Readium publication.
It is constructed from a group of objects with clear responsibilities:
Manifest which holds the metadata parsed from the source publication file/manifest.Fetcher which offers a read-only access to resources.Publication.Service objects which extend the Publication with features such as position list, search, thumbnails generation, rights management, etc.Publication(manifest: Manifest, fetcher: Fetcher = EmptyFetcher(), servicesBuilder: Publication.ServicesBuilder = Publication.ServicesBuilder())
manifest: Manifest
fetcher: Fetcher = EmptyFetcher()
Resource.Error.NotFound for all HREFs.servicesBuilder: Publication.ServicesBuilder = Publication.ServicesBuilder()
Publication.Service attached to this Publication.metadata, links, subcollections, readingOrder, resources and tableOfContents are delegated to the underlying Manifest.get(link: Link) -> Resource
Publication.Service returning a Resource for this Link, or falls back on fetcher.get().