@@ -70,23 +70,27 @@ evalMD md env st = evalState (runReaderT md env) st
7070data WriterEnv = WriterEnv { envInList :: Bool
7171 , envPlain :: Bool
7272 , envRefShortcutable :: Bool
73+ , envBlockLevel :: Int
7374 }
7475
7576instance Default WriterEnv
7677 where def = WriterEnv { envInList = False
7778 , envPlain = False
7879 , envRefShortcutable = True
80+ , envBlockLevel = 0
7981 }
8082
8183data WriterState = WriterState { stNotes :: Notes
8284 , stRefs :: Refs
8385 , stIds :: Set.Set String
86+ , stNoteNum :: Int
8487 }
8588
8689instance Default WriterState
8790 where def = WriterState{ stNotes = []
8891 , stRefs = []
8992 , stIds = Set.empty
93+ , stNoteNum = 1
9094 }
9195
9296-- | Convert Pandoc to Markdown.
@@ -238,9 +242,11 @@ keyToMarkdown opts (label, (src, tit), attr) = do
238242
239243-- | Return markdown representation of notes.
240244notesToMarkdown :: WriterOptions -> [[Block]] -> MD Doc
241−notesToMarkdown opts notes =
242− mapM (\(num, note) -> noteToMarkdown opts num note) (zip [1..] notes) >>=
243− return . vsep
245+notesToMarkdown opts notes = do
246+ n <- gets stNoteNum
247+ notes' <- mapM (\(num, note) -> noteToMarkdown opts num note) (zip [n..] notes)
248+ modify $ \st -> st { stNoteNum = stNoteNum st + length notes }
249+ return $ vsep notes'
244250
245251-- | Return markdown representation of a note.
246252noteToMarkdown :: WriterOptions -> Int -> [Block] -> MD Doc
@@ -335,15 +341,35 @@ beginsWithOrderedListMarker str =
335341blockToMarkdown :: WriterOptions -- ^ Options
336342 -> Block -- ^ Block element
337343 -> MD Doc
338−blockToMarkdown _ Null = return empty
339−blockToMarkdown opts (Div attrs ils) = do
344+blockToMarkdown opts blk =
345+ local (\env -> env {envBlockLevel = envBlockLevel env + 1}) $
346+ do doc <- blockToMarkdown' opts blk
347+ blkLevel <- asks envBlockLevel
348+ if writerReferenceLocation opts == EndOfBlock && blkLevel == 1
349+ then do st <- get
350+ notes' <- notesToMarkdown opts (reverse $ stNotes st)
351+ modify $ \s -> s { stNotes = [] }
352+ st' <- get -- note that the notes may contain refs
353+ refs' <- refsToMarkdown opts (reverse $ stRefs st')
354+ modify $ \s -> s { stRefs = [] }
355+ return $ doc <>
356+ (if isEmpty notes' then empty else blankline <> notes') <>
357+ (if isEmpty refs' then empty else blankline <> refs') <>
358+ (if (isEmpty notes' && isEmpty refs') then empty else blankline)
359+ else return doc
360+
361+blockToMarkdown' :: WriterOptions -- ^ Options
362+ -> Block -- ^ Block element
363+ -> MD Doc
364+blockToMarkdown' _ Null = return empty
365+blockToMarkdown' opts (Div attrs ils) = do
340366 contents <- blockListToMarkdown opts ils
341367 return $ if isEnabled Ext_raw_html opts &&
342368 isEnabled Ext_markdown_in_html_blocks opts
343369 then tagWithAttrs "div" attrs <> blankline <>
344370 contents <> blankline <> "</div>" <> blankline
345371 else contents <> blankline
346−blockToMarkdown opts (Plain inlines) = do
372+blockToMarkdown' opts (Plain inlines) = do
347373 contents <- inlineListToMarkdown opts inlines
348374 -- escape if para starts with ordered list marker
349375 isPlain <- asks envPlain
@@ -360,11 +386,11 @@ blockToMarkdown opts (Plain inlines) = do
360386 else contents
361387 return $ contents' <> cr
362388-- title beginning with fig: indicates figure
363−blockToMarkdown opts (Para [Image attr alt (src,'f':'i':'g':':':tit)]) =
389+blockToMarkdown' opts (Para [Image attr alt (src,'f':'i':'g':':':tit)]) =
364390 blockToMarkdown opts (Para [Image attr alt (src,tit)])
365−blockToMarkdown opts (Para inlines) =
391+blockToMarkdown' opts (Para inlines) =
366392 (<> blankline) `fmap` blockToMarkdown opts (Plain inlines)
367−blockToMarkdown opts (RawBlock f str)
393+blockToMarkdown' opts (RawBlock f str)
368394 | f == "markdown" = return $ text str <> text "\n"
369395 | f == "html" && isEnabled Ext_raw_html opts = do
370396 plain <- asks envPlain
@@ -379,9 +405,25 @@ blockToMarkdown opts (RawBlock f str)
379405 then empty
380406 else text str <> text "\n"
381407 | otherwise = return empty
382−blockToMarkdown opts HorizontalRule = do
408+blockToMarkdown' opts HorizontalRule = do
383409 return $ blankline <> text (replicate (writerColumns opts) '-') <> blankline
384−blockToMarkdown opts (Header level attr inlines) = do
410+blockToMarkdown' opts (Header level attr inlines) = do
411+ -- first, if we're putting references at the end of a section, we
412+ -- put them here.
413+ blkLevel <- asks envBlockLevel
414+ refs <- if writerReferenceLocation opts == EndOfSection && blkLevel == 1
415+ then do st <- get
416+ notes' <- notesToMarkdown opts (reverse $ stNotes st)
417+ modify $ \s -> s { stNotes = [] }
418+ st' <- get -- note that the notes may contain refs
419+ refs' <- refsToMarkdown opts (reverse $ stRefs st')
420+ modify $ \s -> s { stRefs = [] }
421+ return $
422+ (if isEmpty notes' then empty else blankline <> notes') <>
423+ (if isEmpty refs' then empty else blankline <> refs') <>
424+ (if (isEmpty notes' && isEmpty refs') then empty else blankline)
425+ else return empty
426+
385427 plain <- asks envPlain
386428 -- we calculate the id that would be used by auto_identifiers
387429 -- so we know whether to print an explicit identifier
@@ -402,8 +444,7 @@ blockToMarkdown opts (Header level attr inlines) = do
402444 then capitalize inlines
403445 else inlines
404446 let setext = writerSetextHeaders opts
405− return $ nowrap
406− $ case level of
447+ hdr = nowrap $ case level of
407448 1 | plain -> blanklines 3 <> contents <> blanklines 2
408449 | setext ->
409450 contents <> attr' <> cr <> text (replicate (offset contents) '=') <>
@@ -416,11 +457,13 @@ blockToMarkdown opts (Header level attr inlines) = do
416457 _ | plain || isEnabled Ext_literate_haskell opts ->
417458 contents <> blankline
418459 _ -> text (replicate level '#') <> space <> contents <> attr' <> blankline
419−blockToMarkdown opts (CodeBlock (_,classes,_) str)
460+
461+ return $ refs <> hdr
462+blockToMarkdown' opts (CodeBlock (_,classes,_) str)
420463 | "haskell" `elem` classes && "literate" `elem` classes &&
421464 isEnabled Ext_literate_haskell opts =
422465 return $ prefixed "> " (text str) <> blankline
423−blockToMarkdown opts (CodeBlock attribs str) = return $
466+blockToMarkdown' opts (CodeBlock attribs str) = return $
424467 case attribs == nullAttr of
425468 False | isEnabled Ext_backtick_code_blocks opts ->
426469 backticks <> attrs <> cr <> text str <> cr <> backticks <> blankline
@@ -442,7 +485,7 @@ blockToMarkdown opts (CodeBlock attribs str) = return $
442485 else case attribs of
443486 (_,(cls:_),_) -> " " <> text cls
444487 _ -> empty
445−blockToMarkdown opts (BlockQuote blocks) = do
488+blockToMarkdown' opts (BlockQuote blocks) = do
446489 plain <- asks envPlain
447490 -- if we're writing literate haskell, put a space before the bird tracks
448491 -- so they won't be interpreted as lhs...
@@ -451,7 +494,7 @@ blockToMarkdown opts (BlockQuote blocks) = do
451494 else if plain then " " else "> "
452495 contents <- blockListToMarkdown opts blocks
453496 return $ (prefixed leader contents) <> blankline
454−blockToMarkdown opts t@(Table caption aligns widths headers rows) = do
497+blockToMarkdown' opts t@(Table caption aligns widths headers rows) = do
455498 caption' <- inlineListToMarkdown opts caption
456499 let caption'' = if null caption || not (isEnabled Ext_table_captions opts)
457500 then empty
@@ -485,10 +528,10 @@ blockToMarkdown opts t@(Table caption aligns widths headers rows) = do
485528 $ Pandoc nullMeta [t]
486529 | otherwise -> return $ (id, text "[TABLE]")
487530 return $ nst $ tbl $$ blankline $$ caption'' $$ blankline
488−blockToMarkdown opts (BulletList items) = do
531+blockToMarkdown' opts (BulletList items) = do
489532 contents <- inList $ mapM (bulletListItemToMarkdown opts) items
490533 return $ cat contents <> blankline
491−blockToMarkdown opts (OrderedList (start,sty,delim) items) = do
534+blockToMarkdown' opts (OrderedList (start,sty,delim) items) = do
492535 let start' = if isEnabled Ext_startnum opts then start else 1
493536 let sty' = if isEnabled Ext_fancy_lists opts then sty else DefaultStyle
494537 let delim' = if isEnabled Ext_fancy_lists opts then delim else DefaultDelim
@@ -501,7 +544,7 @@ blockToMarkdown opts (OrderedList (start,sty,delim) items) = do
501544 mapM (\(item, num) -> orderedListItemToMarkdown opts item num) $
502545 zip markers' items
503546 return $ cat contents <> blankline
504−blockToMarkdown opts (DefinitionList items) = do
547+blockToMarkdown' opts (DefinitionList items) = do
505548 contents <- inList $ mapM (definitionListItemToMarkdown opts) items
506549 return $ cat contents <> blankline
507550
@@ -1009,7 +1052,7 @@ inlineToMarkdown opts img@(Image attr alternate (source, tit))
10091052inlineToMarkdown opts (Note contents) = do
10101053 modify (\st -> st{ stNotes = contents : stNotes st })
10111054 st <- get
1012− let ref = text $ writerIdentifierPrefix opts ++ show (length $ stNotes st)
1055+ let ref = text $ writerIdentifierPrefix opts ++ show (stNoteNum st + (length $ stNotes st) - 1)
10131056 if isEnabled Ext_footnotes opts
10141057 then return $ "[^" <> ref <> "]"
10151058 else return $ "[" <> ref <> "]"