Home / Blog Menu ↓

Blog: #epub

10 posts / tag feed / about the blog / archive / tags

With Marvin’s recent disappearance from the iOS app store, I’ve started feeling an itch to get my own ebook reading system set up sooner than later — ideally before the sad day comes when I can’t get Marvin to work on my phone anymore.

I’ve tried other iOS ereader apps and they don’t yet meet my needs (and let’s be clear, by “needs” I mean high-maintenance wishes), such as custom fonts, good design, configurable typography, and nice page numbers (ideally the 1,024 characters per page rule that Adobe Digital Editions and Marvin use).

Also, I want to use my phone since I have it with me all the time and can read more often, thus I’m not considering a dedicated ereader like a Kobo or a Kindle. And I have a large collection of ebooks I want to read, so print books don’t meet the need.

The default for me here would be a web app (PWA), with a backend built in Django or FastAPI or Go. That’s probably where I’ll land, but from a research angle I see this as a good time to explore possibilities I wouldn’t normally consider. Some ideas along those lines:

  • PDF — convert EPUBs to phone-sized PDFs automatically and then use a PDF reader like Documents instead of a dedicated EPUB app, possibly with the analog filters I recently posted about
  • Images — convert EPUBs to images (one page per image) and then read via an album in the system photos viewer, deleting each page as I read it (half joking here)
  • HTML — splat the ebooks out into all their HTML files and then put those up on a server behind authentication, reading them in a browser like normal web pages
  • Retro ebook reader — web-based app that feels like a Game Boy or one of those tiny consoles, with a chonky pixel font, possibly using game mechanics for page navigation (I’m intrigued by this idea but in reality it would probably feel super gimmicky)
  • 3D app — deboss the type, procedurally generated paper texture, etc. (also feels gimmicky)
  • Email — export each chapter of the EPUB and then email it to myself (fully joking here) (it would work, sure, but I don’t want to read books in my email)

The PDF and HTML options hold some promise, so I plan to continue exploring them for a bit before I cave and write a PWA.


Reply via email or office hours

I’ve been playing around with making EPUBs look more like print:

Two book pages. At left is a page from a digital PDF. At right is the same page but modified to look less digital.

Why the madness: ebooks feel kind of sterile to me, and I’m intrigued by the idea of giving them a more analog feel.

The experiment is still early on (I’ve only automated the first step so far), but at this point the process involves:

  1. Turning the EPUB into a PDF (concatenating each file in the EPUB into a single HTML file, setting some print CSS rules, and printing from HTML to PDF in a browser)
  2. Turning each page into an image (at left in the above image)
  3. Eroding/dilating the image to simulate ink spread
  4. Adding a very slight ripple
  5. Blurring the next page, flipping it backwards, and compositing it at a low opacity
  6. Adding some paper texture (at right in the above image)
  7. Compiling all the page images back into a PDF

Other notes:

  • This does mean larger file sizes, but not prohibitively so. (For me, anyway.)
  • Right now I’m experimenting with doing this statically, in PDF but I imagine most if not all of it could be done dynamically in-browser. (filter: blur(0.25px) contrast(3) in CSS applied twice to text can give a roughly similar effect to erosion/dilation, for example.)
  • The current erosion/dilation method is acceptable, but I feel like there’s more room for improvement here.
  • A shortcut to doing the full process is to export a blurred backwards page image, composite it onto the paper texture, and then use that as the background image on each page. You lose the variety, but it’s probably not noticeable.

Reply via email or office hours

Robin Rendle:

  1. I’ve always seen the browser as a printing press.
  2. Because of that, I’ve always seen myself as a publisher first and then everything else second.

This, particularly the second point. I’ve seen myself as a publisher for a long time now as well, with all the books and language charts and magazines and even the art. And the web makes publishing so, so easy. It’s magical. Instant worldwide distribution. (Well, instant for the digital things I make.)

His first point has stuck with me as well — I’ve tended to think of my site mostly as a place to publish PDFs and EPUBs and images and other files I’ve made, but I like the idea of the web as the actual delivery mechanism, for more than just blog posts. This isn’t a new idea, of course; it’s just something I haven’t been thinking about as much till now. I’m looking over the type of things I’ve made — books, languages charts, etc. — and thinking what it would be like if the end product were a web page instead of a PDF or an EPUB. And of course nowadays I’m using HTML/CSS as the source for all three main formats for books (web, EPUB, PDF), so it doesn’t necessarily have to be either/or.

