{{todo|Beware, this doesn’t fit the current export files and ePub workflow as of January 2015!}} < [[Epub]]| [[XML]] | [[Export]] | [[ePub|New ePub docs]]>
Creating an ebook with ConTeXt is still tedious and needs a lot of manual work - that will not change, since everyone has other needs, uses different structures etc.
Here I’ll show you my workflow for creating ebooks of my songbooklets (that use [[LilyPond]] via [http[modules://modules.contextgarden.net/t-filter |filter module]] for the notes).
I’m using ConTeXt’s [[Project structure]], separating content in products (for me: single booklets) and components (for me: single songs) with a common stylesheet (environment).
UnfortunatelyBeware, you need a current beta version of ConTeXt has a bug in XML creation , since Hans fixed some export related bugs in this setupthe last few days! --[[User:Hraban|Hraban]] 13 September 2014.
== ConTeXt setup ==
<texcode>
\setupexport[ hyphen=yes,
%firstpage={cover.jpg}, % is ignored
title={Songbook},
\settaggedmetadata[
% here you can set as many metadata entries as you like
%firstpage={cover.jpg}, % is ignored
title={Songbook},
name=ebook, % this becomes the name of the output directory
author={Hraban}] \definehighlight[emph][style=italic] % use \emph{something} instead of {\em something}
</texcode>
Make sure to tag all your structural elements with <{{cmd>|start...</cmd>}}-<{{cmd>|stop...</cmd>}}, e.g. <{{cmd>|startchapter</cmd>}}, but even <{{cmd|startparagraph}}! In places where {{cmd>|startparagraph</}} does not work, such as itemizations, where it causes a blank line after the bullet and before the item text, use {{cmd|bpar}} (and closing {{cmd>!|epar}}) to tag paragraphs.
Then you can call ConTeXt and its ePub script:
<codepre>
context mysongbook
mtxrun --script epub --make mysongbook
</codepre>
The first creates {{code|export.xml }} and a bunch of other files.The second creates a directory "{{code|ebook.tree" }} with the proper structure for ePub. The ePub file in the tree directory is unusable.
We’ll mostly work with "export.xml" that contains all your content (check that, you’ll miss everything that was not properly tagged).
== Fix export.xml ePub structure ==
If you run the epub script on a single file, you’ll get a well-formed and usable export.xml. If you use a project structure, the root node <code><document></code> This is missing. Just put it in manually (after the comment lines). You can also move the <code><metadata></code> block out of the first directory structure, but that’s merely a cosmetical error.that we need for our ePub:
<code><?We use mimetype and container.xml version="1unchanged from ConTeXt’s epub script and (re)create everything else.0" encoding="UTF-8" standalone="yes" ?><!-- input filename : solo --><!-- processing date : Wed Aug 27 13:47:46 2014 --><!-- context version : 2014.08.21 09:56 --><!-- exporter version : 0.31 --><document language=At the end this structure is just zipped with an "enepub" file="solo" date="Wed Aug 27 13:47:46 2014" context="2014.08.21 09:56" version="0.31" xmlns:m="http://www.w3ending.org/1998/Math/MathML"> <metadata> <metavariable name="author">Hraban</metavariable> </metadata> <section detail="chapter" location="aut:1">...</code>
You don’t need the attributes of the document node, even if we could use the language setting.== Unchanged files ==
For the records: === {{code|mimetype}} === <pre>application/epub+zip</pre> === {{code|container.xml}} === <xmlcode><?xml version="1.0" encoding="UTF-8"?> <container version="1.0" xmlns="urn:oasis:names:tc:opendocument:xmlns:container"> <rootfiles> <rootfile full-path="OEBPS/songbook.opf" media-type="application/oebps-package+xml"/> </rootfiles></container></xmlcode> == Transform XML to HTML etc. ==
Even if the ePub format is supposed to work with any XML, most readers only accept HTML.
I use the free version of [[http://saxon.sourceforge.net Saxon]] and some XSL transformations for the conversion.
The incantation goes like <{{code>|saxon -o:content.xhtml -s:export.xml -xsl:export2html.xsl</code>}}.I installed Saxon on my Mac with MacPorts, then instead of just "saxon" you must call <{{code>|java -jar /opt/local/share/java/saxon9he.jar</code>}}.
<xsl:variable name="within-paragraph">0</xsl:variable ><!-- statusxsl: are we variable name="within a paragraph? -section">0</xsl:variable ><xsl:variable name="previous-section">0</xsl:variable >
h1 = book titleh2 = part titleh3 = chapterh4 = sectionh5 = subsection<!DOCTYPE ncx PUBLIC "-//NISO//DTD ncx 2005-1//EN" "http://www.daisy.org/z3986/2005/ncx-2005-1.dtd">
-->
<ncx xmlns="http://www.daisy.org/z3986/2005/ncx/" version="2005-1"> <head> <meta name="dtb:uid" content="BookId" /> <meta name="dtb:depth" content="1" /> <meta name="dtb:totalPgeCount" > <xsl:attribute name="content"> <xsl:value-of select='count(section[starts-with(@detail,"Titel")])' /> </xsl:attribute> </meta> <meta name="dtb:maxPageNumber"> <xsl:attribute name="content"> <xsl:value-of select='count(section[starts-with(@detail,"Titel")])' /> </xsl:attribute> </meta> </head> <docTitle> <text><xsl:value-of select='//metavariable[@name="title"]'/></text> </docTitle> <docAuthor> <text><xsl:value-of select='//metavariable[@name="author"]'/></text> </docAuthor> <navMap> <navPoint id="aut_0" origin="aut_0" playOrder="0"> <navLabel> <text>Cover</text> </navLabel> <content src="cover.html"/> </navPoint> <navPoint id="aut_1" origin="aut_1" playOrder="1"> <navLabel> <text>Start</text> </navLabel> <content src="Text/_intro.html"/> </navPoint> <xsl:for-each select="//registerentry"> <xsl:variable name="location"> <xsl:value-of select='(./descendant::link/@location)[1]'/> </xsl:variable > <xsl:variable name="origin"> <xsl:value-of select='//registerlocation[@internal=$location]/ancestor::section[starts-with(@detail,"Titel")]/@implicit'/> </xsl:variable > <navPoint> <xsl:attribute name="id"> <xsl:value-of select='$location'/> </xsl:attribute> <xsl:attribute name="origin"><xsl:value-of select="$origin" /></xsl:attribute> <xsl:attribute name="playOrder"> <xsl:value-of select="2 + count(preceding-sibling::registerentry)" /> </xsl:attribute> <navLabel> <text><xsl:value-of select='./registercontent'/></text> </navLabel> <content> <xsl:attribute name="src">Text/aut_<xsl:value-of select='$origin' />.html</xsl:attribute> </content> </navPoint> </xsl:for-each> </navMap></ncx></xsl:template> </xsl:stylesheet></xmlcode> The links to a named anchor should work, but don’t in my reader. I must investigate further... == Converting images == In my case, all images are note lines, generated by LilyPond in one temporary directory. Your mileage will vary.ConTeXt’s epub script creates a list of images in {{code|export-images.css}}, you might want to parse that to find all images. <pre>cd $LILYPONDTEMPDIRfor IMG in prd_songbook-temp-lilypond-*.pdf; do NEWIMG=${IMG#prd_songbook-temp-lilypond-} convert -density 196 $IMG'[0]' -trim +repage ../songbook.tree/OEBPS/Images/${NEWIMG%.pdf}.pngdone</pre> == Create ePub == Look at the tree above - are all your files in the right location? Then zip your tree! <pre>cd songbook.treezip -uqr ../songbook.epub *</pre> Now test it with your reader or editor (e.g. Calibre). (Apple iBooks or Adobe Digital Editions don’t work.) == Shell script == Of course I don’t do all these steps above manually. Here’s my little shell script. === {{code|epub.sh}} === <pre>#!/bin/bash# call as "./epub.sh productname" # ConTeXt is not in my usual path (setuptex needs too long to be called with every shell);# probably your installation is at a different locationif [ "$TEXROOT" == "" ]; then source ~/Library/texmf/tex/setuptex ~/Library/texmf/texfi # all my products are named like "prd_something.tex"PRD=$1if [ ! -e prd_${PRD}.tex ]; then echo "Product ${PRD} not found!" exit 1fi # all XSL files are in this WORKDIRWORKDIR=epub-workflow # my ConTeXt wrapper "makeit.sh" script creates PDFs with a dateISODATE=`date +"%Y-%m-%d"`PRDPDF=${PRD}_${ISODATE}.pdf # LilyPond is run in this TEMPDIR and creates its note images thereTEMPDIR=lilytemp EPUBPREFIX=epub_TREE=${PRD}.treeOEBPS=${TREE}/OEBPSSAXON="java -jar /opt/local/share/java/saxon9he.jar"# http://saxonica.com/documentation/html/using-xsl/commandline.html if [ ! -f export.xml ]; then echo "File export.xml not found! Trying to run ConTeXt..." # you should replace this call with your own ./makeit.sh ${PRD} exit 2fi if [ ! -f $PRDPDF ]; then echo Product $PRDPDF not found! echo Please run "makeit.sh $PRD" exit 3fi if [ ! -d $OEBPS ]; then echo Directory $OEBPS missing! echo Creating new ePub ... mtxrun --script epub --make ${PRD}fi if [ -d $OEBPS ]; then echo "Creating directories (might exist) ..." mkdir $OEBPS/Styles mkdir $OEBPS/Images mkdir $OEBPS/Fonts mkdir $OEBPS/Text echo Creating HTML ... $SAXON -o:$OEBPS/Text/_intro.html -s:export.xml -xsl:$WORKDIR/export2html.xsl echo Creating OPF ... $SAXON -o:$OEBPS/${PRD}.opf -s:export.xml -xsl:$WORKDIR/export2opf.xsl echo Creating ToC NCX ... $SAXON -o:$OEBPS/toc.ncx -s:export.xml -xsl:$WORKDIR/export2ncx.xsl echo Creating Cover ... $SAXON -o:$OEBPS/cover.html -s:export.xml -xsl:$WORKDIR/export2cover.xsl echo Creating cover image from first page of PDF ... convert -density 196 $PRDPDF'[0]' +repage $OEBPS/Images/cover.jpg echo Copying files ... cp style.css $OEBPS/Styles/ # This copies only fonts from your project directory; adapt. cp *.?tf $OEBPS/Fonts/ echo Converting images from PDF to PNG ... cd $TEMPDIR for IMG in prd_${PRD}-temp-lilypond-*.pdf; do NEWIMG=../$OEBPS/Images/${IMG#prd_${PRD}-temp-lilypond-} NEWIMG=${NEWIMG%.pdf}.png if [ ! -f $NEWIMG ]; then convert -density 196 $IMG'[0]' -trim +repage ${NEWIMG} fi done cd .. # delete old epub rm $TREE/${PRD}.epub rm ${EPUBPREFIX}${PRD}.epub echo Creating ePub ${EPUBPREFIX}${PRD}.epub ... cd $TREE zip -uqr ../${EPUBPREFIX}${PRD}.epub * cd ..fiecho Ready.</pre>