First, the Kindle Publishing Guidelines strongly recommend an HTML table of contents (TOC) which is now possible in tex4ebook. They also say it should be available to users either via a guide item in the OPF file or a landmarks nav element. It is also good to include an element for the start of the text. I was able to do this by hand, inserting the following lines before the </package> in the OPF file:

    <reference type="toc" title="Contents" href="RefBookli1.html" />
    <reference type="text" title="Preface" href="RefBookch1.html" />

and then repackaging the epub. Is there a way to do this not by hand, e.g. a lua script that can insert text in the OPF file?

Second, many ebooks include items in the sidebar such as "Copyright Page". These seem to be drawn from the ncx TOC. Clearly one doesn't want these in the HTML TOC. Is there a way to add things to the ncx TOC without adding them to the HTML TOC? This is more an item of curiosity for me, I'm not sure I would do it even if it were possible.


3 Answers 3


You schould create file named <main_file>.mk4 (the extension jest important, and basename should be the same as processed file). The file will be automatically processed during run of the tex4ebook. My file contains:

local bookfile  = "book"
local filter    = require "make4ht-filter"
local add_guide = function(s) return s:gsub("</package>",[[<guide>
   <reference type="cover" title="Cover" href="]] .."cover.jpg".. [[" />
   <reference type="toc" title="Table of Contents" href="]] ..bookfile.. ".html#x1-1000".. [[" />
   <reference type="text" title="Beginning" href="]] ..bookfile.."se1.html".. [[" />
local process = filter{"cleanspan", "fixligatures"}            
local guide = filter{add_guide}            
Make:match("html$", process)
Make:match("opf$", guide)
Make:match("html$", "tidy -m -xml -utf8 -q -i -w 200 ${filename}")

bookfile contains (again?) name of the base file. add_guide local function is the main worker: takes opf file, and using regular expressions, substitutes closing </package> by guide section.

In this section there is information about cover (you will be able to navigate to the cover; it is the first line). The second one contains reference to the table of content (the file is somehow old), and the third adds reference to beginning of the text. You can add other references as well.

Next there are definitions of filters (process for HTML processing, and guide for processing opf file). Make runs htlatex twice, for each html file filter process, and for opf file filter guide. At the end tidy cleans each html file.

There is only one issue: I can not manage adding cover both to the epub and mobi files. \coverimage{cover} generates code adding illustration to html file and to the manifest, but not marking as cover. Adding cover in guide is ok, but the cover image is included twice. Omitting \coverimage and dding cover by guide works, but I'm not sure if it is proper way.

  • Thanks, I was just learning my way around the .mk4 file and I think this is a helpful intro. It is a helpful scheme for making ad hoc edits, and editing out the <img> tag is one way to solve the cover problem. Similarly for changes to the .ncx TOC.
    – Nat Kuhn
    Nov 22, 2014 at 18:30
  • nice answer, Wojtek. regarding cover images, see tex.stackexchange.com/a/213562/2891. maybe I should make new command for this as well...
    – michal.h21
    Nov 23, 2014 at 19:19

I totally missed <guide> element, as I am focusing mainly on epub3 and this element is deprecated in that specification. But it was easy to add some support, so I added new command \OpfGuide for adding references to the guide. Syntax is following:

\OpfGuide[filename]{title}{reference type}

in your example, add this to the .cfg file

\OpfGuide[RefBookli1.html]{Table of contents}{toc}

to your second question, ncx file is built from \tableofcontents, but with starred sections included, so maybe something like \section*{Copyright} should work?

  • you are a hero! In the meantime I built on the example above to splice a reference for the TOC into the first position of the ncx file--which worked because playorder="0" actually works, to my amazement. As a result I was able to publish my book this morning, but I may well use these when I do a revision. Good to know that ncx TOC includes starred sections, I didn't think of that. Thank you for all your help! (it turns out I did need to add "Contents" to the ncx TOC because the Android Kindle app didn't have a good way to get back to the <guide> TOC that I could find).
    – Nat Kuhn
    Nov 24, 2014 at 1:47

Starting from @WojtekMyszka's nice answer (you should take a little time away from your computer more often, @michal.h21), I dealt with these issues and some html cleanup issues of getting rid of empty <p class="indent></p> elements, empty <a></a> elements and empty <div></div> elements. I missed the fact that you can invoke tidy programmatically--I had been using the "-t" option which tidies a the end--and I think an earlier application of tidy would make some of this a little more straightforward. Anyway, I like it because the "splicer" helper function is... well, helpful. I think it would be better lua programming practice to say return (s:gsub(from,to)) which I believe is the idiom to return only the first value from gsub and discard the number of substitutions, but I didn't test it that way and this seems to work.

local filter = require "make4ht-filter"
local splicer = function(from,to)
    return function(s)
        return s:gsub(from,to)
--html fixes
local afix = splicer("<a%s*></a>","")
local pfix = splicer("<p%s+[^>]*>%s*</p>", "")
local divfix = splicer("<div%s+[^>]*>%s*</div>", "")
--take out the cover image display
local snipcover = splicer('<div class="cover%-image">.-</div>',"")
--css fix
local cssfix = splicer("%,%s*%{","{")
--opf fix
local insertguide = splicer("</package>",[[
    <reference type="toc" title="Contents" href="RefBookli1.html" />
    <reference type="text" title="Preface" href="RefBookch1.html" />
--ncx fix
local insertcontents = splicer('<navPoint id="navPoint%-1" playOrder="1">',[[
<navPoint id="navPoint-0" playOrder="0">
      <content src="RefBookli1.html" />
    <navPoint id="navPoint-1" playOrder="1">]])
local htmlprocess = filter{afix, pfix, divfix, "nkcleanspan", "fixligatures", "hruletohr"}
local cssprocess = filter{cssfix}
local coverprocess = filter{snipcover}
local opfprocess = filter{insertguide}
local ncxprocess = filter{insertcontents}
Make:match("^RefBook%.html$", coverprocess)

As I mention in my comment above, it is pure luck that I could deal with the ncx TOC this way--it is possible to insert one extra element at the very beginning.

Anyway, I thought it was worth posting this because the more examples that people can see of working .mk4 files the better, I think.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .