Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
16 changes: 8 additions & 8 deletions .github/workflows/checks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,17 @@ on:

env:
platform: ${{ 'iOS Simulator' }}
device: ${{ 'iPhone 12' }}
device: ${{ 'iPhone 15' }}
commit_sha: ${{ github.sha }}
DEVELOPER_DIR: /Applications/Xcode_15.0.1.app/Contents/Developer

jobs:
build:
name: Build
runs-on: macos-12
runs-on: macos-13
if: ${{ !github.event.pull_request.draft }}
env:
scheme: ${{ 'Readium-Package' }}
DEVELOPER_DIR: /Applications/Xcode_13.4.1.app/Contents/Developer

steps:
- name: Checkout
Expand All @@ -42,7 +42,7 @@ jobs:

lint:
name: Lint
runs-on: macos-12
runs-on: macos-13
if: ${{ !github.event.pull_request.draft }}
env:
scripts: ${{ 'Sources/Navigator/EPUB/Scripts' }}
Expand Down Expand Up @@ -76,7 +76,7 @@ jobs:

int-dev:
name: Integration (Local)
runs-on: macos-12
runs-on: macos-13
if: ${{ !github.event.pull_request.draft }}
defaults:
run:
Expand All @@ -98,7 +98,7 @@ jobs:

int-spm:
name: Integration (Swift Package Manager)
runs-on: macos-12
runs-on: macos-13
if: ${{ !github.event.pull_request.draft }}
defaults:
run:
Expand Down Expand Up @@ -126,7 +126,7 @@ jobs:

int-carthage:
name: Integration (Carthage)
runs-on: macos-12
runs-on: macos-13
if: ${{ !github.event.pull_request.draft }}
defaults:
run:
Expand Down Expand Up @@ -157,7 +157,7 @@ jobs:
int-cocoapods:
name: Integration (CocoaPods)
if: github.event_name == 'push'
runs-on: macos-12
runs-on: macos-13
defaults:
run:
working-directory: TestApp
Expand Down
18 changes: 18 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,23 @@ All notable changes to this project will be documented in this file. Take a look

<!-- ## [Unreleased] -->

## [3.0.0-alpha.1]

### Changed

* The `R2Shared`, `R2Streamer` and `R2Navigator` packages are now called `ReadiumShared`, `ReadiumStreamer` and `ReadiumNavigator`.
* Many APIs now expect one of the new URL types (`RelativeURL`, `AbsoluteURL`, `HTTPURL` and `FileURL`). This is helpful because:
* It validates at compile time that we provide a URL that is supported.
* The API's capabilities are better documented, e.g. a download API could look like this : `download(url: HTTPURL) -> FileURL`.

#### Shared

* `Link` and `Locator`'s `href` are normalized as valid URLs to improve interoperability with the Readium Web toolkits.
* **You MUST migrate your database if you were persisting HREFs and Locators**. Take a look at [the migration guide](Documentation/Migration%20Guide.md) for guidance.
* Links are not resolved to the `self` URL of a manifest anymore. However, you can still normalize the HREFs yourselves by calling `Manifest.normalizeHREFsToSelf()`.
* `Publication.localizedTitle` is now optional, as we cannot guarantee a publication will always have a title.


## [2.7.1]

