Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
0da00e8
Improve LCP profiles detection (#857)
mickael-menu Jul 15, 2026
f123eef
Allow external Audio Session handling (#856)
svenmeyers89 Jul 15, 2026
afccc37
Store the auto-generated LCP device ID in the Keychain (#858)
mickael-menu Jul 15, 2026
d82f44f
3.11.0 (#862)
mickael-menu Jul 17, 2026
f75c344
Refactor public classes, structs, and enums to be Sendable (#761)
stevenzeck Apr 1, 2026
d93d29b
Refactor HTTP client (#764)
stevenzeck May 21, 2026
b7b11e5
Fix `FormatSniffer` for strict concurrency (#768)
stevenzeck May 23, 2026
e3454a8
Replace `AnyHashable` with `AnySendableHashable` (#772)
stevenzeck May 29, 2026
9a12961
Update `Logger` to be Swift 6 compliant (#798)
stevenzeck Jun 1, 2026
24d460c
Update Publication Services to be Swift 6 compliant (#769)
stevenzeck Jun 1, 2026
49cb4b4
Make `Streamable` and `Resource` protocols `Sendable` (#801)
stevenzeck Jun 2, 2026
305176a
Cleanup unused files and properties (#779)
grighakobian Jun 12, 2026
95d418b
Remove `Atomic` in favor of `Mutex` (#807)
grighakobian Jun 12, 2026
9fab0a4
Adopt `Sendable` across PDF, LCP and `Container` APIs (#803)
stevenzeck Jun 17, 2026
250cbad
Migrate media and utility types to Swift 6 concurrency (#808)
stevenzeck Jun 19, 2026
b1bce76
Fix HTTP streaming in Swift 6 (#819)
stevenzeck Jun 19, 2026
1393611
Migrate `ReadiumShared` to Swift 6 (#820)
grighakobian Jun 24, 2026
d4352c0
Remove deprecated APIs (#826)
mickael-menu Jun 24, 2026
5e5bf2f
Migrate `ReadiumStreamer` to Swift 6 (#828)
grighakobian Jun 24, 2026
6644f97
Fix `Sendable` conformance in `Mutex` (#827)
grighakobian Jun 24, 2026
2405d3a
Fix `Sendable` conformance for `Weak` type (#831)
grighakobian Jun 25, 2026
b2b55c6
Migrate `ReadiumLCP` to Swift 6 (#829)
stevenzeck Jun 26, 2026
fad57c3
Migrate `ReadiumOPDS` to Swift 6 (#830)
grighakobian Jul 1, 2026
566f3a6
Migrate `ReadiumNavigator` to Swift 6 (#832)
stevenzeck Jul 3, 2026
06d0a13
Remove the `sender` parameter from `PublicationOpener` and LCP APIs (…
grighakobian Jul 3, 2026
3d515f0
Fix LCP hashed-passphrase validation
mickael-menu Jul 3, 2026
621b367
Adopt Swift 6.2 approachable concurrency and harden the strict-concur…
mickael-menu Jul 12, 2026
7df24b7
Remove the `ReadiumInternal` package (#855)
mickael-menu Jul 14, 2026
e76d064
Replace DifferenceKit and CryptoSwift with native Swift code (#875)
stevenzeck Jul 31, 2026
1ace16c
Add missing `Sendable` conformances (#881)
mickael-menu Aug 6, 2026
1a14032
Generate the Playground project with XcodeGen and unify the dev workf…
stevenzeck Aug 7, 2026
cd2ff51
Add accessible name and description to content elements (#882)
mickael-menu Aug 10, 2026
abf343e
Add extended descriptions to content elements (#885)
mickael-menu Aug 12, 2026
ac839b4
Emit SVG elements wrapping a single image as image elements (#887)
mickael-menu Aug 13, 2026
32b6dcd
Explicitly define os and arch for xcodebuild (#888)
stevenzeck Aug 14, 2026
1b56d76
Fix delayed playback info updates in the audio navigator (#848)
stevenzeck Aug 14, 2026
c7e573c
4.0.0-alpha.1 (#889)
mickael-menu Aug 14, 2026
6691403
Fixed HTML media continuing to play after moving the resource off-scr…
mickael-menu Aug 26, 2026
dcca0e9
Make converting a `Link` to a `Locator` synchronous (#892)
mickael-menu Aug 28, 2026
dade0d2
Merge branch 'develop' into fix-issue-579
mauricecarrier7 Sep 9, 2026
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
  •  
  •  
  •  
160 changes: 89 additions & 71 deletions .github/workflows/checks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,112 +4,96 @@ on:
push:
branches: [ main, develop ]
pull_request:
types: [opened, synchronize, reopened, ready_for_review]
workflow_dispatch:

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

permissions:
contents: read

env:
platform: ${{ 'iOS Simulator' }}
device: ${{ 'iPhone 16 Pro' }}
platform: iOS Simulator
device: iPhone 17 Pro
os: latest
arch: arm64
commit_sha: ${{ github.sha }}
DEVELOPER_DIR: /Applications/Xcode_16.4.app/Contents/Developer
DEVELOPER_DIR: /Applications/Xcode_26.4.app/Contents/Developer

jobs:
build:
name: Build
runs-on: macos-15
runs-on: macos-26
if: ${{ !github.event.pull_request.draft }}
timeout-minutes: 60
env:
scheme: ${{ 'Readium-Package' }}
scheme: Readium-Package

steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v6
- name: Install dependencies
run: |
brew update
brew install xcodegen
# Preload the list of simulator for xcodebuild. The workflow is flaky without it.
xcrun simctl list
- name: Check CocoaPods podspecs
run: |
# Check that the podspecs are up to date.
make podspecs
git diff --exit-code Support/CocoaPods/
if git ls-files --others --exclude-standard Support/CocoaPods/ | grep -q .; then echo "Untracked podspec files found. Run 'make podspecs' and commit the result."; exit 1; fi
- name: Build
run: |
set -eo pipefail
xcodebuild build-for-testing -scheme "$scheme" -destination "platform=$platform,name=$device" | xcbeautify --renderer github-actions
xcodebuild build-for-testing -scheme "$scheme" -destination "platform=$platform,name=$device,OS=$os,arch=$arch" | xcbeautify --renderer github-actions
- name: Test
run: |
set -eo pipefail
xcodebuild test-without-building -scheme "$scheme" -destination "platform=$platform,name=$device" | xcbeautify --renderer github-actions
xcodebuild test-without-building -scheme "$scheme" -destination "platform=$platform,name=$device,OS=$os,arch=$arch" | xcbeautify --renderer github-actions
- name: Print Swift package versions
run: |
jq -r '.pins[] | "\(.identity): \(.state.version)"' Package.resolved

# navigator-ui-tests:
# name: Navigator UI Tests
# runs-on: macos-15
# if: ${{ !github.event.pull_request.draft }}
# steps:
# - name: Checkout
# uses: actions/checkout@v3
# - name: Install dependencies
# run: |
# brew update
# brew install xcodegen
# # Preload the list of simulator for xcodebuild. The workflow is flaky without it.
# xcrun simctl list
# - name: Test
# run: |
# set -eo pipefail
# make navigator-ui-tests-project
# xcodebuild test -project Tests/NavigatorTests/UITests/NavigatorUITests.xcodeproj -scheme NavigatorTestHost -destination "platform=$platform,name=$device" | xcbeautify --renderer github-actions
# Runs the test suite under the Thread Sanitizer to validate the
# `@unchecked Sendable` and `nonisolated(unsafe)` sites at runtime.
# Only runs on pushes to main/develop to keep pull requests light.
test-tsan:
name: Test (Thread Sanitizer)
runs-on: macos-26
if: github.event_name == 'push'
timeout-minutes: 60
env:
scheme: Readium-Package

playground:
name: Playground
runs-on: macos-15
if: ${{ !github.event.pull_request.draft }}
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v6
- name: Install dependencies
run: |
brew update
brew install xcodegen
# Preload the list of simulator for xcodebuild. The workflow is flaky without it.
xcrun simctl list
- name: Check Playground project is up-to-date
run: |
make playground
git diff --exit-code Playground/.xcodegen
- name: Build
- name: Test
run: |
set -eo pipefail
xcodebuild build -scheme Playground -project Playground/Playground.xcodeproj -destination "platform=$platform,name=$device" | xcbeautify --renderer github-actions
xcodebuild test -scheme "$scheme" -destination "platform=$platform,name=$device,OS=$os,arch=$arch" -enableThreadSanitizer YES | xcbeautify --renderer github-actions

lint:
name: Lint
runs-on: macos-15
runs-on: macos-26
if: ${{ !github.event.pull_request.draft }}
timeout-minutes: 60
env:
scripts: ${{ 'Sources/Navigator/EPUB/Scripts' }}
scripts: Sources/Navigator/EPUB/Scripts

steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v6
- name: Install pnpm
uses: pnpm/action-setup@v2
uses: pnpm/action-setup@v6
with:
package_json_file: Sources/Navigator/EPUB/Scripts/package.json
run_install: false
- name: Setup cache
uses: actions/setup-node@v3
uses: actions/setup-node@v6
with:
node-version: 20
node-version: 24
cache: 'pnpm'
cache-dependency-path: Sources/Navigator/EPUB/Scripts/pnpm-lock.yaml
- name: Install dependencies
Expand All @@ -122,44 +106,79 @@ jobs:
run: |
make scripts
git diff --exit-code --name-only Sources/Navigator/EPUB/Assets/Static/scripts/*.js
if git ls-files --others --exclude-standard Sources/Navigator/EPUB/Assets/Static/scripts/ | grep -q .; then echo "Untracked bundled scripts found. Run 'make scripts' and commit the result."; exit 1; fi
- name: Lint Swift formatting
run: make lint-format
- name: Check CocoaPods podspecs
run: |
# Check that the podspecs are up to date.
make podspecs
git diff --exit-code Support/CocoaPods/
if git ls-files --others --exclude-standard Support/CocoaPods/ | grep -q .; then echo "Untracked podspec files found. Run 'make podspecs' and commit the result."; exit 1; fi

int-dev:
name: Integration (Local)
runs-on: macos-15
runs-on: macos-26
if: ${{ !github.event.pull_request.draft }}
defaults:
run:
working-directory: TestApp
environment: LCP
timeout-minutes: 60
environment:
name: LCP
deployment: false
env:
# Empty for pull requests opened from a fork: GitHub never passes secrets
# to `pull_request` runs from forks. The LCP steps are skipped in that
# case, and the projects are generated without LCP.
LCP_URL_SPM: ${{ secrets.LCP_URL_SPM }}
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v6
- name: Install dependencies
run: |
brew update
brew install xcodegen
# Preload the list of simulator for xcodebuild. The workflow is flaky without it.
xcrun simctl list
- name: Generate project
run: make dev lcp=${{ secrets.LCP_URL_SPM }}
- name: Build
- name: Generate Playground project
run: make playground lcp="$LCP_URL_SPM"
- name: Build Playground
# Without the LCP secret we can't run the LCP tests, but we still check
# that the Playground compiles. With it, the test step below builds the
# Playground itself.
if: env.LCP_URL_SPM == ''
run: |
set -eo pipefail
xcodebuild build -scheme TestApp -destination "platform=$platform,name=$device" | xcbeautify --renderer github-actions
xcodebuild build -scheme Playground -project Playground/Playground.xcodeproj -destination "platform=$platform,name=$device,OS=$os,arch=$arch" | xcbeautify --renderer github-actions
- name: Test LCP
if: env.LCP_URL_SPM != ''
run: |
set -eo pipefail
xcodebuild test -scheme Playground -project Playground/Playground.xcodeproj -destination "platform=$platform,name=$device,OS=$os,arch=$arch" -only-testing:ReadiumLCPTests | xcbeautify --renderer github-actions
- name: Generate TestApp project
working-directory: TestApp
run: make dev lcp="$LCP_URL_SPM"
- name: Build TestApp
working-directory: TestApp
run: |
set -eo pipefail
xcodebuild build -scheme TestApp -destination "platform=$platform,name=$device,OS=$os,arch=$arch" | xcbeautify --renderer github-actions

int-spm:
name: Integration (Swift Package Manager)
runs-on: macos-15
runs-on: macos-26
if: ${{ !github.event.pull_request.draft }}
timeout-minutes: 60
defaults:
run:
working-directory: TestApp
environment: LCP
environment:
name: LCP
deployment: false
env:
# See the note in the `int-dev` job: this is empty for pull requests
# opened from a fork, in which case the project is generated without LCP.
LCP_URL_SPM: ${{ secrets.LCP_URL_SPM }}
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v6
# We can't use the current github.sha with pull_request event, because they will
# reference the merge commit which cannot be fetched with SPM.
- name: Set commit SHA
Expand All @@ -168,15 +187,14 @@ jobs:
echo "commit_sha=${{ github.event.pull_request.head.sha }}" >> "$GITHUB_ENV"
- name: Install dependencies
run: |
brew update
brew install xcodegen
# Preload the list of simulator for xcodebuild. The workflow is flaky without it.
xcrun simctl list
- name: Generate project
run: make spm lcp=${{ secrets.LCP_URL_SPM }} commit=$commit_sha
env:
LCP_URL_SPM: ${{ secrets.LCP_URL_SPM }}
run: make spm lcp="$LCP_URL_SPM" commit="$commit_sha"
- name: Build
run: |
set -eo pipefail
xcodebuild build -scheme TestApp -destination "platform=$platform,name=$device" | xcbeautify --renderer github-actions


xcodebuild build -scheme TestApp -destination "platform=$platform,name=$device,OS=$os,arch=$arch" | xcbeautify --renderer github-actions
55 changes: 46 additions & 9 deletions .github/workflows/docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,33 +16,68 @@ concurrency:

jobs:
build-and-deploy:
runs-on: macos-15
runs-on: macos-26
timeout-minutes: 60
steps:
- name: Checkout
uses: actions/checkout@v6
with:
fetch-depth: 0

# The workflow runs under two very different triggers:
#
# * `release: published` runs on the tag ref of the released version.
# The versioned folder is always deployed, and "latest" only for a
# stable release.
# * `workflow_dispatch` runs on a branch (usually `develop`), which is
# not a released version. Only "latest" is refreshed: deploying a
# versioned folder here would overwrite a published release with
# docs built from the tip of the branch.
- name: Determine Version
id: versioning
run: |
git fetch --tags --force
VERSION=$(git describe --tag --match "[0-9]*" --abbrev=0)
echo "READIUM_VERSION=$VERSION" >> $GITHUB_OUTPUT
if [[ $GITHUB_REF == refs/tags/* ]]; then
echo "folder=${GITHUB_REF#refs/tags/}" >> $GITHUB_OUTPUT
# Use the tag that triggered the workflow, not the latest one
# reachable from the checked-out ref.
VERSION="${GITHUB_REF#refs/tags/}"
echo "deploy_versioned=true" >> "$GITHUB_OUTPUT"
# A SemVer prerelease (e.g. 4.0.0-alpha.1) is identified by the "-"
# separating the prerelease identifiers from the version core.
# It only gets its versioned folder, as "latest" must keep
# advertising the current stable release.
if [[ $VERSION == *-* ]]; then
echo "deploy_latest=false" >> "$GITHUB_OUTPUT"
else
echo "deploy_latest=true" >> "$GITHUB_OUTPUT"
fi
else
echo "folder=latest" >> $GITHUB_OUTPUT
VERSION=$(git describe --tags --match "[0-9]*" --abbrev=0)
echo "deploy_versioned=false" >> "$GITHUB_OUTPUT"
echo "deploy_latest=true" >> "$GITHUB_OUTPUT"
fi
echo "READIUM_VERSION=$VERSION" >> "$GITHUB_OUTPUT"

# The docs are generated once per folder because the version is baked
# into the output (DocC --hosting-base-path and the 404/redirect pages
# embed /swift-toolkit/<version>/ URLs), so the "latest" site cannot be
# a plain copy of the versioned one.
#
# Each generate step is skipped when its folder is not deployed, as the
# script wipes .build and runs a full cross-compiled build every time.
- name: Generate Documentation
run: |
chmod +x scripts/generate-docs.sh
./scripts/generate-docs.sh ${{ steps.versioning.outputs.READIUM_VERSION }}
./scripts/generate-docs.sh latest
if: steps.versioning.outputs.deploy_versioned == 'true'
run: ./scripts/generate-docs.sh ${{ steps.versioning.outputs.READIUM_VERSION }}

- name: Generate Latest Documentation
if: steps.versioning.outputs.deploy_latest == 'true'
run: ./scripts/generate-docs.sh latest

# The generate steps create this directory tree, but they are both
# conditional, so make sure it exists before writing into it.
- name: Setup Root Redirect
run: |
mkdir -p docs-site/swift-toolkit
cat <<EOF > docs-site/swift-toolkit/index.html
<!DOCTYPE html>
<html>
Expand All @@ -56,6 +91,7 @@ jobs:
EOF

- name: Deploy Versioned Folder 🚀
if: steps.versioning.outputs.deploy_versioned == 'true'
uses: JamesIves/github-pages-deploy-action@v4
with:
branch: gh-pages
Expand All @@ -64,6 +100,7 @@ jobs:
clean: true

- name: Deploy Latest Folder 🚀
if: steps.versioning.outputs.deploy_latest == 'true'
uses: JamesIves/github-pages-deploy-action@v4
with:
branch: gh-pages
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -59,3 +59,6 @@ out/
# DocC generation
.build-docs
docs-site

/Support/Readium.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
/Support/R2LCPClient/
Loading