Anyway, nothing specific in mind yet. We’ll see what comes of it.


Reply via email or office hours

Lector intro

Yet another entry in the ignominious series talking about my personal productivity tools.

Lector is a reading app for macOS. It’s an Electron app for now. The name comes from the Latin (for someone who reads), with a homophonic hat tip to Hannibal. It came about from wanting a minimalist app that would let me read PDFs and scanned books in dark mode and keep track of my spot across multiple books.

Overview

A Lector book is just a directory full of images. (PDFs have to be split up into image files first, so I have a small script to do that.) When the app starts up, it looks at the book list directory to see what books are available. It also has a JSON file to track where I’m at on each book (which page and which part of the page), what size the window is, which book I last had open, etc.

The app itself looks like this, on an empty desktop to show how I usually use it:

lector.png

No title bar, since I find that distracting. And the page images are scaled by default to fit the window width.

Hitting g / brings up a brief panel showing the books that are in the system, with alphabetized keys to get to them (so g a to go to the first, g b for the second, etc.). When I’m done reading a book, I delete its directory, so these mappings change fairly regularly.

j and f and double-clicking all go to the next page; k and d both go back to the previous page. J and K move up and down the page (in larger jumps), and the mouse can also be used to scroll. (I find that I mostly use the mouse for scrolling and f/d for page navigation, but every once in a while I’ll use the other keys.)

As you can see in the screenshot, it defaults to dark mode, with slightly lowered contrast for easier reading. i inverts the colors and s toggles the higher contrast view.

How I use Lector

I use it when I want to read a book I’ve scanned (usually with Scanbook). I haven’t used it as often lately, but I fully expect that to change soon. (It’s been very handy for reading textbooks.)

I’ve found that I prefer the window size shown in the screenshot, wide (so that the text is large enough) with just enough vertical room for a paragraph or so (since reading in smaller chunks is easier).

The future

I’d like to move off Electron at some point, probably to a native Swift app. Having it support PDFs directly (or splitting them up itself) would be nice, and having a way within the app to remove books would also be good.

Finally, I’d love to add EPUB support at some point. (I haven’t yet found a desktop EPUB reader I like. Marvin’s great on iOS, though.)


Reply via email or office hours

Greek New Testament reader’s edition

Just posted a verseless, paragraphed reader’s edition of the Greek New Testament, available for free download as an EPUB. It uses the paragraphing from the Nestle 1904 source edition.


Reply via email or office hours

epubdiff

I’ve released epubdiff, a Python script for diffing EPUBs.


Reply via email or office hours

Scrub

Just released Scrub, that Python script for bleeping profanity out of EPUBs that I mentioned a couple months ago.


Reply via email or office hours

Recommended: Standard Ebooks. They’re doing the same kind of thing I’ve done — making nice EPUB/Kindle editions of Project Gutenberg (though my efforts have of course been at a much smaller scale, and far more sporadic). Even better, Standard Ebooks has good typography standards and they’re proofing the books against original scans. This is a good project.


Reply via email or office hours

Formatting poetry for EPUB and Kindle

2018 note: this post has some formatting issues from when I migrated to a new blog engine. Until I get time to get it fixed, you’ll have to view source to see the markup correctly. (The post is also somewhat obsolete now, I think.)

A lot of the ebooks I’m working on have poetry, and after struggling with the formatting for a while, I think I’ve finally found some methods that are quite acceptable for EPUB (iBooks and Adobe Digital Editions) and somewhat acceptable for Kindle.

Without line numbers

This is the easiest. We’ll be working with the first two stanzas of “Adam-ondi-Ahman”, aiming for the following formatting:

This earth was once a garden place,

With all her glories common,

And men did live a holy race,

And worship Jesus face to face,

In Adam-ondi-Ahman.

We read that Enoch walk’d with God,

Above the power of mammon,

While Zion spread herself abroad,

And Saints and angels sung aloud,

In Adam-ondi-Ahman.

EPUB

First off, there’s no standard way to mark up poetry. This works for me, but if you’ve got a better way, let us know in the comments.

Markup

This earth was once a garden place,

With all her glories common,

And men did live a holy race,

And worship Jesus face to face,

In Adam-ondi-Ahman.

We read that Enoch walk'd with God,

Above the power of mammon,

While Zion spread herself abroad,