### Added
Expand Down Expand Up @@ -672,3 +689,4 @@ progression. Now if no reading progression is set, the `effectiveReadingProgress
[2.6.1]: https://github.com/readium/swift-toolkit/compare/2.6.0...2.6.1
[2.7.0]: https://github.com/readium/swift-toolkit/compare/2.6.1...2.7.0
[2.7.1]: https://github.com/readium/swift-toolkit/compare/2.7.0...2.7.1
[3.0.0-alpha.1]: https://github.com/readium/swift-toolkit/compare/2.7.1...3.0.0-alpha.1
24 changes: 24 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Contributing to the Readium Swift Toolkit

First and foremost, thanks for your interest! 🙏 We need contributors like you to help bring this project to fruition.

We welcome many kind of contributions such as improving the documentation, submitting bug reports and feature requests, or writing code.

## Writing code

### Coding standard

We use [`SwiftFormat`](https://github.com/nicklockwood/SwiftFormat) to ensure code formatting and avoid bikeshedding.

Before submitting a PR, save yourself some trouble by automatically formatting the code with `make format` from the project's root directory.

### Modifying the EPUB Navigator's JavaScript layer

The EPUB navigator injects a set of JavaScript files into a publication's resources, exposing a JavaScript API to the `WKWebView` under the `readium` global namespace. The JavaScript source code is located under [`Sources/Navigator/EPUB/Scripts`](Sources/Navigator/EPUB/Scripts).

`index-reflowable.js` is the root of the bundle injected in a reflowable EPUB's resources, while `index-fixed.js` is used for a fixed-layout EPUB's resources.

In the case of fixed-layout EPUBs, the publication resources are actually loaded inside an `iframe` in one of [our HTML wrapper pages](Sources/Navigator/EPUB/Assets/) (`fxl-spread-one.html` for single pages, `fxl-spread-two.html` when displaying two pages side-by-side). The matching `index-fixed-wrapper-one.js` and `index-fixed-wrapper-two.js` are injected in the HTML wrappers.

If you make any changes to the JavaScript files, you must regenerate the bundles embedded in the application. First, make sure you have [`corepack` installed](https://pnpm.io/installation#using-corepack). Then, run `make scripts` from the project's root directory.

136 changes: 136 additions & 0 deletions Documentation/Guides/Getting Started.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
# Getting started

The Readium Swift toolkit enables you to develop reading apps for iOS and iPadOS. It provides built-in support for multiple publication formats such as EPUB, PDF, audiobooks, and comics.

:warning: Readium offers only low-level tools. You are responsible for creating a user interface for reading and managing books, as well as a data layer to store the user's publications. The Test App is an example of such integration.

## Design principles

The toolkit has been designed following these core tenets:

* **Modular**: It is divided into separate modules that can be used independently.
* **Extensible**: Integrators should be able to support a custom DRM, publication format or inject their own stylesheets without modifying the toolkit itself.
* **Opiniated**: We adhere to open standards but sometimes interpret them for practicality.

## Packages

### Main packages

* `R2Shared` contains shared `Publication` models and utilities.
* `R2Streamer` parses publication files (e.g. an EPUB) into a `Publication` object.
* [`R2Navigator` renders the content of a publication](Navigator/Navigator.md).

### Specialized packages

* `ReadiumOPDS` parses [OPDS catalog feeds](https://opds.io) (both OPDS 1 and 2).
* [`ReadiumLCP` downloads and decrypts LCP-protected publications](Readium%20LCP.md).

### Adapters to third-party dependencies

* `ReadiumAdapterGCDWebServer` provides an HTTP server built with [GCDWebServer](https://github.com/swisspol/GCDWebServer).

## Overview of the shared models (`R2Shared`)

The Readium toolkit provides models used as exchange types between packages.

### Publication models

#### Publication

`Publication` and its sub-components represent a single publication – ebook, audiobook or comic. It is loosely based on the [Readium Web Publication Manifest](https://readium.org/webpub-manifest/).

A `Publication` instance:

* holds the metadata of a publication, such as its author or table of contents,
* allows to read the contents of a publication, e.g. XHTML or audio resources,
* provides additional services, for example content extraction or text search.

#### Link


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.

The `Publication` contains several `Link` collections, for example:

* `readingOrder` lists the publication resources arranged in the order they should be read.
* `resources` contains secondary resources necessary for rendering the `readingOrder`, such as an image or a font file.
* `tableOfContents` represents the table of contents as a tree of `Link` objects.
* `links` exposes additional resources, such as a canonical link to the manifest or a search web service.

#### Locator

A [`Locator` object](https://readium.org/architecture/models/locators/) represents a precise location in a publication resource in a format that can be stored and shared across reading systems. It is more accurate than a `Link` and contains additional information about the location, e.g. progression percentage, position or textual context.

`Locator` objects are used for various features, including:

* reporting the current progression in the publication
* saving bookmarks, highlights and annotations
* navigating search results

### Data models

#### Publication Asset

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.

#### Resource

A `Resource` provides read access to a single resource of a publication, such as a file or an entry in an archive.

`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.

#### Fetcher

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.

`Publication` objects internally use a `Fetcher` to expose their content.

## Opening a publication (`R2Streamer`)

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.

```swift
let file = URL(fileURLWithPath: "path/to/book.epub")
let asset = FileAsset(file: file)
```

Then, use a `Streamer` instance to parse the asset and create a `Publication` object.

```swift
let streamer = Streamer()

streamer.open(asset: asset, allowUserInteraction: false) { result in
switch result {
case .success(let publication):
print("Opened \(publication.metadata.title)")
case .failure(let error):
alert(error.localizedDescription)
case .cancelled:
// The user cancelled the opening, for example by dismissing a password pop-up.
break
}
}
```

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.

## Accessing the metadata of a publication

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.

You can retrieve the publication cover using `publication.cover`. Avoid calling this from the main thread to prevent blocking the user interface.

## Rendering the publication on the screen (`R2Navigator`)

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.

```swift
let navigator = try EPUBNavigatorViewController(
publication: publication,
initialLocation: lastReadLocation,
httpServer: GCDHTTPServer.shared
)

hostViewController.present(navigator, animated: true)
```
Please refer to the [Navigator guide](Navigator/Navigator.md) for more information.
Loading