All formats

go-epub

LanguageGo
LicenseMIT
Repositorygithub.com/go-shiori/go-epub
Documentationpkg.go.dev/github.com/go-shiori/go-epub
Depends onGo standard library, a few small modules
Read / writeno / yes (EPUB 3.0 with an EPUB 2 NCX)

go-epub builds EPUB files from HTML fragments. You add sections (chapters) as XHTML body content, plus CSS, images, fonts, audio and video from local files or URLs; the library writes the package document, the EPUB 3 navigation document, an EPUB 2 toc.ncx for older readers, and zips everything with mimetype first. Its test suite runs EPUBCheck, so the output is valid EPUB 3.

It’s a maintained fork of bmaupin/go-epub, used by the Shiori bookmark manager to save web pages as e-books. It only creates books: to read EPUB files in Go, use goreader/epub.

Installation#

Shell
go get github.com/go-shiori/go-epub

Basic usage: create an EPUB#

Go
package main

import (
	"log"

	epub "github.com/go-shiori/go-epub"
)

func main() {
	e, err := epub.NewEpub("My Book")
	if err != nil {
		log.Fatal(err)
	}
	e.SetAuthor("Jane Doe")
	e.SetLang("en")
	e.SetDescription("A short example book")

	_, err = e.AddSection("<h1>Chapter 1</h1><p>First chapter.</p>", "Chapter 1", "", "")
	if err != nil {
		log.Fatal(err)
	}
	_, err = e.AddSection("<h1>Chapter 2</h1><p>Second chapter.</p>", "Chapter 2", "", "")
	if err != nil {
		log.Fatal(err)
	}

	if err := e.Write("book.epub"); err != nil {
		log.Fatal(err)
	}
}

AddSection(body, title, internalFilename, internalCSSPath) returns the internal file name of the section. Leave the file name empty to get a generated one.

How to add a cover image#

Go
imgPath, err := e.AddImage("cover.jpg", "cover.jpg") // local path or URL, internal name
if err != nil {
	log.Fatal(err)
}
// second argument: CSS for the cover page; "" uses the default
if err := e.SetCover(imgPath, ""); err != nil {
	log.Fatal(err)
}

How to add images and CSS to chapters#

AddImage and AddCSS return paths relative to the sections, ready to use in HTML:

Go
cssPath, err := e.AddCSS("book.css", "book.css")
if err != nil {
	log.Fatal(err)
}
imgPath, err := e.AddImage("https://example.com/photo.png", "photo.png")
if err != nil {
	log.Fatal(err)
}
body := `<h1>Photos</h1><p><img src="` + imgPath + `" alt="photo"/></p>`
if _, err := e.AddSection(body, "Photos", "photos.xhtml", cssPath); err != nil {
	log.Fatal(err)
}

How to create nested chapters#

Go
parent, err := e.AddSection("<h1>Part 1</h1>", "Part 1", "part1.xhtml", "")
if err != nil {
	log.Fatal(err)
}
_, err = e.AddSubSection(parent, "<h2>Chapter 1</h2><p>Text.</p>", "Chapter 1", "", "")
if err != nil {
	log.Fatal(err)
}

Subsections appear nested in the table of contents.

How to write the EPUB to an HTTP response#

WriteTo writes to any io.Writer:

Go
func handler(w http.ResponseWriter, r *http.Request) {
	e, _ := epub.NewEpub("Generated")
	e.AddSection("<p>Hello</p>", "Hello", "", "")
	w.Header().Set("Content-Type", "application/epub+zip")
	w.Header().Set("Content-Disposition", `attachment; filename="book.epub"`)
	if _, err := e.WriteTo(w); err != nil {
		log.Println(err)
	}
}

Tips#