How to Generate EPUB from Markdown: Complete Build Pipeline for AI Agent Book

To generate EPUB from Markdown sources, install Pandoc and Poppler, run the build_epub.sh script, and let the automated pipeline handle cover extraction, table-of-contents flattening, and optional EPUBCheck validation.

The bojieli/ai-agent-book repository maintains a sophisticated toolchain to generate EPUB from Markdown files across multiple languages. According to the project's EPUB.md documentation and the build_epub.sh driver script, the process combines Pandoc document conversion with custom post-processing utilities to handle everything from cover image extraction to right-to-left language support.

Prerequisites: Installing Pandoc, Poppler, and EPUBCheck

Before you can generate EPUB from Markdown sources, you must install the core conversion toolchain. The pipeline requires Pandoc as the conversion engine and Poppler (specifically pdftoppm) to extract the first-page PDF as the EPUB cover image. Optionally, install EPUBCheck to validate the generated files against the EPUB 3 specification.


# Install required tools on Ubuntu/Debian

sudo apt-get install pandoc poppler-utils

# Optional: Install EPUBCheck for validation

sudo apt-get install epubcheck

Running the Build Script

The central entry point is build_epub.sh, which orchestrates the entire pipeline. Located in the repository root, this Bash script manages language detection, cover extraction, Pandoc invocation, and post-processing.

Building All Supported Languages

With no arguments, build_epub.sh generates EPUB files for every language that has a fully validated PDF pipeline. As defined in build_epub.sh at lines 34-38, this includes Chinese Simplified, Chinese Traditional, English, Spanish, Indonesian, Russian, Tamil, Vietnamese, Turkish, Korean, and Hungarian.


# Build all validated languages

./build_epub.sh

Building Individual Languages

To generate EPUB from Markdown for a specific language, pass its ISO 639-1 or ISO 639-2 language code as an argument. The script accepts codes such as zh-CN, en, es, or ru.


# Build only the English edition

./build_epub.sh en

Note: Japanese (ja) and Arabic (ar) are explicitly excluded from the default "all" target because their PDF pipelines are still being validated, as documented in EPUB.md at lines 13-22 and 31-33. To build these languages, you must invoke them explicitly:


# Build Japanese or Arabic explicitly

./build_epub.sh ja
./build_epub.sh ar

Understanding the Post-Processing Pipeline

After Pandoc converts the Markdown to EPUB format, the build script executes a multi-stage post-processing phase to ensure the output meets distribution standards.

Cover Image Extraction with Poppler

The script extracts the cover image from the first page of the corresponding PDF file using pdftoppm from Poppler. This extracted image becomes the EPUB cover, and the final .epub file is written adjacent to its source PDF in the file system. Generated EPUBs are automatically ignored by Git according to the repository's .gitignore configuration.

TOC Flattening and RTL Language Support

The script calls flatten_epub_toc.py to clean up the generated navigation structure. As implemented in lines 1-31 and 84-99 of flatten_epub_toc.py, this Python utility performs several critical operations:

  • Removes automatic section numbers from the table of contents
  • Adds proper title and TOC entries to the NCX and navigation files
  • For right-to-left languages (such as Arabic), rewrites navigation files and sets the page-progression-direction attribute to rtl

To prevent EPUBCheck from flagging dangling resources, the pipeline uses a custom Pandoc Lua filter. The epub_external_links.lua script, referenced at lines 1-14, rewrites external links inside chapter files that point to sibling directories, converting them to absolute GitHub URLs before they reach the final EPUB output.


# The script automatically runs these steps:

# 1. pdftoppm (cover extraction)

# 2. pandoc + epub_external_links.lua (conversion)

# 3. flatten_epub_toc.py (TOC cleanup)

# 4. epubcheck (optional validation)

Summary

  • Tooling: Generate EPUB from Markdown using Pandoc for conversion, Poppler for cover extraction, and EPUBCheck for validation.
  • Entry Point: Use ./build_epub.sh to build all validated languages, or pass a specific ISO code (e.g., en, es) for single-language builds.
  • Exceptions: Japanese and Arabic require explicit invocation and are excluded from the default build target due to ongoing PDF pipeline validation.
  • Post-Processing: The flatten_epub_toc.py script handles navigation cleanup and right-to-left language support, while epub_external_links.lua ensures external links point to valid absolute URLs.

Frequently Asked Questions

Why are Japanese and Arabic excluded from the default build target?

According to EPUB.md in the source repository, the PDF pipelines for Japanese and Arabic are still undergoing validation. While you can generate EPUB from Markdown for these languages by passing ja or ar explicitly to build_epub.sh, they are omitted from the "all" target to prevent incomplete builds in automated workflows.

What does the flatten_epub_toc.py script do?

This Python utility post-processes the raw EPUB output from Pandoc to remove automatically generated section numbers from the table of contents and add proper metadata entries. For right-to-left languages like Arabic, it also modifies the navigation files to set the correct page-progression-direction attribute, ensuring proper reading order in e-book readers.

The pipeline passes the epub_external_links.lua filter to Pandoc during conversion. This Lua script rewrites relative links that point to sibling directories (which would be dangling in the standalone EPUB) into absolute GitHub URLs, ensuring EPUBCheck validation passes without resource errors.

Is EPUB validation mandatory?

No. If epubcheck is installed on your system, build_epub.sh automatically runs it against the generated files and outputs the results. If the tool is not found, the script simply prints a reminder message and exits successfully, leaving you with an unvalidated but fully functional EPUB file.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →