@@ -34,12 +34,12 @@ Conversion of 'Pandoc' documents to markdown-formatted plain text.
34Markdown: <http://daringfireball.net/projects/markdown/>
34Markdown: <http://daringfireball.net/projects/markdown/>
36module Text.Pandoc.Writers.Markdown (writeMarkdown, writePlain) where
36module Text.Pandoc.Writers.Markdown (writeMarkdown, writePlain) where
37−import Control.Monad.Except (throwError)
38import Control.Monad.Reader
37import Control.Monad.Reader
39import Control.Monad.State
38import Control.Monad.State
40import Data.Char (chr, isPunctuation, isSpace, ord)
39import Data.Char (chr, isPunctuation, isSpace, ord)
41import Data.Default
40import Data.Default
42import qualified Data.HashMap.Strict as H
41import qualified Data.HashMap.Strict as H
42+import qualified Data.Map as M
43import Data.List (find, group, intersperse, sortBy, stripPrefix, transpose)
43import Data.List (find, group, intersperse, sortBy, stripPrefix, transpose)
44import Data.Maybe (fromMaybe)
44import Data.Maybe (fromMaybe)
45import Data.Monoid (Any (..))
45import Data.Monoid (Any (..))
@@ -52,7 +52,6 @@ import Network.HTTP (urlEncode)
52import Text.HTML.TagSoup (Tag (..), isTagText, parseTags)
52import Text.HTML.TagSoup (Tag (..), isTagText, parseTags)
53import Text.Pandoc.Class (PandocMonad, report)
53import Text.Pandoc.Class (PandocMonad, report)
54import Text.Pandoc.Definition
54import Text.Pandoc.Definition
55−import Text.Pandoc.Error
56import Text.Pandoc.Logging
55import Text.Pandoc.Logging
57import Text.Pandoc.Options
56import Text.Pandoc.Options
58import Text.Pandoc.Parsing hiding (blankline, blanklines, char, space)
57import Text.Pandoc.Parsing hiding (blankline, blanklines, char, space)
@@ -90,7 +89,9 @@ instance Default WriterEnv
91data WriterState = WriterState { stNotes :: Notes
90data WriterState = WriterState { stNotes :: Notes
92 , stRefs :: Refs
91 , stRefs :: Refs
93− , stKeys :: Set.Set Key
92+ , stKeys :: M.Map Key
93+ (M.Map (Target, Attr) Int)
94 , stIds :: Set.Set String
95 , stIds :: Set.Set String
95 , stNoteNum :: Int
96 , stNoteNum :: Int
@@ -98,7 +99,8 @@ data WriterState = WriterState { stNotes :: Notes
98instance Default WriterState
99instance Default WriterState
99 where def = WriterState{ stNotes = []
100 where def = WriterState{ stNotes = []
100 , stRefs = []
101 , stRefs = []
101− , stKeys = Set.empty
102+ , stKeys = M.empty
102 , stIds = Set.empty
104 , stIds = Set.empty
103 , stNoteNum = 1
105 , stNoteNum = 1
@@ -804,17 +806,44 @@ getReference attr label target = do
804 Just (ref, _, _) -> return ref
806 Just (ref, _, _) -> return ref
805 Nothing -> do
807 Nothing -> do
806 keys <- gets stKeys
808 keys <- gets stKeys
807− label' <- if isEmpty label || getKey label `Set.member` keys
809+ case M.lookup (getKey label) keys of
808− then case find (\n -> not (Key n `Set.member` keys)) $
810+ Nothing -> do -- no other refs with this label
809− map show [1..(10000 :: Integer)] of
811+ (lab', idx) <- if isEmpty label
810− Just x -> return $ text x
812+ then do
811− Nothing ->
813+ i <- (+ 1) <$> gets stLastIdx
812− throwError $ PandocSomeError "no unique label"
814+ modify $ \s -> s{ stLastIdx = i }
815+ return (text (show i), i)
813− else return label
816+ else return (label, 0)
814− modify (\s -> s{ stRefs = (label', target, attr) : stRefs s,
817+ modify (\s -> s{
818+ stRefs = (lab', target, attr) : refs,
819+ stKeys = M.insert (getKey label)
820+ (M.insert (target, attr) idx mempty)
824+ Just km -> do -- we have refs with this label
825+ case M.lookup (target, attr) km of
827+ let lab' = label <> if i == 0
830+ -- make sure it's in stRefs; it may be
831+ -- a duplicate that was printed in a previous
833+ when ((lab', target, attr) `notElem` refs) $
835+ stRefs = (lab', target, attr) : refs })
837+ Nothing -> do -- but this one is to a new target
838+ i <- (+ 1) <$> gets stLastIdx
839+ modify $ \s -> s{ stLastIdx = i }
840+ let lab' = text (show i)
842+ stRefs = (lab', target, attr) : refs,
815− stKeys = Set.insert (getKey label') (stKeys s)
843+ stKeys = M.insert (getKey label)
816− })
844+ (M.insert (target, attr) i km)
817− return label'
846+ return lab'
819-- | Convert list of Pandoc inline elements to markdown.
848-- | Convert list of Pandoc inline elements to markdown.
820inlineListToMarkdown :: PandocMonad m => WriterOptions -> [Inline] -> MD m Doc
849inlineListToMarkdown :: PandocMonad m => WriterOptions -> [Inline] -> MD m Doc