And Saints and angels sung aloud,

In Adam-ondi-Ahman.

So, encapsulate the poem in a .poetry div, put each line in a <p> tag, and use the .indent class for indenting lines. For new stanzas, add a .stanza class to the first line.

CSS
.poetry                 { margin: 1em 0; }
.poetry p               { margin: 0 0 0 4em; text-indent: -2em; }
.poetry p.stanza        { margin-top: 1em; }
.poetry p.indent        { margin-left: 5em; }
.poetry p.indent2       { margin-left: 5.5em; }
.poetry p.indent3       { margin-left: 6em; }

And that’ll give you hanging indents and proper indentation and all that good stuff, indenting the whole poem 2em from the left; if you need further indentation, you can use the .indent2 and .indent3 classes (and of course modify them however you need).

To set the poetry flush left, by the way, change margin: 0 0 0 4em to margin: 0 0 0 2em and set the .indent classes to start at 3em instead of 5em.

Kindle (no hanging indent)

If your lines are short enough that you don’t need to worry about using hanging indents, this markup is clean and short:

Markup

This earth was once a garden place,

With all her glories common,

And men did live a holy race,

And worship Jesus face to face,

In Adam-ondi-Ahman.

We read that Enoch walk'd with God,

Above the power of mammon,

While Zion spread herself abroad,

And Saints and angels sung aloud,

In Adam-ondi-Ahman.

CSS
p           { text-align: left; }
p.stanza    { margin-top: 1em; }
p.indent    { text-indent: 3em; }

Fairly simple.

Kindle (hanging indent)

With longer lines, you’ll usually want to give them hanging indents, as is traditional in formatting poetry. We can do this on the Kindle using nested “ tags.

There’s a catch, though: if you use this technique for hanging indents, you can’t do further indentation using CSS (like line 2 in our example poem) — as soon as you try to add the hanging indent, the whole thing goes flush left again. Instead, you have to resort to the dreaded   entity. If any of you figure out how to get indents and hanging indents on the Kindle, let me know.

Markup

This earth was once a garden place,

     With all her glories common,

And men did live a holy race,

And worship Jesus face to face,

     In Adam-ondi-Ahman.

We read that Enoch walk'd with God,

     Above the power of mammon,

While Zion spread herself abroad,

And Saints and angels sung aloud,

     In Adam-ondi-Ahman.

Note that for a new stanza, we replace the .inner class with .stanza (since the Kindle parser can’t handle two CSS classes on the same element).

CSS
p           { text-align: left; }
p.outer     { text-indent: 2em; }
p.inner     { text-indent: -2em; }
p.stanza    { text-indent: -2em; margin-top: 1em; }

With line numbers

Now it gets a little more complicated. For all of these, I’m using manually entered line numbers. Once EPUB readers support more CSS selectors (like :nth-child), though, it’ll be possible to do this automatically.

There are two basic styles of line numbers in poetry. Here’s left-aligned, using the first twelve lines of the Old English poem “Dream of the Rood” as an example of what we’re trying to achieve:

Hwæt! Ic swefna cyst secgan wylle,

hwæt me gemætte to midre nihte,

syðþan reordberend reste wunedon!

þuhte me þæt ic gesawe syllicre treow

5

on lyft lædan, leohte bewunden,

beama beorhtost. Eall þæt beacen wæs

begoten mid golde. Gimmas stodon

fægere æt foldan sceatum, swylce þær fife wæron

uppe on þam eaxlegespanne. Beheoldon þær engel dryhtnes ealle,

10

fægere þurh forðgesceaft. Ne wæs ðær huru fracodes gealga,

ac hine þær beheoldon halige gastas,

men ofer moldan, ond eall þeos mære gesceaft.

And right-aligned:

Hwæt! Ic swefna cyst secgan wylle,

hwæt me gemætte to midre nihte,

syðþan reordberend reste wunedon!

þuhte me þæt ic gesawe syllicre treow

5

on lyft lædan, leohte bewunden,

beama beorhtost. Eall þæt beacen wæs

begoten mid golde. Gimmas stodon

fægere æt foldan sceatum, swylce þær fife wæron

uppe on þam eaxlegespanne. Beheoldon þær engel dryhtnes ealle,

10

fægere þurh forðgesceaft. Ne wæs ðær huru fracodes gealga,

ac hine þær beheoldon halige gastas,

