Skip to main content

Create and safely rebuild EPUB files from structured text and Markdown.

Project description

PyPI - Version PyPI - Python Version PyPI - Downloads codecov

text2epub

text2epub is a typed Python library and CLI for creating EPUB files from plain-text writing workflows. It is useful when you keep a manuscript as one Markdown file, as a folder of numbered Markdown chapters, or as already-rendered XHTML chapter fragments.

It also includes a conservative rebuild workflow for tools such as booktx that need to apply validated text replacements to an existing EPUB without rewriting unchanged package entries.

Features

  • create new EPUBs from one Markdown file
  • create new EPUBs from a folder of ordered Markdown files
  • discover chapters from filename-based manuscript conventions
  • generate XHTML, OPF, NAV, NCX, CSS, and deterministic ZIP output
  • optionally add a generated title page and reader-visible contents page
  • request automatic TOC page numbers with CSS target-counter() for readers that support paged-media counters
  • package local image assets referenced by Markdown
  • support YAML-like front matter for common EPUB metadata
  • build EPUBs from explicit XHTML chapter bodies
  • safely rebuild existing EPUBs from extraction manifests and replacement plans
  • byte-identical no-op and identity rebuild paths
  • basic EPUB package validation and unresolved-token checks

Installation

uv pip install text2epub

For development from a checkout:

python -m pip install -e .

Folder-based Markdown workflow

A simple manuscript folder can use filenames to define reading order:

manuscript/
├── 00-front-matter.md
├── 01-introduction.md
├── 02-method.md
└── 03-appendix.md

The first file may contain front matter for book metadata:

---
title: Example Book
language: en
author: Ada Lovelace
publisher: Example Press
date: 2026-06-22
---

# Introduction

This becomes the first EPUB chapter.

Build it from Python with the convenience API:

from pathlib import Path

from text2epub import BuildOptions, create_epub_from_markdown_folder

create_epub_from_markdown_folder(
    Path("manuscript"),
    Path("book.epub"),
    options=BuildOptions(
        include_title_page=True,
        include_toc_page=True,
        toc_page_numbers=True,
    ),
)

Or build the same folder from the CLI:

text2epub markdown manuscript/ -o book.epub --title-page --toc-page --toc-page-numbers

Explicit Python API

Use create_epub_from_markdown_files when your application already controls the chapter list and order:

from pathlib import Path

from text2epub import BuildOptions, EpubMetadata, create_epub_from_markdown_files

create_epub_from_markdown_files(
    [Path("01-introduction.md"), Path("02-body.md")],
    Path("book.epub"),
    metadata=EpubMetadata(title="Example Book", language="en"),
    options=BuildOptions(include_title_page=True, include_toc_page=True),
)

Use the lower-level model API when you need per-chapter ids, hrefs, titles, or custom build options:

from pathlib import Path

from text2epub import (
    BuildOptions,
    EpubMetadata,
    MarkdownBook,
    MarkdownChapter,
    create_epub_from_markdown,
)

book = MarkdownBook(
    metadata=EpubMetadata(title="Example Book", language="en"),
    chapters=[MarkdownChapter(path=Path("chapter-01.md"))],
    options=BuildOptions(deterministic=True),
)
create_epub_from_markdown(book, Path("book.epub"))

Rebuild API

from pathlib import Path

from text2epub import Replacement, ReplacementPlan, rebuild_epub

report = rebuild_epub(
    ReplacementPlan(
        source_epub=Path("source.epub"),
        extraction_manifest=Path("manifest.json"),
        replacements=[
            Replacement(
                block_id="spine-0001:block-000001",
                text="Translated paragraph.",
            )
        ],
    ),
    Path("rebuilt.epub"),
)
print(report.changed_entries)

CLI

text2epub markdown INPUT.md -o OUTPUT.epub
text2epub markdown CHAPTER_DIR -o OUTPUT.epub --title "Book" --language en
text2epub markdown CHAPTER_DIR -o OUTPUT.epub --title-page --toc-page --toc-page-numbers
text2epub rebuild SOURCE.epub MANIFEST.json REPLACEMENTS.json -o OUTPUT.epub
text2epub validate OUTPUT.epub
text2epub version

Documentation

The Sphinx documentation lives under docs/. Build it locally with:

python -m pip install -e ".[docs]"
python -m sphinx -b html docs docs/_build/html

Start with docs/index.md for the user guide and docs/release-checklist.md for release validation.

Page numbers in EPUB readers

EPUB files do not contain universal static page numbers. When toc_page_numbers=True or --toc-page-numbers is used, text2epub writes CSS using target-counter() on the generated contents page. Reading systems with paged-media counter support can fill those numbers automatically; other readers still display the linked contents entries without page numbers.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

text2epub-0.1.1.tar.gz (48.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

text2epub-0.1.1-py3-none-any.whl (26.3 kB view details)

Uploaded Python 3

File details

Details for the file text2epub-0.1.1.tar.gz.

File metadata

  • Download URL: text2epub-0.1.1.tar.gz
  • Upload date:
  • Size: 48.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for text2epub-0.1.1.tar.gz
Algorithm Hash digest
SHA256 f6f51de963234bf921a6aa96320b2b0e7472178efebe21364a6b4e1fde6564fc
MD5 f4e0cbc757f8293251d0c85322e0d745
BLAKE2b-256 74823062ebfde30c289389411c695754351def75c2b6dda593f19a7b875cccac

See more details on using hashes here.

File details

Details for the file text2epub-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: text2epub-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 26.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for text2epub-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 cce8fa22afd4409f6af6a7afa27dcdeda71d7cb2a70b91f34ba52be5771361d1
MD5 c050f6dd197d3f9a29d32a902b410dba
BLAKE2b-256 20e0bfa3b149d7a0e2f263b47a73ea8389ad1872bfbcc181c93ae161a2819d23

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page