More on Ulysses and ePub

Ebook publishing seems to be my theme of the week. It’s something I didn’t know much about. I’ve managed to learn quite a bit this week. The most important thing I learned is about workflow.

There are lots of ways to make an ePub file. Amazon KDP will take just about any file and convert it to their .mobi format. Smashwords has a converter (“Meatgrinder”)that take a Word (.doc) file and do the conversion to ePub. These are convenient because they’re an all-in-one solution. But for the most part require a lot of work on the input file to avoid the garbage—in-garbage-out problem.

The Amazon and Smashwords guides are quite involved and require work to get the table of contents build in a way that will survive the Meatgrinder. Most other options are similar. Scrivener is another popular tool that will output an ePub directly. But work must be done inside the program to get the output correct.

Looking over the options, I still think I’m going to stick with Ulysses for making ePubs for now. It comes back to workflow.

I’m just one that would rather write in markdown, then export. This way all the formatting can be done through one stylesheet. From text to ePub is one click in the export panel. I can send the manuscript directly to iBooks for previewing. This is actually a huge time saver.

I’ve written a stylesheet for Ulysses that outputs clean formatting that will pass the KindleGen check and will convert to .mobi with no errors. This solved a lot of my problems with formatting. The default stylesheets contain CSS tags that get deleted during the conversion. It’s better to not have them in the file to start with. Once the new version, Ulysses for Mac (a name change from the current Ulysses III) ships, I’ll verify my stylesheet is still working and start a GitHub repository for it.

The exported ePub files will open in iBooks and convert to Kindle. I did find the files fail the ePub validation test1. This is because of the blank section problem I described in the last post. I also found out about a problem with the way the TOC file items are numbered. These are annoying, but easy enough to fix. In the end it’s easier to fix the files afterword than to deal with building TOCs by hand each time.

These bugs have been reported. Unfortunately, they won’t be fixed in time for the upcoming version.

Here’s what’s needed to fix an exported ePub file:

Start by putting the ePub file into its own folder. All the work will be done here. First, unzip the file.

$ unzip ulysses-fix.epub 

This will extract the contents, and leave the original file intact. The folder should have the following contents:

$ tree
├── META-INF
│   └── container.xml
├── OPS
│   ├── book.opf
│   ├── cover.html
│   ├── cover.png
│   ├── css
│   │   └── style.css
│   ├── index.html
│   ├── navigation.html
│   └── toc.ncx
├── mimetype
└── ulysses-fix.epub

If there’s any comments before page headers, like this:

%% This is a comment
# This is a H1 header

Then jump back to my post on removing the blank leading section, and do those edits to the index.html, toc.ncx, and navigation.html files.

Once those edits are done, we can move on to fixing the “playOrder” bug. This is happens to all of the exports. If you don’t use leading comments, it’s the only thing that prevents ePub validation.

This one is a bit annoying, in that we’ll have to change several lines. The problem is that the playOrder items are not incremented. They are all stuck at 1. To pass validation, they need to count up with each TOC entry.

The sample file I’m using has one h1 header, two h2 headers, and one h3 header. Only the top two levels count for the TOC.

The toc.ncx file needs to be edited so that each playOrder line after the first gets incremented. Thes first line doesn’t need changing.

<navPoint class="h1" id="chapter-1" playOrder="1">

The following navPoint lines need editing.

<navPoint class="h2" id="section-1.1" playOrder="1">
<navPoint class="h2" id="section-1.2" playOrder="1">

The numbers need to increase so they are sequential. Like so:

<navPoint class="h2" id="section-1.1" playOrder="2">
<navPoint class="h2" id="section-1.2" playOrder="3">

This can be done by hand in a short TOC. With more than a few, it’s easier to automate. Check the bottom of this post for simple ruby script that will do this edit for you.

Once all the edits are done, we need to zip the file back up. This is best done with the -f option to zip, which will update (or “freshen”) the file with the changed files. Because we have the zip file and the extracted contents in the same folder, this command works:

$ zip -f ulysses-fix.epub 
freshening: OPS/index.html (deflated 54%)
freshening: OPS/navigation.html (deflated 51%)
freshening: OPS/toc.ncx (deflated 59%)

Now the same ePub file we started with will have the new files inserted into it. This is much easier that trying to re-zip the whole file. Now take the file to the validator and make sure it passes.

This will seem like a lot of work to start with. It’s really not, just annoying. The Ulysses developers know about the bugs. Soon these steps won’t be necessary. The benefits of one-click markdown > ePub export outweigh the hassle of having to edit the files for now.


Here’s the bonus ruby script for fixing the toc.ncx increment bug.

#!/usr/bin/env ruby
cnt = 1
ARGF.each_line do |line|
    if /playOrder/.match(line)
        line.sub!(/"1"/, "\"#{cnt}\"")
        cnt += 1
    end
    puts line
end

Use it like this:

$ epub-fix.rb OPS/toc.ncx > toc.new

Inspect the toc.new file to make sure everything looks good, then replace the old one with it.

$ mv toc.new OPS/toc.ncx 

Then re-zip the file as shown above.


  1. To list a book on the iBooks store, an ePub file must pass validation with no warnings or errors.