@@ -44,12 +44,16 @@ import qualified Data.Set as Set
4444import Text.Pandoc.Writers.HTML (writeHtmlString)
4545import Text.Pandoc.Readers.TeXMath (readTeXMath)
4646import Text.HTML.TagSoup (renderTags, parseTags, isTagText, Tag(..))
47+import Data.Default
4748
4849type Notes = [[Block]]
4950type Refs = [([Inline], Target)]
5051data WriterState = WriterState { stNotes :: Notes
51− , stRefs :: Refs
52+ , stRefs :: Refs
53+ , stIds :: [String]
5254 , stPlain :: Bool }
55+instance Default WriterState
56+ where def = WriterState{ stNotes = [], stRefs = [], stIds = [], stPlain = False }
5357
5458-- | Convert Pandoc to Markdown.
5559writeMarkdown :: WriterOptions -> Pandoc -> String
@@ -57,9 +61,7 @@ writeMarkdown opts document =
5761 evalState (pandocToMarkdown opts{
5862 writerWrapText = writerWrapText opts &&
5963 not (isEnabled Ext_hard_line_breaks opts) }
60− document) WriterState{ stNotes = []
61− , stRefs = []
62− , stPlain = False }
64+ document) def
6365
6466-- | Convert Pandoc to plain text (like markdown, but without links,
6567-- pictures, or inline formatting).
@@ -68,9 +70,7 @@ writePlain opts document =
6870 evalState (pandocToMarkdown opts{
6971 writerExtensions = Set.delete Ext_escaped_line_breaks $
7072 writerExtensions opts }
71− document') WriterState{ stNotes = []
72− , stRefs = []
73− , stPlain = True }
73+ document') def{ stPlain = True }
7474 where document' = plainify document
7575
7676plainify :: Pandoc -> Pandoc
@@ -196,9 +196,7 @@ tableOfContents :: WriterOptions -> [Block] -> Doc
196196tableOfContents opts headers =
197197 let opts' = opts { writerIgnoreNotes = True }
198198 contents = BulletList $ map (elementToListItem opts) $ hierarchicalize headers
199− in evalState (blockToMarkdown opts' contents) WriterState{ stNotes = []
200− , stRefs = []
201− , stPlain = False }
199+ in evalState (blockToMarkdown opts' contents) def
202200
203201-- | Converts an Element to a list item for a table of contents,
204202elementToListItem :: WriterOptions -> Element -> [Block]
@@ -275,21 +273,33 @@ blockToMarkdown _ (RawBlock _ _) = return empty
275273blockToMarkdown _ HorizontalRule =
276274 return $ blankline <> text "* * * * *" <> blankline
277275blockToMarkdown opts (Header level attr inlines) = do
276+ -- we calculate the id that would be used by auto_identifiers
277+ -- so we know whether to print an explicit identifier
278+ ids <- gets stIds
279+ let autoId = uniqueIdent inlines ids
280+ modify $ \st -> st{ stIds = autoId : ids }
281+ let attr' = case attr of
282+ ("",[],[]) -> empty
283+ (id',[],[]) | isEnabled Ext_auto_identifiers opts
284+ && id' == autoId -> empty
285+ _ | isEnabled Ext_header_attributes opts ->
286+ space <> attrsToMarkdown attr
287+ | otherwise -> empty
278288 contents <- inlineListToMarkdown opts inlines
279289 st <- get
280290 let setext = writerSetextHeaders opts
281291 return $ nowrap
282292 $ case level of
283293 1 | setext ->
284− contents <> cr <> text (replicate (offset contents) '=') <>
294+ contents <> attr' <> cr <> text (replicate (offset contents) '=') <>
285295 blankline
286296 2 | setext ->
287− contents <> cr <> text (replicate (offset contents) '-') <>
297+ contents <> attr' <> cr <> text (replicate (offset contents) '-') <>
288298 blankline
289299 -- ghc interprets '#' characters in column 1 as linenum specifiers.
290300 _ | stPlain st || isEnabled Ext_literate_haskell opts ->
291301 contents <> blankline
292− _ -> text (replicate level '#') <> space <> contents <> blankline
302+ _ -> text (replicate level '#') <> space <> contents <> attr' <> blankline
293303blockToMarkdown opts (CodeBlock (_,classes,_) str)
294304 | "haskell" `elem` classes && "literate" `elem` classes &&
295305 isEnabled Ext_literate_haskell opts =