@@ -82,6 +82,7 @@ import qualified Data.ByteString.Lazy as B
8282import Data.Default (Default)
8383import Data.List (delete, intersect)
8484import qualified Data.Map as M
85+import Data.Maybe (isJust)
8586import Data.Sequence (ViewL (..), viewl)
8687import qualified Data.Sequence as Seq
8788import qualified Data.Set as Set
@@ -119,6 +120,7 @@ readDocx _ _ =
119120
120121data DState = DState { docxAnchorMap :: M.Map String String
121122 , docxAnchorSet :: Set.Set String
123+ , docxImmedPrevAnchor :: Maybe String
122124 , docxMediaBag :: MediaBag
123125 , docxDropCap :: Inlines
124126 , docxWarnings :: [String]
@@ -130,6 +132,7 @@ data DState = DState { docxAnchorMap :: M.Map String String
130132instance Default DState where
131133 def = DState { docxAnchorMap = M.empty
132134 , docxAnchorSet = mempty
135+ , docxImmedPrevAnchor = Nothing
133136 , docxMediaBag = mempty
134137 , docxDropCap = mempty
135138 , docxWarnings = []
@@ -341,9 +344,26 @@ blocksToInlinesWarn cmtId blks = do
341344 "Docx comment " ++ cmtId ++ " will not retain formatting"
342345 return $ blocksToInlines' blkList
343346
347+-- The majority of work in this function is done in the primted
348+-- subfunction `partPartToInlines'`. We make this wrapper so that we
349+-- don't have to modify `docxImmedPrevAnchor` state after every function.
344350parPartToInlines :: PandocMonad m => ParPart -> DocxContext m Inlines
345−parPartToInlines (PlainRun r) = runToInlines r
346−parPartToInlines (Insertion _ author date runs) = do
351+parPartToInlines parPart =
352+ case parPart of
353+ (BookMark _ anchor) | not $ anchor `elem` dummyAnchors -> do
354+ inHdrBool <- asks docxInHeaderBlock
355+ ils <- parPartToInlines' parPart
356+ immedPrevAnchor <- gets docxImmedPrevAnchor
357+ unless (isJust immedPrevAnchor || inHdrBool)
358+ (modify $ \s -> s{ docxImmedPrevAnchor = Just anchor})
359+ return ils
360+ _ -> do
361+ ils <- parPartToInlines' parPart
362+ modify $ \s -> s{ docxImmedPrevAnchor = Nothing}
363+ return ils
364+parPartToInlines' :: PandocMonad m => ParPart -> DocxContext m Inlines
365+parPartToInlines' (PlainRun r) = runToInlines r
366+parPartToInlines' (Insertion _ author date runs) = do
347367 opts <- asks docxOptions
348368 case readerTrackChanges opts of
349369 AcceptChanges -> smushInlines <$> mapM runToInlines runs
@@ -352,7 +372,7 @@ parPartToInlines (Insertion _ author date runs) = do
352372 ils <- smushInlines <$> mapM runToInlines runs
353373 let attr = ("", ["insertion"], [("author", author), ("date", date)])
354374 return $ spanWith attr ils
355−parPartToInlines (Deletion _ author date runs) = do
375+parPartToInlines' (Deletion _ author date runs) = do
356376 opts <- asks docxOptions
357377 case readerTrackChanges opts of
358378 AcceptChanges -> return mempty
@@ -361,7 +381,7 @@ parPartToInlines (Deletion _ author date runs) = do
361381 ils <- smushInlines <$> mapM runToInlines runs
362382 let attr = ("", ["deletion"], [("author", author), ("date", date)])
363383 return $ spanWith attr ils
364−parPartToInlines (CommentStart cmtId author date bodyParts) = do
384+parPartToInlines' (CommentStart cmtId author date bodyParts) = do
365385 opts <- asks docxOptions
366386 case readerTrackChanges opts of
367387 AllChanges -> do
@@ -370,16 +390,16 @@ parPartToInlines (CommentStart cmtId author date bodyParts) = do
370390 let attr = ("", ["comment-start"], [("id", cmtId), ("author", author), ("date", date)])
371391 return $ spanWith attr ils
372392 _ -> return mempty
373−parPartToInlines (CommentEnd cmtId) = do
393+parPartToInlines' (CommentEnd cmtId) = do
374394 opts <- asks docxOptions
375395 case readerTrackChanges opts of
376396 AllChanges -> do
377397 let attr = ("", ["comment-end"], [("id", cmtId)])
378398 return $ spanWith attr mempty
379399 _ -> return mempty
380−parPartToInlines (BookMark _ anchor) | anchor `elem` dummyAnchors =
400+parPartToInlines' (BookMark _ anchor) | anchor `elem` dummyAnchors =
381401 return mempty
382−parPartToInlines (BookMark _ anchor) =
402+parPartToInlines' (BookMark _ anchor) =
383403 -- We record these, so we can make sure not to overwrite
384404 -- user-defined anchor links with header auto ids.
385405 do
@@ -395,27 +415,34 @@ parPartToInlines (BookMark _ anchor) =
395415 -- of rewriting user-defined anchor links. However, since these
396416 -- are not defined in pandoc, it seems like a necessary evil to
397417 -- avoid an extra pass.
398− let newAnchor =
399− if not inHdrBool && anchor `elem` M.elems anchorMap
400− then uniqueIdent [Str anchor] (Set.fromList $ M.elems anchorMap)
401− else anchor
402− unless inHdrBool
403− (modify $ \s -> s { docxAnchorMap = M.insert anchor newAnchor anchorMap})
404− return $ spanWith (newAnchor, ["anchor"], []) mempty
405−parPartToInlines (Drawing fp title alt bs ext) = do
418+ immedPrevAnchor <- gets docxImmedPrevAnchor
419+ case immedPrevAnchor of
420+ Just prevAnchor -> do
421+ unless inHdrBool
422+ (modify $ \s -> s { docxAnchorMap = M.insert anchor prevAnchor anchorMap})
423+ return mempty
424+ Nothing -> do
425+ let newAnchor =
426+ if not inHdrBool && anchor `elem` M.elems anchorMap
427+ then uniqueIdent [Str anchor] (Set.fromList $ M.elems anchorMap)
428+ else anchor
429+ unless inHdrBool
430+ (modify $ \s -> s { docxAnchorMap = M.insert anchor newAnchor anchorMap})
431+ return $ spanWith (newAnchor, ["anchor"], []) mempty
432+parPartToInlines' (Drawing fp title alt bs ext) = do
406433 (lift . lift) $ P.insertMedia fp Nothing bs
407434 return $ imageWith (extentToAttr ext) fp title $ text alt
408−parPartToInlines Chart =
435+parPartToInlines' Chart =
409436 return $ spanWith ("", ["chart"], []) $ text "[CHART]"
410−parPartToInlines (InternalHyperLink anchor runs) = do
437+parPartToInlines' (InternalHyperLink anchor runs) = do
411438 ils <- smushInlines <$> mapM runToInlines runs
412439 return $ link ('#' : anchor) "" ils
413−parPartToInlines (ExternalHyperLink target runs) = do
440+parPartToInlines' (ExternalHyperLink target runs) = do
414441 ils <- smushInlines <$> mapM runToInlines runs
415442 return $ link target "" ils
416−parPartToInlines (PlainOMath exps) =
443+parPartToInlines' (PlainOMath exps) =
417444 return $ math $ writeTeX exps
418−parPartToInlines (SmartTag runs) = do
445+parPartToInlines' (SmartTag runs) = do
419446 smushInlines <$> mapM runToInlines runs
420447
421448isAnchorSpan :: Inline -> Bool