phil / epub
EPUB 3 in PHP: package document with accessibility metadata, navigation with table of contents, landmarks and page list, EPUB 2 toc.ncx, well-formed XHTML from purified HTML, stylesheets, images, obfuscated fonts and cover, audio and video with fallbacks, media overlays, fixed layout, and UJO docume
Requires
- php: >=8.5
- ext-dom: *
- ext-zip: *
Requires (Dev)
- phil/ujo: ^0.1@dev
- phpunit/phpunit: ^13.4
- symfony/process: ^8.2
Suggests
- phil/ujo: To write UJO documents (Universal JSON Output, a block document format) as chapters
Provides
None
Conflicts
None
Replaces
None
This package is auto-updated.
Last update: 2026-11-13 22:45:55 UTC
README
EPUB 3 books from the HTML you already have, valid for EPUBCheck and readable by assistive technologies.
phil/epub writes EPUB 3 publications. It takes chapters as fragments of purified HTML, turns them into well-formed
XHTML content documents, and packages them with their stylesheets, images and fonts: the package document with its
metadata — title, language, identifiers, creators, modification time — and its schema.org accessibility metadata, the
navigation document with its table of contents, landmarks and page list, the EPUB 2 table of contents when asked, the
manifest and the spine, a cover, audio and video files with their fallbacks and text tracks, media overlays that read
the text aloud in sync, fixed-layout pages, fonts obfuscated with the IDPF algorithm when asked, and the ZIP container
with its mimetype first and stored. Links that
cross chapters are rewritten to the chapter that holds their target, and addresses the book does not hold are dropped
rather than left broken.
It is for any PHP application that publishes long texts and wants them read offline, in a reading application or on an
e-reader: a CMS exporting a series of articles, a tool that lays out game books, a wiki exporting a section, a
newsletter archive. A book is written in one call, in memory or to a file, and the same book gives the same bytes. An
application that stores documents in UJO (Universal JSON Output), the block document format of phil/ujo, turns them
into chapters through phil/ujo.
It is a plain PHP library that needs PHP's dom and zip extensions and nothing else;
phil/ujo is an optional dependency. The EPUB 3.3 specification, EPUB Accessibility 1.1 and the IDPF font
obfuscation algorithm are its references; no code of another EPUB library is used.
The design is small: a Book holds its Metadata (with an Accessibility value), its Chapter list — each with its
MediaOverlay when narrated —, its Asset files, its Cover and its Rendition; EpubWriter writes it.
HtmlSplitter cuts a long fragment into chapters at its headings, and Ujo\UjoChapters does the same with a UJO
document, its page breaks becoming the page list.
Status
| Part | State |
|---|---|
Container, mimetype first and stored, entries dated by the modification time, reproducible bytes |
Implemented and tested |
| Package document: title, language, identifiers (UUID, ISBN-13, DOI, URN, own), creators and contributors with MARC roles, publisher, description, date, subjects, rights, source, modification time, direction | Implemented and tested |
| Accessibility metadata: access modes, sufficient modes, features, hazards, summary, conformance, certifier, with what the writer knows added | Implemented and tested |
| Navigation document: table of contents from the headings or given, landmarks, page list | Implemented and tested |
EPUB 2 table of contents (toc.ncx) with its page list, for older reading systems |
Implemented and tested |
| XHTML from purified HTML: parsed as HTML5, written as XML, SVG and MathML in their namespace, scripts and handlers removed, identifiers deduplicated | Implemented and tested |
| Links across chapters, resources checked against the book, addresses mapped by the application, remote audio and video | Implemented and tested |
| Stylesheets, images and fonts in EPUB core media types, read from their bytes; font obfuscation; cover | Implemented and tested |
| Audio and video files inside the book, read from their bytes, with manifest fallbacks; WebVTT text tracks | Implemented and tested |
| Media overlays: SMIL documents, durations, narrators and active classes in the package document | Implemented and tested |
| Fixed layout: pre-paginated books or chapters, viewport per page, orientation, spread and page spread | Implemented and tested |
Chapters split at headings; UJO documents through phil/ujo with page breaks as page list |
Implemented and tested |
| Output checked by EPUBCheck 5.4 | Tested when EPUBCheck is installed |
Documentation
| Document | What it covers |
|---|---|
| Installation | Requirements and installing. |
| Books | Book, Metadata, identifiers, creators, chapters, assets, the cover and font obfuscation. |
| Accessibility | The accessibility metadata, what the writer adds, and what makes the content accessible. |
| Content documents | How HTML becomes XHTML, links and resources, mapping addresses, and splitting a fragment into chapters. |
| Navigation | The table of contents, the landmarks, the page list, their labels and the EPUB 2 table of contents. |
| Media, overlays and layout | Audio, video and text tracks, fallbacks, media overlays, and fixed layout. |
| UJO documents | UjoChapters: a UJO document rendered by phil/ujo and split into chapters with its pages. |
| Exceptions | EpubException and its two exceptions. |
| Extension points | The ports, arguments and data an application chooses or replaces. |
| Testing | The library's tests, EPUBCheck, the mutation bar, and how to test code that writes books. |
| Reference | Every type of the library, with its role. |
Quick start
composer require phil/epub
use Phil\Epub\Asset; use Phil\Epub\Book; use Phil\Epub\Chapter; use Phil\Epub\Creator; use Phil\Epub\EpubWriter; use Phil\Epub\Identifier; use Phil\Epub\Metadata; $book = new Book(new Metadata( 'The Lighthouse Keeper', 'en', Identifier::uuid('7c9e6679-7425-40de-944b-e07fc1f90ae7'), new DateTimeImmutable(), creators: [new Creator('Ann Writer', 'aut')], )) ->withAsset(Asset::stylesheet('css/book.css', 'body { line-height: 1.5; }')) ->withChapter( new Chapter('<h1>The Storm</h1><p>The light went out at midnight.</p>'), new Chapter('<h1>The Morning</h1><p>See <a href="#the-boat">the boat</a>.</p><h2 id="the-boat">The Boat</h2>'), ); new EpubWriter()->write($book, 'lighthouse.epub');
Requirements
PHP 8.5 or later, with the dom and zip extensions. phil/ujo for UJO documents.
Contributing
Contributions are welcome on the PHIL monorepo: read the contribution guide and the code of conduct. Report a vulnerability privately, as the security policy explains, never in a public issue.
License
MIT, © Philippe Gamache, doing business as Le Gnome Archiviste; a Parler Haut Interagir Librement project. See LICENSE.