men ofer moldan, ond eall þeos mære gesceaft.

EPUB markup (left- and right-aligned line numbers)

The markup is the same for both left-aligned and right-aligned line numbers:

Hwæt! Ic swefna cyst secgan wylle,

hwæt me gemætte to midre nihte,

syðþan reordberend reste wunedon!

þuhte me þæt ic gesawe syllicre treow

5

on lyft lædan, leohte bewunden,

beama beorhtost. Eall þæt beacen wæs

begoten mid golde. Gimmas stodon

fægere æt foldan sceatum, swylce þær fife wæron

uppe on þam eaxlegespanne. Beheoldon þær engel dryhtnes ealle,

10

fægere þurh forðgesceaft. Ne wæs ðær huru fracodes gealga,

ac hine þær beheoldon halige gastas,

men ofer moldan, ond eall þeos mære gesceaft.

Syllic wæs se sigebeam, ond ic synnum fah,

forwunded mid wommum. Geseah ic wuldres treow,

EPUB CSS (left-aligned line numbers)

.poetry             { margin: 1em 0; }
.poetry p           { margin: 0 0 0 6em; text-indent: -3em; }
.poetry p.indent    { margin-left: 7em; }
.poetry .num        { float: left; margin-left: 5px; font-size: .8em;
                        color: #999; font-style: italic; }
.poetry .caesura     { display: inline-block; width: 2em; }

EPUB CSS (right-aligned line numbers)

.poetry             { margin: 1em 0; }
.poetry p           { margin: 0 2em 0 2em; text-indent: -2em; }
.poetry p.indent    { margin-left: 1em; }
.poetry .num        { float: right; margin-left: 2em; margin-right: 5px;
                        font-size: .8em; color: #999; font-style: italic; }
.poetry .caesura     { display: inline-block; width: 2em; }

Kindle (right-aligned)

With Kindle, alas, there’s no good way to set line numbers with poetry. The best I’ve come up with has the line numbers right aligned on their own line, which means every five lines (or however often you put line numbers in) there’s a stanza-like blank line. You’ll also notice that the .caesura spans have been replaced with manual strings of  , because the spans don’t work on Kindle.

Markup

Hwæt! Ic swefna cyst       secgan wylle,

hwæt me gemætte       to midre nihte,

syðþan reordberend       reste wunedon!

þuhte me þæt ic gesawe       syllicre treow

5

on lyft lædan,       leohte bewunden,

beama beorhtost.       Eall þæt beacen wæs

begoten mid golde.       Gimmas stodon

fægere æt foldan sceatum,       swylce þær fife wæron

uppe on þam eaxlegespanne.       Beheoldon þær engel dryhtnes ealle,

10

fægere þurh forðgesceaft.       Ne wæs ðær huru fracodes gealga,

ac hine þær beheoldon       halige gastas,

men ofer moldan,       ond eall þeos mære gesceaft.

CSS
p           { text-align: left; }
p.outer     { text-indent: 2em; }
p.inner     { text-indent: -2em; }
p.num       { font-style: italic; text-indent: 90%; }

Conclusion

Nice as it would be to have a cross-platform EPUB/Kindle solution for formatting poetry, that day hasn’t yet come. But in spite of the occasional hassles (I’m looking at you, Kindle), you can get decent-looking results without resorting to too much hackery.


Reply via email or office hours

md2epub

An itch scratched: md2epub, a Python script for making an EPUB out of Markdown files.

All it takes is a simple book file, which gives the script some basic metadata about the book and then lists the files that need to be included. The script runs Markdown on the files and makes an EPUB.

# Sample book file for md2epub
# 9 Jun 2010

Title: My Sample Book
Author: John Doe
Language: en-US
URL: /books/my-sample-book/
CSS: content/style.css

# Chapters
Foreword | content/foreword.text
Chapter 1 | content/chapter_1.text
Chapter 2 | content/chapter_2.text
Chapter 3 | content/chapter_3.text

# Images to be included
Images: images/illustration1.jpg, images/illustration2.jpg
Image: images/illustration4.jpg

And then you just run “md2epub myfile.book” and voila, instant EPUB. I’ve already used it on my Pearl of Great Price reader’s edition (which I’ll be releasing shortly) and it works like a charm.

Last but not least, the code is based on my friend Matt’s script GetBook.py. (And, in fact, that’s where I got the idea for this script.)


Reply via email or office hours