git.iko.soy/typeable/pandoc
on master help sign in
EPUB writer: Better TOC and footnote handling.

* Here we go back to splitting the document at the Pandoc AST level, and converting each chapter to HTML separately. * Fixes bug in footnote processing introduced by commit 01d109e2efb880d9d2b8256d2e19ed4954076754. The bug caused all footnotes to appear in the last chapter, so that footnote links from other chapters would not work. Closes #651. * We also disable writerTableOfContents, since TOC is automatic for epub.

commitae6028d442df4ddc4ceb1cd7b01d7e0178d1d8e5 authorJohn MacFarlane <fiddlosopher@gmail.com> dateSun 4 Nov 2012, 18:03 (14 years ago) parentb69792e
1 file changed+29−20
src/Text/Pandoc/Writers/EPUB.hs+29−20
src/Text/Pandoc/Writers/EPUB.hs+29−20
@@ -46,7 +46,6 @@ import qualified Text.Pandoc.Shared as Shared
4646import Text.Pandoc.Options
4747import Text.Pandoc.Definition
4848import Text.Pandoc.Generic
49−import Text.Pandoc.Templates
5049import Control.Monad.State
5150import Text.XML.Light hiding (ppTopElement)
5251import Text.Pandoc.UUID
@@ -57,7 +56,7 @@ import Network.URI ( unEscapeString )
5756import Text.Pandoc.MIME (getMimeType)
5857import Prelude hiding (catch)
5958import Control.Exception (catch, SomeException)
60−import Text.HTML.TagSoup
59+import Text.Blaze.Html.Renderer.Utf8 (renderHtml)
6160
6261data EPUBVersion = EPUB2 | EPUB3 deriving Eq
6362
@@ -79,6 +78,8 @@ writeEPUB version opts doc@(Pandoc meta _) = do
7978 let opts' = opts{ writerEmailObfuscation = NoObfuscation
8079 , writerStandalone = True
8180 , writerSectionDivs = True
81+ , writerHtml5 = epub3
82+ , writerTableOfContents = False -- we always have one in epub
8283 , writerHTMLMathMethod =
8384 if epub3
8485 then MathML Nothing
@@ -134,25 +135,34 @@ writeEPUB version opts doc@(Pandoc meta _) = do
134135 fontEntries <- mapM mkFontEntry $ writerEpubFonts opts'
135136
136137 -- body pages
138+
137139 -- add level 1 header to beginning if none there
138140 let blocks' = case blocks of
139141 (Header 1 _ : _) -> blocks
140142 _ -> Header 1 (docTitle meta) : blocks
143+
141144 -- internal reference IDs change when we chunk the file,
142− -- so the next two lines fix that:
145+ -- so that '#my-header-1' might turn into 'chap004.xhtml#my-header'.
146+ -- the next two lines fix that:
143147 let reftable = correlateRefs blocks'
144148 let blocks'' = replaceRefs reftable blocks'
145− let tags = parseTags $ writeHtmlString opts'{writerStandalone = False,
146− writerHtml5 = epub3}
147− $ Pandoc (Meta [] [] []) blocks''
148149
149− let chunks = partitions (~== TagOpen "h1" []) tags
150+ let addToChunk :: [[Block]] -> Block -> [[Block]]
151+ addToChunk (c:cs) (Header 1 xs) = [Header 1 xs] : c : cs
152+ addToChunk (c:cs) x = (c ++ [x]) : cs
153+ addToChunk [] x = [[x]]
154+
155+ let chunks = reverse $ foldl addToChunk [] blocks''
150156
151− let chapToEntry :: Int -> [Tag String] -> Entry
152− chapToEntry num ts = mkEntry (showChapter num)
153− $ fromStringLazy
154− $ renderTemplate (("body",renderTags ts):("pagetitle",show num):vars)
155− $ pageTemplate
157+ let chapToEntry :: Int -> [Block] -> Entry
158+ chapToEntry num bs = mkEntry (showChapter num)
159+ $ renderHtml
160+ $ writeHtml opts'{ writerStandalone = True
161+ , writerTemplate = pageTemplate
162+ }
163+ $ case bs of
164+ (Header 1 xs : _) -> Pandoc (Meta xs [] []) bs
165+ _ -> Pandoc (Meta [] [] []) bs
156166
157167 let chapterEntries = zipWith chapToEntry [1..] chunks
158168
@@ -455,15 +465,14 @@ correlateRefs bs = identTable $ execState (mapM_ go bs)
455465 , chapterIdents = [] }
456466 st <- get
457467 let runningid = uniqueIdent ils (runningIdents st)
458− let chapid = if n == 1
459− then Nothing
460− else Just $ uniqueIdent ils (chapterIdents st)
468+ let chapterid = showChapter (chapterNumber st) ++
469+ if n == 1
470+ then ""
471+ else '#' : uniqueIdent ils (chapterIdents st)
461472 modify $ \s -> s{ runningIdents = runningid : runningIdents st
462− , chapterIdents = maybe (chapterIdents st)
463− (: chapterIdents st) chapid
464− , identTable = (runningid,
465− showChapter (chapterNumber st) ++
466− maybe "" ('#':) chapid) : identTable st
473+ , chapterIdents = chapterid : chapterIdents st
474+ , identTable = (runningid, chapterid) :
475+ identTable st
467476 }
468477 go _ = return ()
469478