@@ -40,13 +40,13 @@ import System.Time
4040import Text.Pandoc.Shared hiding ( Element )
4141import Text.Pandoc.Definition
4242import Text.Pandoc.Generic
43−import Control.Monad (liftM)
43+import Control.Monad.State
4444import Text.XML.Light hiding (ppTopElement)
4545import Text.Pandoc.UUID
4646import Text.Pandoc.Writers.HTML
4747import Text.Pandoc.Writers.Markdown ( writePlain )
4848import Data.Char ( toLower )
49−import Network.URI ( unEscapeString, isRelativeReference )
49+import Network.URI ( unEscapeString )
5050
5151-- | Produce an EPUB file from a Pandoc document.
5252writeEPUB :: Maybe String -- ^ EPUB stylesheet specified at command line
@@ -104,12 +104,16 @@ writeEPUB mbStylesheet opts doc@(Pandoc meta _) = do
104104 -- body pages
105105 let isH1 (Header 1 _) = True
106106 isH1 _ = False
107− let h1Indices = dropWhile (== 0) $ findIndices isH1 blocks
108− let chunks = splitByIndices h1Indices blocks
107+ -- internal reference IDs change when we chunk the file,
108+ -- so the next two lines fix that:
109+ let reftable = correlateRefs blocks
110+ let blocks' = replaceRefs reftable blocks
111+ let h1Indices = dropWhile (== 0) $ findIndices isH1 blocks'
112+ let chunks = splitByIndices h1Indices blocks'
109113 let titleize (Header 1 xs : ys) = Pandoc meta{docTitle = xs} ys
110114 titleize xs = Pandoc meta xs
111− let chapToHtml = writeHtmlString opts'{ writerTemplate = pageTemplate }
112115 let chapters = map titleize chunks
116+ let chapToHtml = writeHtmlString opts'{ writerTemplate = pageTemplate }
113117 let chapterToEntry :: Int -> Pandoc -> Entry
114118 chapterToEntry num chap = mkEntry ("ch" ++ show num ++ ".xhtml") $
115119 fromString $ chapToHtml chap
@@ -271,7 +275,6 @@ transformInlines (MathML _) _ _ (x@(Math _ _) : xs) = do
271275 result = if "<math" `isPrefixOf` mathml then inOps else mathml
272276 return $ RawInline "html" result : xs
273277transformInlines _ _ _ (RawInline _ _ : xs) = return $ Str "" : xs
274−transformInlines _ _ _ (Link lab (src,_) : xs) | isRelativeReference src = return $ lab ++ xs
275278transformInlines _ _ _ xs = return xs
276279
277280transformBlock :: Block -> Block
@@ -305,3 +308,49 @@ imageTypeOf x = case drop 1 (map toLower (takeExtension x)) of
305308 "svg" -> Just "image/svg+xml"
306309 _ -> Nothing
307310
311+
312+data IdentState = IdentState{
313+ chapterNumber :: Int,
314+ runningIdents :: [String],
315+ chapterIdents :: [String],
316+ identTable :: [(String,String)]
317+ } deriving (Read, Show)
318+
319+-- Go through a block list and construct a table
320+-- correlating the automatically constructed references
321+-- that would be used in a normal pandoc document with
322+-- new URLs to be used in the EPUB. For example, what
323+-- was "header-1" might turn into "ch6.xhtml#header".
324+correlateRefs :: [Block] -> [(String,String)]
325+correlateRefs bs = identTable $ execState (mapM_ go bs)
326+ IdentState{ chapterNumber = 0
327+ , runningIdents = []
328+ , chapterIdents = []
329+ , identTable = [] }
330+ where go :: Block -> State IdentState ()
331+ go (Header n ils) = do
332+ when (n == 1) $
333+ modify $ \s -> s{ chapterNumber = chapterNumber s + 1
334+ , chapterIdents = [] }
335+ st <- get
336+ let runningid = uniqueIdent ils (runningIdents st)
337+ let chapid = if n == 1
338+ then Nothing
339+ else Just $ uniqueIdent ils (chapterIdents st)
340+ modify $ \s -> s{ runningIdents = runningid : runningIdents st
341+ , chapterIdents = maybe (chapterIdents st)
342+ (: chapterIdents st) chapid
343+ , identTable = (runningid, "ch" ++ show (chapterNumber st) ++
344+ ".xhtml" ++ maybe "" ('#':) chapid) : identTable st
345+ }
346+ go _ = return ()
347+
348+-- Replace internal link references using the table produced
349+-- by correlateRefs.
350+replaceRefs :: [(String,String)] -> [Block] -> [Block]
351+replaceRefs refTable = bottomUp replaceOneRef
352+ where replaceOneRef x@(Link lab ('#':xs,tit)) =
353+ case lookup xs refTable of
354+ Just url -> Link lab (url,tit)
355+ Nothing -> x
356+ replaceOneRef x = x