You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: Documentation/Guides/Getting Started.md
+56-38Lines changed: 56 additions & 38 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -16,9 +16,9 @@ The toolkit has been designed following these core tenets:
16
16
17
17
### Main packages
18
18
19
-
*`R2Shared` contains shared `Publication` models and utilities.
20
-
*`R2Streamer` parses publication files (e.g. an EPUB) into a `Publication` object.
21
-
*[`R2Navigator` renders the content of a publication](Navigator/Navigator.md).
19
+
*`ReadiumShared` contains shared `Publication` models and utilities.
20
+
*`ReadiumStreamer` parses publication files (e.g. an EPUB) into a `Publication` object.
21
+
*[`ReadiumNavigator` renders the content of a publication](Navigator/Navigator.md).
22
22
23
23
### Specialized packages
24
24
@@ -30,7 +30,7 @@ The toolkit has been designed following these core tenets:
30
30
*`ReadiumAdapterGCDWebServer` provides an HTTP server built with [GCDWebServer](https://github.com/swisspol/GCDWebServer).
31
31
*`ReadiumAdapterLCPSQLite` provides implementations of the `ReadiumLCP` license and passphrase repositories using [SQLite.swift](https://github.com/stephencelis/SQLite.swift).
32
32
33
-
## Overview of the shared models (`R2Shared`)
33
+
## Overview of the shared models (`ReadiumShared`)
34
34
35
35
The Readium toolkit provides models used as exchange types between packages.
36
36
@@ -48,7 +48,6 @@ A `Publication` instance:
48
48
49
49
#### Link
50
50
51
-
52
51
A [`Link` object](https://readium.org/webpub-manifest/#24-the-link-object) holds a pointer (URL) to a resource or service along with additional metadata, such as its media type or title.
53
52
54
53
The `Publication` contains several `Link` collections, for example:
@@ -70,68 +69,87 @@ A [`Locator` object](https://readium.org/architecture/models/locators/) represen
70
69
71
70
### Data models
72
71
73
-
#### Publication Asset
72
+
#### Asset
74
73
75
-
A `PublicationAsset` is an interface representing a single file or package holding the content of a `Publication`. A default implementation `FileAsset` grants access to a publication stored locally.
74
+
An `Asset` represents a single file or package and provides access to its content. There are two types of `Asset`:
76
75
77
-
#### Resource
76
+
*`ContainerAsset` for packages which contains several resources, such as a ZIP archive.
77
+
*`ResourceAsset` for accessing a single resource, such as a JSON or PDF file.
78
78
79
-
A `Resource` provides read access to a single resource of a publication, such as a file or an entry in an archive.
79
+
`Asset` instances are obtained through an `AssetRetriever`.
80
80
81
-
`Resource` instances are usually created by a `Fetcher`. The toolkit ships with various implementations supporting different data access protocols such as local files, HTTP, etc.
81
+
You can use the `asset.format` to identify the media type and capabilities of the asset.
82
82
83
-
#### Fetcher
83
+
```swift
84
+
if asset.format.conformsTo(.lcp) {
85
+
// The asset is protected with LCP.
86
+
}
87
+
if asset.format.conformsTo(.epub) {
88
+
// The asset represents an EPUB publication.
89
+
}
90
+
```
84
91
85
-
A `Fetcher` provides read access to a collection of resources. `Fetcher` instances are created by a `PublicationAsset` to provide access to the content of a publication.
92
+
#### Resource
86
93
87
-
`Publication` objects internally use a `Fetcher` to expose their content.
94
+
A `Resource` provides read access to a single resource, such as a file or an entry in an archive.
88
95
89
-
## Opening a publication (`R2Streamer`)
96
+
`Resource` instances are usually created by a `ResourceFactory`. The toolkit ships with various implementations supporting different data access protocols such as local files or HTTP.
90
97
91
-
To retrieve a `Publication` object from a publication file like an EPUB or audiobook, begin by creating a `PublicationAsset` object used to read the file. Readium provides a `FileAsset` implementation for reading a publication stored on the local file system.
98
+
#### Container
92
99
93
-
```swift
94
-
let file =URL(fileURLWithPath: "path/to/book.epub")
95
-
let asset =FileAsset(file: file)
96
-
```
100
+
A `Container` provides read access to a collection of resources. `Container` instances representing an archive are usually created by an `ArchiveOpener`. The toolkit ships with a `ZIPArchiveOpener` supporting local ZIP files.
101
+
102
+
`Publication` objects internally use a `Container` to expose its content.
103
+
104
+
## Opening a publication (`ReadiumStreamer`)
97
105
98
-
Then, use a `Streamer` instance to parse the asset and create a `Publication` object.
106
+
To retrieve a `Publication` object from a publication file like an EPUB or audiobook, you can use an `AssetRetriever` and `PublicationOpener`.
99
107
100
108
```swift
101
-
let streamer =Streamer()
109
+
// Instantiate the required components.
110
+
let httpClient =DefaultHTTPClient()
111
+
let assetRetriever =AssetRetriever(
112
+
httpClient: httpClient
113
+
)
114
+
let publicationOpener =PublicationOpener(
115
+
publicationParser: DefaultPublicationParser(
116
+
httpClient: httpClient,
117
+
assetRetriever: assetRetriever,
118
+
pdfFactory: DefaultPDFDocumentFactory()
119
+
)
120
+
)
121
+
122
+
let url: URL =URL(...)
102
123
103
-
streamer.open(asset: asset, allowUserInteraction: false) { result in
104
-
switch result {
124
+
// Retrieve an `Asset` to access the file content.
// The user cancelled the opening, for example by dismissing a password pop-up.
111
-
break
133
+
// Failed to access or parse the publication
112
134
}
135
+
136
+
case .failure(let error):
137
+
// Failed to retrieve the asset
113
138
}
114
139
```
115
140
116
141
The `allowUserInteraction` parameter is useful when supporting a DRM like Readium LCP. It indicates if the toolkit can prompt the user for credentials when the publication is protected.
117
142
143
+
[See the dedicated user guide for more information](Open%20Publication.md).
144
+
118
145
## Accessing the metadata of a publication
119
146
120
147
After opening a publication, you may want to read its metadata to insert a new entity into your bookshelf database, for instance. The `publication.metadata` object contains everything you need, including `title`, `authors` and the `published` date.
121
148
122
-
You can retrieve the publication cover using `publication.cover`. Avoid calling this from the main thread to prevent blocking the user interface.
149
+
You can retrieve the publication cover using `await publication.cover()`.
123
150
124
-
## Rendering the publication on the screen (`R2Navigator`)
151
+
## Rendering the publication on the screen (`ReadiumNavigator`)
125
152
126
153
You can use a Readium navigator to present the publication to the user. The `Navigator` renders resources on the screen and offers APIs and user interactions for navigating the contents.
To open a publication with Readium, you need to instantiate a couple of components: an `AssetRetriever` and a `PublicationOpener`.
4
+
5
+
## `AssetRetriever`
6
+
7
+
The `AssetRetriever` grants access to the content of an asset located at a given URL, such as a publication package, manifest, or LCP license.
8
+
9
+
### Constructing an `AssetRetriever`
10
+
11
+
You can create an instance of `AssetRetriever` with:
12
+
13
+
* An `HTTPClient` to enable the toolkit to perform HTTP requests and support the `http` and `https` URL schemes. You can use `DefaultHTTPClient` which provides callbacks for handling authentication when needed.
14
+
15
+
```swift
16
+
let assetRetriever =AssetRetriever(httpClient: DefaultHTTPClient())
17
+
```
18
+
19
+
### Retrieving an `Asset`
20
+
21
+
With your fresh instance of `AssetRetriever`, you can open an `Asset` from any `AbsoluteURL`.
22
+
23
+
```swift
24
+
// From a local file.
25
+
let url =FileURL(string: "file:///path/to/book.epub")
26
+
// or from an HTTP URL.
27
+
let url =HTTPURL(string: "https://domain/book.epub")
28
+
29
+
switchawait assetRetriever.retrieve(url: url) {
30
+
case .success(let asset):
31
+
...
32
+
case .failure(let error):
33
+
// Failed to retrieve the asset.
34
+
}
35
+
```
36
+
37
+
The `AssetRetriever` will sniff the media type of the asset, which you can store in your bookshelf database to speed up the process next time you retrieve the `Asset`. This will improve performance, especially with HTTP URL schemes.
38
+
39
+
```swift
40
+
let mediaType = asset.format.mediaType
41
+
42
+
// Speed up the retrieval with a known media type.
43
+
let result =await assetRetriever.retrieve(url: url, mediaType: mediaType)
44
+
```
45
+
46
+
## `PublicationOpener`
47
+
48
+
`PublicationOpener` builds a `Publication` object from an `Asset` using:
49
+
50
+
* A `PublicationParser` to parse the asset structure and publication metadata.
51
+
* The `DefaultPublicationParser` handles all the formats supported by Readium out of the box.
52
+
* An optional list of `ContentProtection` to decrypt DRM-protected publications.
53
+
* If you support Readium LCP, you can get one from the `LCPService`.
Now that you have a `PublicationOpener` ready, you can use it to create a `Publication` from an `Asset` that was previously obtained using the `AssetRetriever`.
70
+
71
+
The `allowUserInteraction` parameter is useful when supporting Readium LCP. When enabled and using a `LCPDialogAuthentication`, the toolkit will prompt the user if the passphrase is missing.
72
+
73
+
```swift
74
+
let result =await readium.publicationOpener.open(
75
+
asset: asset,
76
+
allowUserInteraction: true,
77
+
sender: sender
78
+
)
79
+
```
80
+
81
+
## Supporting additional formats or URL schemes
82
+
83
+
`DefaultPublicationParser` accepts additional parsers. You also have the option to use your own parser list by using `CompositePublicationParser` or create your own `PublicationParser` for a fully customized parsing resolution strategy.
84
+
85
+
The `AssetRetriever` offers an additional constructor that provides greater extensibility options, using:
86
+
87
+
*`ResourceFactory` which handles the URL schemes through which you can access content.
88
+
*`ArchiveOpener` which determines the types of archives (ZIP, RAR, etc.) that can be opened by the `AssetRetriever`.
89
+
*`FormatSniffer` which identifies the file formats that `AssetRetriever` can recognize.
90
+
91
+
You can use either the default implementations or implement your own for each of these components using the composite pattern. The toolkit's `CompositeResourceFactory`, `CompositeArchiveOpener`, and `CompositeFormatSniffer` provide a simple resolution strategy.
Copy file name to clipboardExpand all lines: Documentation/Migration Guide.md
+65-3Lines changed: 65 additions & 3 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -4,11 +4,64 @@ All migration steps necessary in reading apps to upgrade to major versions of th
4
4
5
5
## Unreleased
6
6
7
-
### Async APIs
7
+
### Opening a `Publication`
8
8
9
-
Plenty of completion-based APIs were changed to use `async` functions instead. Follow the deprecation warnings to update your codebase.
9
+
The `Streamer` object has been deprecated in favor of components with smaller responsibilities:
10
10
11
-
### Readium LCP SQLite adapter
11
+
*`AssetRetriever` grants access to the content of an asset located at a given URL, such as a publication package, manifest, or LCP license
12
+
*`PublicationOpener` uses a publication parser and a set of content protections to create a `Publication` object from an `Asset`.
13
+
14
+
[See the user guide for a detailed explanation on how to use these new APIs](Guides/Open%20Publication.md).
15
+
16
+
### Typed URLs
17
+
18
+
The toolkit now includes a new set of URL types (`RelativeURL`, `AbsoluteURL`, `FileURL`, `HTTPURL`, etc.). These new types ensure that you only pass URLs supported by our APIs.
19
+
20
+
You can create an instance of such `URL` from its string representation:
21
+
22
+
```swift
23
+
FileURL(string: "file:///path/to%20a%20file")
24
+
FileURL(path: "/path/to a file")
25
+
HTTPURL(string: "https://domain.com/file")
26
+
```
27
+
28
+
Or convert an existing Foundation `URL`:
29
+
30
+
```swift
31
+
let url: URL
32
+
url.fileURL
33
+
url.httpURL
34
+
```
35
+
36
+
### Sniffing a `Format`
37
+
38
+
`MediaType` no longer has static helpers for sniffing it from a file or URL. Instead, you can use an `AssetRetriever` to retrieve the format of a file.
39
+
40
+
```swift
41
+
let assetRetriever =AssetRetriever(httpClient: DefaultHTTPClient())
// Failed to access the asset or recognize its format
48
+
}
49
+
```
50
+
51
+
The `MediaType` struct has been simplified. It now only holds the actual media type string. The name has been removed, and the file extension has been moved to `Format`.
52
+
53
+
### Navigator
54
+
55
+
All the navigator `go` APIs are now asynchronous and take an `options` argument instead of the `animated` boolean.
The Readium LCP persistence layer was extracted to allow applications to provide their own implementations. The previous implementation is now part of a new package, `ReadiumAdapterLCPSQLite`, which you need to use to maintain the same behavior as before.
14
67
@@ -38,6 +91,15 @@ let lcpService = LCPService(
38
91
)
39
92
```
40
93
94
+
#### Introducing `LicenseDocumentSource`
95
+
96
+
The LCP APIs now accept a `LicenseDocumentSource` enum instead of a URL to an LCPL file. This approach is more flexible, as it doesn't require the LCPL file to be stored on the file system.
0 commit comments