git.iko.soy/typeable/pandoc
on master help sign in
Docx Reader: Introduce link rewriting.
commitdce360e1e6fee089e849c07785d8e21961fefb9b authorJesse Rosenthal <jrosenthal@jhu.edu> dateSat 28 Jun 2014, 03:54 (12 years ago) parentb89a3ba
1 file changed+30−7
src/Text/Pandoc/Readers/Docx.hs+30−7
src/Text/Pandoc/Readers/Docx.hs+30−7
@@ -104,7 +104,7 @@ readDocx opts bytes =
104104 Nothing -> error $ "couldn't parse docx file"
105105
106106
107−data DState = DState { docxHeaderAnchors :: M.Map String String }
107+data DState = DState { docxAnchorMap :: M.Map String String }
108108
109109data DEnv = DEnv { docxOptions :: ReaderOptions
110110 , docxDocument :: Docx}
@@ -276,7 +276,22 @@ parPartToInlines (Deletion _ author date runs) = do
276276 ("", ["deletion"], [("author", author), ("date", date)])
277277 ils]
278278parPartToInlines (BookMark _ anchor) | anchor `elem` dummyAnchors = return []
279−parPartToInlines (BookMark _ anchor) = return [Span (anchor, ["anchor"], []) []]
279+parPartToInlines (BookMark _ anchor) =
280+ -- We record these, so we can make sure not to overwrite
281+ -- user-defined anchor links with header auto ids.
282+ do
283+ -- Get the anchor map.
284+ anchorMap <- gets docxAnchorMap
285+ -- Check to see if the id is already in there. Rewrite if
286+ -- necessary. This will have the possible effect of rewriting
287+ -- user-defined anchor links. However, since these are not defined
288+ -- in pandoc, it seems like a necessary evil to avoid an extra
289+ -- pass.
290+ let newAnchor = case anchor `elem` (M.elems anchorMap) of
291+ True -> uniqueIdent [Str anchor] (M.elems anchorMap)
292+ False -> anchor
293+ put DState{ docxAnchorMap = M.insert anchor newAnchor anchorMap}
294+ return [Span (anchor, ["anchor"], []) []]
280295parPartToInlines (Drawing relid) = do
281296 (Docx _ _ _ rels _) <- asks docxDocument
282297 return $ case lookupRelationship relid rels of
@@ -311,9 +326,9 @@ makeHeaderAnchor (Header n (_, classes, kvs) ils)
311326 , (Span (ident, _, _) _) <- x
312327 , notElem ident dummyAnchors =
313328 do
314− hdrIDMap <- gets docxHeaderAnchors
329+ hdrIDMap <- gets docxAnchorMap
315330 let newIdent = uniqueIdent ils (M.elems hdrIDMap)
316− put DState{docxHeaderAnchors = M.insert ident newIdent hdrIDMap}
331+ put DState{docxAnchorMap = M.insert ident newIdent hdrIDMap}
317332 return $ Header n (newIdent, classes, kvs) (ils \\ (x:xs))
318333makeHeaderAnchor blk = return blk
319334
@@ -411,6 +426,14 @@ bodyPartToBlocks (Tbl cap _ look (r:rs)) = do
411426
412427 return [Table caption alignments widths hdrCells cells]
413428
429+-- replace targets with generated anchors.
430+rewriteLink :: Inline -> DocxContext Inline
431+rewriteLink l@(Link ils ('#':target, title)) = do
432+ anchorMap <- gets docxAnchorMap
433+ return $ case M.lookup target anchorMap of
434+ Just newTarget -> (Link ils ('#':newTarget, title))
435+ Nothing -> l
436+rewriteLink il = return il
414437
415438makeImagesSelfContained :: Inline -> DocxContext Inline
416439makeImagesSelfContained i@(Image alt (uri, title)) = do
@@ -429,14 +452,15 @@ makeImagesSelfContained inline = return inline
429452
430453bodyToBlocks :: Body -> DocxContext [Block]
431454bodyToBlocks (Body bps) = do
432− blks <- concatMapM bodyPartToBlocks bps
455+ blks <- concatMapM bodyPartToBlocks bps >>=
456+ walkM rewriteLink
433457 return $
434458 blocksToDefinitions $
435459 blocksToBullets $ blks
436460
437461docxToBlocks :: ReaderOptions -> Docx -> [Block]
438462docxToBlocks opts d@(Docx (Document _ body) _ _ _ _) =
439− let dState = DState { docxHeaderAnchors = M.empty }
463+ let dState = DState { docxAnchorMap = M.empty }
440464 dEnv = DEnv { docxOptions = opts
441465 , docxDocument = d}
442466 in
@@ -447,7 +471,6 @@ ilToCode (Str s) = s
447471ilToCode Space = " "
448472ilToCode _ = ""
449473
450−
451474isHeaderClass :: String -> Maybe Int
452475isHeaderClass s | "Heading" `isPrefixOf` s =
453476 case reads (drop (length "Heading") s) :: [(Int, String)] of