git.iko.soy/typeable/pandoc
on master help sign in
Markdown writer: Handle labels with integer names

Previously if labels had integer names, it could produce a conflict with auto-labeled reference links. Now we test for a conflict and find the next available integer. Note that this involves adding a new state variable `stPrevRefs` to keep track of refs used in other document parts when using `--reference-location=block|section` Closes #5495

commited73bd28e511f72b17fc84126da85410e13b396b authorJesse Rosenthal <jrosenthal@jhu.edu> dateTue 21 May 2019, 11:31 (7 years ago) parent6208d4e
2 files changed+38−3
src/Text/Pandoc/Writers/Markdown.hs+20−3 test/command/5495.md+18
src/Text/Pandoc/Writers/Markdown.hs+20−3
@@ -75,6 +75,7 @@ instance Default WriterEnv
7575 }
7676
7777data WriterState = WriterState { stNotes :: Notes
78+ , stPrevRefs :: Refs
7879 , stRefs :: Refs
7980 , stKeys :: M.Map Key
8081 (M.Map (Target, Attr) Int)
@@ -85,6 +86,7 @@ data WriterState = WriterState { stNotes :: Notes
8586
8687instance Default WriterState
8788 where def = WriterState{ stNotes = []
89+ , stPrevRefs = []
8890 , stRefs = []
8991 , stKeys = M.empty
9092 , stLastIdx = 0
@@ -355,7 +357,8 @@ notesAndRefs opts = do
355357 notes' <- reverse <$> gets stNotes >>= notesToMarkdown opts
356358 modify $ \s -> s { stNotes = [] }
357359 refs' <- reverse <$> gets stRefs >>= refsToMarkdown opts
358− modify $ \s -> s { stRefs = [] }
360+ modify $ \s -> s { stPrevRefs = stPrevRefs s ++ stRefs s
361+ , stRefs = []}
359362
360363 let endSpacing =
361364 if | writerReferenceLocation opts == EndOfDocument -> empty
@@ -867,6 +870,20 @@ blockListToMarkdown opts blocks = do
867870getKey :: Doc -> Key
868871getKey = toKey . render Nothing
869872
873+findUsableIndex :: [Doc] -> Int -> Int
874+findUsableIndex lbls i = do
875+ if (text (show i)) `elem` lbls
876+ then findUsableIndex lbls (i + 1)
877+ else i
878+
879+getNextIndex :: PandocMonad m => MD m Int
880+getNextIndex = do
881+ prevRefs <- gets stPrevRefs
882+ refs <- gets stRefs
883+ i <- (+ 1) <$> gets stLastIdx
884+ let refLbls = map (\(r,_,_) -> r) $ prevRefs ++ refs
885+ return $ findUsableIndex refLbls i
886+
870887-- | Get reference for target; if none exists, create unique one and return.
871888-- Prefer label if possible; otherwise, generate a unique key.
872889getReference :: PandocMonad m => Attr -> Doc -> Target -> MD m Doc
@@ -880,7 +897,7 @@ getReference attr label target = do
880897 Nothing -> do -- no other refs with this label
881898 (lab', idx) <- if isEmpty label
882899 then do
883− i <- (+ 1) <$> gets stLastIdx
900+ i <- getNextIndex
884901 modify $ \s -> s{ stLastIdx = i }
885902 return (text (show i), i)
886903 else return (label, 0)
@@ -905,7 +922,7 @@ getReference attr label target = do
905922 stRefs = (lab', target, attr) : refs })
906923 return lab'
907924 Nothing -> do -- but this one is to a new target
908− i <- (+ 1) <$> gets stLastIdx
925+ i <- getNextIndex
909926 modify $ \s -> s{ stLastIdx = i }
910927 let lab' = text (show i)
911928 modify (\s -> s{
test/command/5495.mdnew file+18
@@ -0,0 +1,18 @@
1+```
2+% pandoc -t markdown --reference-links
3+All because of [1](#one) link...
4+
5+[This](#foo) will break Pandoc.
6+
7+[This](#bar) will make you laugh.
8+^D
9+All because of [1] link...
10+
11+[This] will break Pandoc.
12+
13+[This][2] will make you laugh.
14+
15+ [1]: #one
16+ [This]: #foo
17+ [2]: #bar
18+```