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:
Publication
The 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()
.