Download the PHP package adrorocker/epub-builder without Composer
On this page you can find all versions of the php package adrorocker/epub-builder. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.
Download adrorocker/epub-builder
More information about adrorocker/epub-builder
Files in adrorocker/epub-builder
Package epub-builder
Short Description Convert Tiptap JSON to valid EPUB 3.3 files with an injectable renderer interface
License MIT
Informations about the package epub-builder
adrorocker/epub-builder
Convert Tiptap JSON documents into valid EPUB 3.3 files. Framework-agnostic, zero runtime dependencies, with an injectable renderer interface so you can plug in your own Tiptap-to-XHTML logic.
- Spec-conformant: passes the W3C reference validator (EPUBCheck 5.x) with 0 errors / 0 warnings.
- Cross-reader: tested against Apple Books, calibre, and the EPUBCheck reference. Ships an EPUB 2 NCX fallback for legacy readers (older Kindle apps, ADE pre-v4).
- Tiptap-native: a default renderer covers the standard Tiptap node and mark set. Custom Tiptap nodes can be registered with a one-line handler.
- No third-party runtime deps: only PHP 8.1+ and the
zipanddomextensions.
Installation
Requirements: PHP 8.1+, ext-zip, ext-dom.
Quick start
That's a complete, valid EPUB. Open in any reader.
Metadata
All metadata is set through a fluent builder. Title, language, and at least one chapter are required; everything else is optional.
MARC relator codes
contributor() takes an optional second argument — a MARC relator code describing the contributor's role. Common ones:
| Code | Role |
|---|---|
trl |
Translator |
edt |
Editor |
ill |
Illustrator |
pht |
Photographer |
aui |
Introduction |
aft |
Afterword |
fwd |
Foreword |
cmp |
Compiled by |
nrt |
Narrated by |
oth |
Other (default) |
These codes are emitted into the OPF and translated to readable labels ("Translated by", "Edited by", …) on the auto-generated cover page.
Chapters
Each call to addChapter(string $title, array $tiptapJson) adds one chapter:
- The title becomes the chapter's
<h1>and a top-level entry in the table of contents. - The Tiptap JSON is rendered to XHTML using the default renderer (or a custom one — see below).
- Inner Tiptap headings nest under the chapter title in the TOC.
- The chapter is auto-registered as a page in the EPUB 3 page-list nav (so readers can show "page N of M"). Disable with
->disableAutoPageList(). - The chapter body is wrapped in
<section epub:type="chapter">for accessibility.
Cover page
When you set a cover image, the library auto-generates a title page (OEBPS/chapters/cover.xhtml) showing:
- The cover image, full-bleed
- The book title (large, centered)
- Authors ("by Robert Frost & Jane Doe")
- Contributors with role labels ("Translated by Constance Garnett")
- Publisher
- Year
- Rights / copyright line
- Description (justified, smaller text)
This is rendered XHTML, so it shows up the same in every reader — even readers that don't surface OPF metadata in their library/info UIs.
The cover is automatically:
- Added to the OPF manifest with
properties="cover-image"(EPUB 3) and<meta name="cover">(EPUB 2 legacy). - Placed first in the spine with
linear="no"so it appears as cover artwork only, not as the first reading-flow page. - Added to the EPUB 3 landmarks nav and the legacy
<guide>block.
Output
build() returns an EpubOutput value object:
If you don't pass a path to build(), it writes to sys_get_temp_dir() with a random name.
Streaming without keeping a file
When you don't want a file at all — e.g. you're piping the EPUB straight into an HTTP response or an S3 upload — use buildToStream() or buildToString(). They use a temp file internally and delete it once the bytes are out.
Laravel
Or stream without staging the file in your storage directory:
Symfony
Streaming variant via StreamedResponse:
Custom Tiptap nodes
The default renderer ships handlers for the standard Tiptap node and mark set:
Nodes: doc, paragraph, heading, blockquote, codeBlock, bulletList, orderedList, listItem, horizontalRule, hardBreak, image, table, tableRow, tableCell, tableHeader, text, pageBreak
Marks: bold, italic, underline, strike, code, link, highlight, subscript, superscript
Unknown nodes are silently dropped (so editors emitting custom node types like unsplashImage, callout, embed don't crash builds). To opt in to rendering a custom node, write a NodeHandlerInterface and register it:
Now {"type": "callout", "attrs": {"type": "warning"}, "content": [...]} renders to <aside class="callout callout--warning">…</aside>.
Custom node that needs to embed images
If your custom node has remote or local image references, register them with the AssetManager so they're embedded in the EPUB:
A complete working example is in examples/UnsplashImageHandler.php.
Overriding a built-in node
override() replaces a default handler:
Custom marks
Same pattern via MarkHandlerInterface:
Custom renderer (full replacement)
If you'd rather not use the default renderer at all — for example, you have an existing Tiptap-to-HTML pipeline you want to wrap — implement ContentRendererInterface:
You'd typically use this to wrap a third-party Tiptap PHP renderer like ueberdosis/tiptap-php. The default renderer remains an option you can fall back to.
Styling
A clean default stylesheet is embedded automatically. To customize:
Navigation features
The library auto-generates three EPUB nav structures (you don't have to think about any of them):
- TOC (
<nav epub:type="toc">) — every chapter at the top level, inner Tiptap headings nested below. - Landmarks (
<nav epub:type="landmarks">) — cover, table of contents, beginning of body. - Page-list (
<nav epub:type="page-list">) — one entry per chapter so readers can show "page N of M". Disable with->disableAutoPageList().
Plus the legacy formats for older readers:
- NCX (
OEBPS/toc.ncx) — EPUB 2 navigation. Older Kindle apps, Adobe Digital Editions pre-v4, and calibre's older TOC UI fall back to this. Disable with->disableNcx(). - Guide (
<guide>in OPF) — EPUB 2 reference list (cover, toc, beginning).
Verification
The library passes EPUBCheck 5.x (the W3C reference validator) with 0 errors / 0 warnings on every build. To verify your output:
Expected output:
Spec references
The library follows the W3C EPUB 3.3 Recommendation:
- EPUB 3.3 (umbrella)
- EPUB Packages 3.3 (OPF)
- EPUB Content Documents 3.3 (XHTML/SVG/MathML)
- EPUB OCF 3.3 (ZIP container)
- EPUB Reading Systems 3.3
Plus selected EPUB 2 features for legacy-reader compatibility (NCX, <guide>, <meta name="cover">).
API reference
EpubBuilder
| Method | Description |
|---|---|
EpubBuilder::create(): static |
Entry point — start a new builder. |
setMetadata(callable $cb): static |
$cb(BookMetadata $m) — configure metadata. |
addChapter(string $title, array $tiptapJson): static |
Add a chapter. |
setRenderer(ContentRendererInterface): static |
Replace the default Tiptap renderer entirely. |
getRenderer(): ContentRendererInterface |
Get the current renderer (used to register custom nodes/marks before adding chapters). |
setStylesheet(string $path): static |
Use a custom CSS file in place of the default. |
addCss(string $css): static |
Append CSS rules to the default (or custom) stylesheet. |
disableAutoPageList(): static |
Opt out of one-page-per-chapter page-list entries. |
disableNcx(): static |
Opt out of the legacy EPUB 2 NCX fallback. |
assetManager(): AssetManager |
Internal asset manager (for custom node handlers that embed images/fonts). |
tocBuilder(): TocBuilder |
Internal TOC builder (for custom heading-like nodes). |
pageListBuilder(): PageListBuilder |
Internal page-list builder (for custom page-break nodes). |
metadata(): BookMetadata |
Direct access to the metadata object. |
build(?string $path = null): EpubOutput |
Validate, render, and write the EPUB. |
buildToStream($resource, int $chunkSize = 8192): int |
Build and copy bytes into a writable stream resource; deletes the temp file afterwards. Returns bytes written. |
buildToString(): string |
Build and return the EPUB as a binary string; deletes the temp file afterwards. |
BookMetadata
All setters return static for chaining.
| Method | EPUB field |
|---|---|
title(string) |
<dc:title> (required) |
language(string) |
<dc:language> (required, BCP 47) |
author(string) |
<dc:creator> — call multiple times for multiple authors |
contributor(string $name, string $role = 'oth') |
<dc:contributor> with MARC relator role |
subject(string) |
<dc:subject> — call multiple times for multiple tags |
publisher(string) |
<dc:publisher> |
description(string) |
<dc:description> |
rights(string) |
<dc:rights> |
isbn(string) |
<dc:identifier> with urn:isbn: prefix |
coverImage(string $path) |
Triggers cover-page generation; image is embedded |
direction(string) |
'ltr' (default) or 'rtl' |
series(string $name, ?int $position) |
EPUB 3 collection metadata |
identifier(string) |
Override the auto-generated UUIDv4 |
modified(\DateTimeImmutable) |
Override the auto-generated modification time |
EpubOutput
| Method | Description |
|---|---|
getPath(): string |
Path on disk where the EPUB was written. |
getSize(): int |
File size in bytes. |
getContents(): string |
Raw EPUB bytes. |
download(string $filename = 'book.epub'): never |
Stream as HTTP download (calls exit). |
streamTo($resource, int $chunkSize = 8192): int |
Copy the EPUB into any writable stream resource in chunks. Returns bytes written. |
chunks(int $chunkSize = 8192): \Generator |
Yield the EPUB body as a generator of byte chunks. |
delete(): void |
Remove the file. |
Architecture overview
The package is intentionally small and composable: replace any layer by passing a different implementation, or extend behavior by registering handlers in the registries.
License
MIT.
All versions of epub-builder with dependencies
ext-zip Version *
ext-dom Version *