@@ -56,10 +56,10 @@ import Text.Pandoc.Options ( WriterOptions(..)
5656 , EPUBVersion(..)
5757 , ObfuscationMethod(NoObfuscation) )
5858import Text.Pandoc.Definition
59−import Text.Pandoc.Walk (walk, walkM)
59+import Text.Pandoc.Walk (walk, walkM, query)
6060import Data.Default
6161import Text.Pandoc.Writers.Markdown (writePlain)
62−import Control.Monad.State (modify, get, execState, State, put, evalState)
62+import Control.Monad.State (modify, get, State, put, evalState)
6363import Control.Monad (mplus, liftM, when)
6464import Text.XML.Light ( unode, Element(..), unqual, Attr(..), add_attrs
6565 , strContent, lookupAttr, Node(..), QName(..), parseXML
@@ -408,11 +408,6 @@ writeEPUB opts doc@(Pandoc meta _) = do
408408 (docTitle' meta) : blocks
409409
410410 let chapterHeaderLevel = writerEpubChapterLevel opts
411− -- internal reference IDs change when we chunk the file,
412− -- so that '#my-header-1' might turn into 'chap004.xhtml#my-header'.
413− -- the next two lines fix that:
414− let reftable = correlateRefs chapterHeaderLevel blocks'
415− let blocks'' = replaceRefs reftable blocks'
416411
417412 let isChapterHeader (Header n _ _) = n <= chapterHeaderLevel
418413 isChapterHeader (Div ("",["references"],[]) (Header n _ _:_)) =
@@ -443,7 +438,37 @@ writeEPUB opts doc@(Pandoc meta _) = do
443438 let (xs,ys) = break isChapterHeader bs
444439 (Chapter Nothing (b:xs) :) `fmap` toChapters ys
445440
446− let chapters = evalState (toChapters blocks'') []
441+ let chapters' = evalState (toChapters blocks') []
442+
443+ let extractLinkURL' :: Int -> Inline -> [(String, String)]
444+ extractLinkURL' num (Span (ident, _, _) _)
445+ | not (null ident) = [(ident, showChapter num ++ ('#':ident))]
446+ extractLinkURL' _ _ = []
447+
448+ let extractLinkURL :: Int -> Block -> [(String, String)]
449+ extractLinkURL num (Div (ident, _, _) _)
450+ | not (null ident) = [(ident, showChapter num ++ ('#':ident))]
451+ extractLinkURL num (Header _ (ident, _, _) _)
452+ | not (null ident) = [(ident, showChapter num ++ ('#':ident))]
453+ extractLinkURL num b = query (extractLinkURL' num) b
454+
455+ let reftable = concat $ zipWith (\(Chapter _ bs) num ->
456+ query (extractLinkURL num) bs)
457+ chapters' [1..]
458+
459+ let fixInternalReferences :: Inline -> Inline
460+ fixInternalReferences (Link lab ('#':xs, tit)) =
461+ case lookup xs reftable of
462+ Just ys -> Link lab (ys, tit)
463+ Nothing -> Link lab ('#':xs, tit)
464+ fixInternalReferences x = x
465+
466+ -- internal reference IDs change when we chunk the file,
467+ -- so that '#my-header-1' might turn into 'chap004.xhtml#my-header'.
468+ -- this fixes that:
469+ let chapters = map (\(Chapter mbnum bs) ->
470+ Chapter mbnum $ walk fixInternalReferences bs)
471+ chapters'
447472
448473 let chapToEntry :: Int -> Chapter -> Entry
449474 chapToEntry num (Chapter mbnum bs) = mkEntry (showChapter num)
@@ -549,7 +574,7 @@ writeEPUB opts doc@(Pandoc meta _) = do
549574 let contentsEntry = mkEntry "content.opf" contentsData
550575
551576 -- toc.ncx
552− let secs = hierarchicalize blocks''
577+ let secs = hierarchicalize blocks'
553578
554579 let tocLevel = writerTOCDepth opts
555580
@@ -889,11 +914,6 @@ mediaTypeOf x =
889914 Just y | any (`isPrefixOf` y) mediaPrefixes -> Just y
890915 _ -> Nothing
891916
892−data IdentState = IdentState{
893− chapterNumber :: Int,
894− identTable :: [(String,String)]
895− } deriving (Read, Show)
896−
897917-- Returns filename for chapter number.
898918showChapter :: Int -> String
899919showChapter = printf "ch%03d.xhtml"
@@ -910,45 +930,6 @@ addIdentifiers bs = evalState (mapM go bs) []
910930 return $ Header n (ident',classes,kvs) ils
911931 go x = return x
912932
913−-- Go through a block list and construct a table
914−-- correlating the automatically constructed references
915−-- that would be used in a normal pandoc document with
916−-- new URLs to be used in the EPUB. For example, what
917−-- was "header-1" might turn into "ch006.xhtml#header".
918−correlateRefs :: Int -> [Block] -> [(String,String)]
919−correlateRefs chapterHeaderLevel bs =
920− identTable $ execState (walkM goBlock bs >>= walkM goInline)
921− IdentState{ chapterNumber = 0
922− , identTable = [] }
923− where goBlock :: Block -> State IdentState Block
924− goBlock x@(Header n (ident,_,_) _) = x <$ addIdentifier (Just n) ident
925− goBlock x@(Div (ident,_,_) _) = x <$ addIdentifier Nothing ident
926− goBlock x = return x
927− goInline :: Inline -> State IdentState Inline
928− goInline x@(Span (ident,_,_) _) = x <$ addIdentifier Nothing ident
929− goInline x = return x
930− addIdentifier mbHeaderLevel ident = do
931− case mbHeaderLevel of
932− Just n | n <= chapterHeaderLevel ->
933− modify $ \s -> s{ chapterNumber = chapterNumber s + 1 }
934− _ -> return ()
935− st <- get
936− let chapterid = showChapter (chapterNumber st) ++
937− case mbHeaderLevel of
938− Just n | n <= chapterHeaderLevel -> ""
939− _ -> '#' : ident
940− modify $ \s -> s{ identTable = (ident, chapterid) : identTable st }
941−
942−-- Replace internal link references using the table produced
943−-- by correlateRefs.
944−replaceRefs :: [(String,String)] -> [Block] -> [Block]
945−replaceRefs refTable = walk replaceOneRef
946− where replaceOneRef x@(Link lab ('#':xs,tit)) =
947− case lookup xs refTable of
948− Just url -> Link lab (url,tit)
949− Nothing -> x
950− replaceOneRef x = x
951−
952933-- Variant of normalizeDate that allows partial dates: YYYY, YYYY-MM
953934normalizeDate' :: String -> Maybe String
954935normalizeDate' xs =