archetypes | ||
exampleSite | ||
layouts | ||
static | ||
LICENSE | ||
README.md | ||
theme.toml |
Epub Theme
An epub theme for the Static Site Generator HUGO.
This is a simple ebook generator that creates a valid epub ebook from md files.
The epub format
I use the newer epub3 format. The file structure looks like this:
├── mimetype
├── META-INF
│ └── container.xml
└── OEBPS
├── chapter
│ ├── chapter-1.xhtml
│ ├── chapter-1
│ │ ├── image-1-1.jpg
│ │ └── image-1-2.jpg
│ ├── chapter-2.xhtml
│ ├── chapter-3.xhtml
│ ├── chapter-3
│ │ └── image-3.jpg
│ ...
│
├── content.opf
├── cover.jpg
├── css
│ └── stylesheet.css
├── inhaltsverzeichnis.xhtml
├── titelseite.xhtml
└── toc.ncx
How the as HUGO epub theme works
- mimetype, container.xml and stylesheet.css are static files located in the static/ theme folder
- cover.jpg is located in the static/OEBPS folder
The rest of the files are dynamically generated from the content of the HUGO project:
content
├── _index.md
├── inhaltsverzeichnis.md
├── blog
│ ├── chapter-1
│ │ ├── image-1-1.jpg
│ │ ├── image-1-2.jpg
│ │ └── index.md
│ ├── chapter-2.md
│ └── chapter-3
│ ├── image-3.jpg
│ └── index.md
└── titelseite.md
_index.md creates the central files content.opf and toc.ncx via the configuration in config.toml and the theme layout. The setting
cascade:
_build:
publishResources: false
in frontmatter ensures that only the scaled images end up in the ebook folder and the original files are not copied along with them -- which HUGO would otherwise do by default.
table of contents.md and title page.md create these necessary pages in the ebook. These files must not be deleted or renamed. The content comes from params in config.toml. In the frontmatter the parameter
ebook: toc
resp.
ebook: cover
ensures that the template single.xhtml handles these special cases differently from the standard.
The actual theme layout under themes/epub/layouts consists of only three files:
├── _default
│ └── single.xhtml
├── index.ncx
├── index.opf
single.xhtml creates all xhtml pages, index.ncx is the template for toc.ncx and index.opf creates content.opf. All this is controlled by config.toml. Normally these three files do not need to be changed. Also, all files used in the ebook must be registered in the manifest of content.opf. This happens automatically for all files from the content folder. But if, for example, static images are referenced in the pages, they would have to be added manually in the manifest. This happens in index.opf.
config.toml contains all meta data for the ebook and ensures that the correct file structure is created:
- disableKinds turns off almost everything that HUGO does by default. We only generate output for pages and for the root file _index.md.
- permalinks plays an important role. Here we have to define the path for each section contained in content/. I have predefined an entry for "blog". If there should be other or further sections (these are the folders directly below content/), a line must be added in each case.
- mediaTypes, outputFormats and outputs define the three file formats dynamically generated by HUGO: xhtml, opf and ncx. Corresponding templates are located in the layouts/ directory of the theme.
- markup controls the interpretation of the markdown files and can be customized as desired. The setting xHTML = true must not be changed.
- params contains the metadata for the ebook (book title, author, etc.). It also specifies how the images should be scaled. Older ebook readers seem to have problems with jpg files (at least my ancient Kindle).
How to generate the epub file
Calling hugo
in the HUGO root directory of the project creates the demo ebook in the public folder -- but still unpacked. To get the desired epub format, the contents of the public directory must be zipped. The zip archive must have the extension .epub.
Important: the mimetype file must be the first file in the zip archive. So the call of zip should be like this to create an ebook named ebook.epub which is located in the HUGO root directory:
cd public
zip -rX ../ebook.epub mimetype OEBPS META-INF
To avoid having file garbage in the finished ebook, the public/ directory and the zip/epub file should be deleted before re-creating the ebook. For Linux enviroment, a deploy bash script is included in the theme that does all the steps automatically:
deploy.sh:
#!/bin/bash
hugo --cleanDestinationDir
cd public
rm -f ../ebook.epub
zip -rX ../ebook.epub mimetype OEBPS META-INF
Good to know
The theme uses HUGO Page Bundles to manage the images automatically. If you want to integrate images into your resources, you can do this with the shortcode
{{< image src="image name" caption="image caption" >}}
It is enough to specify a substring of the image name, as long as it is unique. The theme currently supports only jpg and png images. The automatic determination of the mimetype in the manifest of content.opf may need some improvement and can be adjusted in index.opf if needed. In general, all file and folder names should be without special characters, as this can lead to validation errors.
Who wants to embed static images from the static/ folder, must consider three things:
1. the images must be in the static/OEBPS/ directory.
2. each image file must be listed in the manifest (in the template index.opf). The already existing entry for cover.jpg can be used as an example.
3. the files must be addressed in the content relatively, e.g. ![Alt-Text](../my-image.jpg)
Epub files with validation errors are usually still displayed by the readers. However, it is of course better if the ebook is formally free of errors. The highly recommended ebook management software Calibre offers the possibility to edit books and in this context also to check for errors and debug them. Other validators: Epub online validator and pagina EPUB checker (freeware).
There is a hack in the automatic generation of the manifest in content.opf and the table of contents (single.xhtml) for which I could not think of a better solution. HUGO would generate paths for relative URLs that look like this, for example: ../OEBPS/chapter/chapter-1.xhtml. This is theoretically correct, but some ebook readers (and also Calibre) don't handle this well and destroy the chapter order. I therefore transform the path by a subsequent replace. I cut ../OEBPS/ from the path, so that it then looks like this, for example: chapter/chapter-1.xhtml.
By the way, for manual internal links between articles, the automatic relative HUGO paths are working fine. For this, the internal ref-shortcode should be used.
There are also two shortcodes that generate the cover page and can be customized if needed: cover.html and covertext.html.
Demo ebook
License
This Hugo theme is licensed under the Creative Commons Attribution 4.0 License.