@@ -54,6 +54,8 @@ import Text.HTML.TagSoup
5454import Text.HTML.TagSoup.Match (tagOpen)
5555import qualified Data.Set as Set
5656
57+type MarkdownParser = Parser [Char] ParserState
58+
5759-- | Read markdown from an input string and return a Pandoc document.
5860readMarkdown :: ReaderOptions -- ^ Reader options
5961 -> String -- ^ String to parse (assuming @'\n'@ line endings)
@@ -103,13 +105,13 @@ spnl = try $ do
103105 skipSpaces
104106 notFollowedBy (char '\n')
105107
106−indentSpaces :: Parser [Char] ParserState String
108+indentSpaces :: MarkdownParser String
107109indentSpaces = try $ do
108110 tabStop <- getOption readerTabStop
109111 count tabStop (char ' ') <|>
110112 string "\t" <?> "indentation"
111113
112−nonindentSpaces :: Parser [Char] ParserState String
114+nonindentSpaces :: MarkdownParser String
113115nonindentSpaces = do
114116 tabStop <- getOption readerTabStop
115117 sps <- many (char ' ')
@@ -117,27 +119,27 @@ nonindentSpaces = do
117119 then return sps
118120 else unexpected "indented line"
119121
120−skipNonindentSpaces :: Parser [Char] ParserState ()
122+skipNonindentSpaces :: MarkdownParser ()
121123skipNonindentSpaces = do
122124 tabStop <- getOption readerTabStop
123125 atMostSpaces (tabStop - 1)
124126
125−atMostSpaces :: Int -> Parser [Char] ParserState ()
127+atMostSpaces :: Int -> MarkdownParser ()
126128atMostSpaces 0 = notFollowedBy (char ' ')
127129atMostSpaces n = (char ' ' >> atMostSpaces (n-1)) <|> return ()
128130
129−litChar :: Parser [Char] ParserState Char
131+litChar :: MarkdownParser Char
130132litChar = escapedChar'
131133 <|> noneOf "\n"
132134 <|> (newline >> notFollowedBy blankline >> return ' ')
133135
134136-- | Parse a sequence of inline elements between square brackets,
135137-- including inlines between balanced pairs of square brackets.
136−inlinesInBalancedBrackets :: Parser [Char] ParserState (F Inlines)
138+inlinesInBalancedBrackets :: MarkdownParser (F Inlines)
137139inlinesInBalancedBrackets = charsInBalancedBrackets >>=
138140 parseFromString (trimInlinesF . mconcat <$> many inline)
139141
140−charsInBalancedBrackets :: Parser [Char] ParserState [Char]
142+charsInBalancedBrackets :: MarkdownParser [Char]
141143charsInBalancedBrackets = do
142144 char '['
143145 result <- manyTill ( many1 (noneOf "`[]\n")
@@ -152,7 +154,7 @@ charsInBalancedBrackets = do
152154-- document structure
153155--
154156
155−titleLine :: Parser [Char] ParserState (F Inlines)
157+titleLine :: MarkdownParser (F Inlines)
156158titleLine = try $ do
157159 char '%'
158160 skipSpaces
@@ -161,7 +163,7 @@ titleLine = try $ do
161163 newline
162164 return $ trimInlinesF $ mconcat res
163165
164−authorsLine :: Parser [Char] ParserState (F [Inlines])
166+authorsLine :: MarkdownParser (F [Inlines])
165167authorsLine = try $ do
166168 char '%'
167169 skipSpaces
@@ -172,16 +174,16 @@ authorsLine = try $ do
172174 newline
173175 return $ sequence $ filter (not . isNull) $ map (trimInlinesF . mconcat) authors
174176
175−dateLine :: Parser [Char] ParserState (F Inlines)
177+dateLine :: MarkdownParser (F Inlines)
176178dateLine = try $ do
177179 char '%'
178180 skipSpaces
179181 trimInlinesF . mconcat <$> manyTill inline newline
180182
181−titleBlock :: Parser [Char] ParserState (F Inlines, F [Inlines], F Inlines)
183+titleBlock :: MarkdownParser (F Inlines, F [Inlines], F Inlines)
182184titleBlock = pandocTitleBlock <|> mmdTitleBlock
183185
184−pandocTitleBlock :: Parser [Char] ParserState (F Inlines, F [Inlines], F Inlines)
186+pandocTitleBlock :: MarkdownParser (F Inlines, F [Inlines], F Inlines)
185187pandocTitleBlock = try $ do
186188 guardEnabled Ext_pandoc_title_block
187189 title <- option mempty titleLine
@@ -190,7 +192,7 @@ pandocTitleBlock = try $ do
190192 optional blanklines
191193 return (title, author, date)
192194
193−mmdTitleBlock :: Parser [Char] ParserState (F Inlines, F [Inlines], F Inlines)
195+mmdTitleBlock :: MarkdownParser (F Inlines, F [Inlines], F Inlines)
194196mmdTitleBlock = try $ do
195197 guardEnabled Ext_mmd_title_block
196198 kvPairs <- many1 kvPair
@@ -200,7 +202,7 @@ mmdTitleBlock = try $ do
200202 let date = maybe mempty return $ lookup "date" kvPairs
201203 return (title, author, date)
202204
203−kvPair :: Parser [Char] ParserState (String, Inlines)
205+kvPair :: MarkdownParser (String, Inlines)
204206kvPair = try $ do
205207 key <- many1Till (alphaNum <|> oneOf "_- ") (char ':')
206208 val <- manyTill anyChar
@@ -209,7 +211,7 @@ kvPair = try $ do
209211 let val' = trimInlines $ B.text val
210212 return (key',val')
211213
212−parseMarkdown :: Parser [Char] ParserState Pandoc
214+parseMarkdown :: MarkdownParser Pandoc
213215parseMarkdown = do
214216 -- markdown allows raw HTML
215217 updateState $ \state -> state { stateOptions =
@@ -226,7 +228,7 @@ parseMarkdown = do
226228 $ B.setDate (runF date st)
227229 $ B.doc $ runF blocks st
228230
229−referenceKey :: Parser [Char] ParserState (F Blocks)
231+referenceKey :: MarkdownParser (F Blocks)
230232referenceKey = try $ do
231233 skipNonindentSpaces
232234 (_,raw) <- reference
@@ -250,7 +252,7 @@ referenceKey = try $ do
250252 updateState $ \s -> s { stateKeys = M.insert (toKey raw) target oldkeys }
251253 return $ return mempty
252254
253−referenceTitle :: Parser [Char] ParserState String
255+referenceTitle :: MarkdownParser String
254256referenceTitle = try $ do
255257 skipSpaces >> optional newline >> skipSpaces
256258 tit <- (charsInBalanced '(' ')' litChar >>= return . unwords . words)
@@ -262,7 +264,7 @@ referenceTitle = try $ do
262264-- | PHP Markdown Extra style abbreviation key. Currently
263265-- we just skip them, since Pandoc doesn't have an element for
264266-- an abbreviation.
265−abbrevKey :: Parser [Char] ParserState (F Blocks)
267+abbrevKey :: MarkdownParser (F Blocks)
266268abbrevKey = do
267269 guardEnabled Ext_abbreviations
268270 try $ do
@@ -273,23 +275,23 @@ abbrevKey = do
273275 blanklines
274276 return $ return mempty
275277
276−noteMarker :: Parser [Char] ParserState String
278+noteMarker :: MarkdownParser String
277279noteMarker = string "[^" >> many1Till (satisfy $ not . isBlank) (char ']')
278280
279−rawLine :: Parser [Char] ParserState String
281+rawLine :: MarkdownParser String
280282rawLine = try $ do
281283 notFollowedBy blankline
282284 notFollowedBy' $ try $ skipNonindentSpaces >> noteMarker
283285 optional indentSpaces
284286 anyLine
285287
286−rawLines :: Parser [Char] ParserState String
288+rawLines :: MarkdownParser String
287289rawLines = do
288290 first <- anyLine
289291 rest <- many rawLine
290292 return $ unlines (first:rest)
291293
292−noteBlock :: Parser [Char] ParserState (F Blocks)
294+noteBlock :: MarkdownParser (F Blocks)
293295noteBlock = try $ do
294296 skipNonindentSpaces
295297 ref <- noteMarker
@@ -309,10 +311,10 @@ noteBlock = try $ do
309311-- parsing blocks
310312--
311313
312−parseBlocks :: Parser [Char] ParserState (F Blocks)
314+parseBlocks :: MarkdownParser (F Blocks)
313315parseBlocks = mconcat <$> manyTill block eof
314316
315−block :: Parser [Char] ParserState (F Blocks)
317+block :: MarkdownParser (F Blocks)
316318block = choice [ codeBlockFenced
317319 , codeBlockBackticks
318320 , guardEnabled Ext_latex_macros *> (mempty <$ macro)
@@ -338,21 +340,27 @@ block = choice [ codeBlockFenced
338340-- header blocks
339341--
340342
341−header :: Parser [Char] ParserState (F Blocks)
343+header :: MarkdownParser (F Blocks)
342344header = setextHeader <|> atxHeader <?> "header"
343345
344−atxHeader :: Parser [Char] ParserState (F Blocks)
346+addToHeaderList :: F Inlines -> MarkdownParser ()
347+addToHeaderList text =
348+ updateState $ \st -> st{ stateHeaders = B.toList (runF text defaultParserState)
349+ : stateHeaders st }
350+
351+atxHeader :: MarkdownParser (F Blocks)
345352atxHeader = try $ do
346353 level <- many1 (char '#') >>= return . length
347354 notFollowedBy (char '.' <|> char ')') -- this would be a list
348355 skipSpaces
349356 text <- trimInlinesF . mconcat <$> manyTill inline atxClosing
357+ addToHeaderList text
350358 return $ B.header level <$> text
351359
352360atxClosing :: Parser [Char] st String
353361atxClosing = try $ skipMany (char '#') >> blanklines
354362
355−setextHeader :: Parser [Char] ParserState (F Blocks)
363+setextHeader :: MarkdownParser (F Blocks)
356364setextHeader = try $ do
357365 -- This lookahead prevents us from wasting time parsing Inlines
358366 -- unless necessary -- it gives a significant performance boost.
@@ -362,6 +370,7 @@ setextHeader = try $ do
362370 many (char underlineChar)
363371 blanklines
364372 let level = (fromMaybe 0 $ findIndex (== underlineChar) setextHChars) + 1
373+ addToHeaderList text
365374 return $ B.header level <$> text
366375
367376--
@@ -382,7 +391,7 @@ hrule = try $ do
382391-- code blocks
383392--
384393
385−indentedLine :: Parser [Char] ParserState String
394+indentedLine :: MarkdownParser String
386395indentedLine = indentSpaces >> manyTill anyChar newline >>= return . (++ "\n")
387396
388397blockDelimiter :: (Char -> Bool)
@@ -437,7 +446,7 @@ keyValAttr = try $ do
437446 <|> many nonspaceChar
438447 return ("",[],[(key,val)])
439448
440−codeBlockFenced :: Parser [Char] ParserState (F Blocks)
449+codeBlockFenced :: MarkdownParser (F Blocks)
441450codeBlockFenced = try $ do
442451 guardEnabled Ext_fenced_code_blocks
443452 size <- blockDelimiter (=='~') Nothing
@@ -449,7 +458,7 @@ codeBlockFenced = try $ do
449458 blanklines
450459 return $ return $ B.codeBlockWith attr $ intercalate "\n" contents
451460
452−codeBlockBackticks :: Parser [Char] ParserState (F Blocks)
461+codeBlockBackticks :: MarkdownParser (F Blocks)
453462codeBlockBackticks = try $ do
454463 guardEnabled Ext_backtick_code_blocks
455464 blockDelimiter (=='`') (Just 3)
@@ -460,7 +469,7 @@ codeBlockBackticks = try $ do
460469 blanklines
461470 return $ return $ B.codeBlockWith ("",[cls],[]) $ intercalate "\n" contents
462471
463−codeBlockIndented :: Parser [Char] ParserState (F Blocks)
472+codeBlockIndented :: MarkdownParser (F Blocks)
464473codeBlockIndented = do
465474 contents <- many1 (indentedLine <|>
466475 try (do b <- blanklines
@@ -471,7 +480,7 @@ codeBlockIndented = do
471480 return $ return $ B.codeBlockWith ("", classes, []) $
472481 stripTrailingNewlines $ concat contents
473482
474−lhsCodeBlock :: Parser [Char] ParserState (F Blocks)
483+lhsCodeBlock :: MarkdownParser (F Blocks)
475484lhsCodeBlock = do
476485 guardEnabled Ext_literate_haskell
477486 (return . B.codeBlockWith ("",["sourceCode","literate","haskell"],[]) <$>
@@ -479,7 +488,7 @@ lhsCodeBlock = do
479488 <|> (return . B.codeBlockWith ("",["sourceCode","haskell"],[]) <$>
480489 lhsCodeBlockInverseBird)
481490
482−lhsCodeBlockLaTeX :: Parser [Char] ParserState String
491+lhsCodeBlockLaTeX :: MarkdownParser String
483492lhsCodeBlockLaTeX = try $ do
484493 string "\\begin{code}"
485494 manyTill spaceChar newline
@@ -487,13 +496,13 @@ lhsCodeBlockLaTeX = try $ do
487496 blanklines
488497 return $ stripTrailingNewlines contents
489498
490−lhsCodeBlockBird :: Parser [Char] ParserState String
499+lhsCodeBlockBird :: MarkdownParser String
491500lhsCodeBlockBird = lhsCodeBlockBirdWith '>'
492501
493−lhsCodeBlockInverseBird :: Parser [Char] ParserState String
502+lhsCodeBlockInverseBird :: MarkdownParser String
494503lhsCodeBlockInverseBird = lhsCodeBlockBirdWith '<'
495504
496−lhsCodeBlockBirdWith :: Char -> Parser [Char] ParserState String
505+lhsCodeBlockBirdWith :: Char -> MarkdownParser String
497506lhsCodeBlockBirdWith c = try $ do
498507 pos <- getPosition
499508 when (sourceColumn pos /= 1) $ fail "Not in first column"
@@ -516,10 +525,10 @@ birdTrackLine c = try $ do
516525-- block quotes
517526--
518527
519−emailBlockQuoteStart :: Parser [Char] ParserState Char
528+emailBlockQuoteStart :: MarkdownParser Char
520529emailBlockQuoteStart = try $ skipNonindentSpaces >> char '>' >>~ optional (char ' ')
521530
522−emailBlockQuote :: Parser [Char] ParserState [String]
531+emailBlockQuote :: MarkdownParser [String]
523532emailBlockQuote = try $ do
524533 emailBlockQuoteStart
525534 let emailLine = many $ nonEndline <|> try
@@ -533,7 +542,7 @@ emailBlockQuote = try $ do
533542 optional blanklines
534543 return raw
535544
536−blockQuote :: Parser [Char] ParserState (F Blocks)
545+blockQuote :: MarkdownParser (F Blocks)
537546blockQuote = do
538547 raw <- emailBlockQuote
539548 -- parse the extracted block, which may contain various block elements:
@@ -544,7 +553,7 @@ blockQuote = do
544553-- list blocks
545554--
546555
547−bulletListStart :: Parser [Char] ParserState ()
556+bulletListStart :: MarkdownParser ()
548557bulletListStart = try $ do
549558 optional newline -- if preceded by a Plain block in a list context
550559 skipNonindentSpaces
@@ -553,7 +562,7 @@ bulletListStart = try $ do
553562 spaceChar
554563 skipSpaces
555564
556−anyOrderedListStart :: Parser [Char] ParserState (Int, ListNumberStyle, ListNumberDelim)
565+anyOrderedListStart :: MarkdownParser (Int, ListNumberStyle, ListNumberDelim)
557566anyOrderedListStart = try $ do
558567 optional newline -- if preceded by a Plain block in a list context
559568 skipNonindentSpaces
@@ -572,11 +581,11 @@ anyOrderedListStart = try $ do
572581 skipSpaces
573582 return (num, style, delim)
574583
575−listStart :: Parser [Char] ParserState ()
584+listStart :: MarkdownParser ()
576585listStart = bulletListStart <|> (anyOrderedListStart >> return ())
577586
578587-- parse a line of a list item (start = parser for beginning of list item)
579−listLine :: Parser [Char] ParserState String
588+listLine :: MarkdownParser String
580589listLine = try $ do
581590 notFollowedBy blankline
582591 notFollowedBy' (do indentSpaces
@@ -586,8 +595,8 @@ listLine = try $ do
586595 return $ concat chunks ++ "\n"
587596
588597-- parse raw text for one list item, excluding start marker and continuations
589−rawListItem :: Parser [Char] ParserState a
590− -> Parser [Char] ParserState String
598+rawListItem :: MarkdownParser a
599+ -> MarkdownParser String
591600rawListItem start = try $ do
592601 start
593602 first <- listLine
@@ -598,14 +607,14 @@ rawListItem start = try $ do
598607-- continuation of a list item - indented and separated by blankline
599608-- or (in compact lists) endline.
600609-- note: nested lists are parsed as continuations
601−listContinuation :: Parser [Char] ParserState String
610+listContinuation :: MarkdownParser String
602611listContinuation = try $ do
603612 lookAhead indentSpaces
604613 result <- many1 listContinuationLine
605614 blanks <- many blankline
606615 return $ concat result ++ blanks
607616
608−listContinuationLine :: Parser [Char] ParserState String
617+listContinuationLine :: MarkdownParser String
609618listContinuationLine = try $ do
610619 notFollowedBy blankline
611620 notFollowedBy' listStart
@@ -613,8 +622,8 @@ listContinuationLine = try $ do
613622 result <- manyTill anyChar newline
614623 return $ result ++ "\n"
615624
616−listItem :: Parser [Char] ParserState a
617− -> Parser [Char] ParserState (F Blocks)
625+listItem :: MarkdownParser a
626+ -> MarkdownParser (F Blocks)
618627listItem start = try $ do
619628 first <- rawListItem start
620629 continuations <- many listContinuation
@@ -630,7 +639,7 @@ listItem start = try $ do
630639 updateState (\st -> st {stateParserContext = oldContext})
631640 return contents
632641
633−orderedList :: Parser [Char] ParserState (F Blocks)
642+orderedList :: MarkdownParser (F Blocks)
634643orderedList = try $ do
635644 (start, style, delim) <- lookAhead anyOrderedListStart
636645 unless ((style == DefaultStyle || style == Decimal || style == Example) &&
@@ -645,14 +654,14 @@ orderedList = try $ do
645654 start' <- option 1 $ guardEnabled Ext_startnum >> return start
646655 return $ B.orderedListWith (start', style, delim) <$> fmap compactify' items
647656
648−bulletList :: Parser [Char] ParserState (F Blocks)
657+bulletList :: MarkdownParser (F Blocks)
649658bulletList = do
650659 items <- fmap sequence $ many1 $ listItem bulletListStart
651660 return $ B.bulletList <$> fmap compactify' items
652661
653662-- definition lists
654663
655−defListMarker :: Parser [Char] ParserState ()
664+defListMarker :: MarkdownParser ()
656665defListMarker = do
657666 sps <- nonindentSpaces
658667 char ':' <|> char '~'
@@ -663,7 +672,7 @@ defListMarker = do
663672 else mzero
664673 return ()
665674
666−definitionListItem :: Parser [Char] ParserState (F (Inlines, [Blocks]))
675+definitionListItem :: MarkdownParser (F (Inlines, [Blocks]))
667676definitionListItem = try $ do
668677 guardEnabled Ext_definition_lists
669678 -- first, see if this has any chance of being a definition list:
@@ -678,7 +687,7 @@ definitionListItem = try $ do
678687 updateState (\st -> st {stateParserContext = oldContext})
679688 return $ liftM2 (,) term (sequence contents)
680689
681−defRawBlock :: Parser [Char] ParserState String
690+defRawBlock :: MarkdownParser String
682691defRawBlock = try $ do
683692 defListMarker
684693 firstline <- anyLine
@@ -690,7 +699,7 @@ defRawBlock = try $ do
690699 return $ unlines lns ++ trl
691700 return $ firstline ++ "\n" ++ unlines rawlines ++ trailing ++ cont
692701
693−definitionList :: Parser [Char] ParserState (F Blocks)
702+definitionList :: MarkdownParser (F Blocks)
694703definitionList = do
695704 items <- fmap sequence $ many1 definitionListItem
696705 return $ B.definitionList <$> fmap compactify'DL items
@@ -723,7 +732,7 @@ isHtmlOrBlank (LineBreak) = True
723732isHtmlOrBlank _ = False
724733-}
725734
726−para :: Parser [Char] ParserState (F Blocks)
735+para :: MarkdownParser (F Blocks)
727736para = try $ do
728737 result <- trimInlinesF . mconcat <$> many1 inline
729738 -- TODO remove this if not really needed? and remove isHtmlOrBlank
@@ -735,34 +744,34 @@ para = try $ do
735744 <|> (guardDisabled Ext_blank_before_header >> lookAhead header)
736745 return $ B.para <$> result
737746
738−plain :: Parser [Char] ParserState (F Blocks)
747+plain :: MarkdownParser (F Blocks)
739748plain = fmap B.plain . trimInlinesF . mconcat <$> many1 inline <* spaces
740749
741750--
742751-- raw html
743752--
744753
745−htmlElement :: Parser [Char] ParserState String
754+htmlElement :: MarkdownParser String
746755htmlElement = strictHtmlBlock <|> liftM snd (htmlTag isBlockTag)
747756
748−htmlBlock :: Parser [Char] ParserState (F Blocks)
757+htmlBlock :: MarkdownParser (F Blocks)
749758htmlBlock = do
750759 guardEnabled Ext_raw_html
751760 res <- (guardEnabled Ext_markdown_in_html_blocks >> rawHtmlBlocks)
752761 <|> htmlBlock'
753762 return $ return $ B.rawBlock "html" res
754763
755−htmlBlock' :: Parser [Char] ParserState String
764+htmlBlock' :: MarkdownParser String
756765htmlBlock' = try $ do
757766 first <- htmlElement
758767 finalSpace <- many spaceChar
759768 finalNewlines <- many newline
760769 return $ first ++ finalSpace ++ finalNewlines
761770
762−strictHtmlBlock :: Parser [Char] ParserState String
771+strictHtmlBlock :: MarkdownParser String
763772strictHtmlBlock = htmlInBalanced (not . isInlineTag)
764773
765−rawVerbatimBlock :: Parser [Char] ParserState String
774+rawVerbatimBlock :: MarkdownParser String
766775rawVerbatimBlock = try $ do
767776 (TagOpen tag _, open) <- htmlTag (tagOpen (\t ->
768777 t == "pre" || t == "style" || t == "script")
@@ -770,7 +779,7 @@ rawVerbatimBlock = try $ do
770779 contents <- manyTill anyChar (htmlTag (~== TagClose tag))
771780 return $ open ++ contents ++ renderTags [TagClose tag]
772781
773−rawTeXBlock :: Parser [Char] ParserState (F Blocks)
782+rawTeXBlock :: MarkdownParser (F Blocks)
774783rawTeXBlock = do
775784 guardEnabled Ext_raw_tex
776785 result <- (B.rawBlock "latex" <$> rawLaTeXBlock)
@@ -778,7 +787,7 @@ rawTeXBlock = do
778787 spaces
779788 return $ return result
780789
781−rawHtmlBlocks :: Parser [Char] ParserState String
790+rawHtmlBlocks :: MarkdownParser String
782791rawHtmlBlocks = do
783792 htmlBlocks <- many1 $ try $ do
784793 s <- rawVerbatimBlock <|> try (
@@ -832,7 +841,7 @@ dashedLine ch = do
832841-- Parse a table header with dashed lines of '-' preceded by
833842-- one (or zero) line of text.
834843simpleTableHeader :: Bool -- ^ Headerless table
835− -> Parser [Char] ParserState (F [Blocks], [Alignment], [Int])
844+ -> MarkdownParser (F [Blocks], [Alignment], [Int])
836845simpleTableHeader headless = try $ do
837846 rawContent <- if headless
838847 then return ""
@@ -876,16 +885,16 @@ alignType strLst len =
876885 (False, False) -> AlignDefault
877886
878887-- Parse a table footer - dashed lines followed by blank line.
879−tableFooter :: Parser [Char] ParserState String
888+tableFooter :: MarkdownParser String
880889tableFooter = try $ skipNonindentSpaces >> many1 (dashedLine '-') >> blanklines
881890
882891-- Parse a table separator - dashed line.
883−tableSep :: Parser [Char] ParserState Char
892+tableSep :: MarkdownParser Char
884893tableSep = try $ skipNonindentSpaces >> many1 (dashedLine '-') >> char '\n'
885894
886895-- Parse a raw line and split it into chunks by indices.
887896rawTableLine :: [Int]
888− -> Parser [Char] ParserState [String]
897+ -> MarkdownParser [String]
889898rawTableLine indices = do
890899 notFollowedBy' (blanklines <|> tableFooter)
891900 line <- many1Till anyChar newline
@@ -894,13 +903,13 @@ rawTableLine indices = do
894903
895904-- Parse a table line and return a list of lists of blocks (columns).
896905tableLine :: [Int]
897− -> Parser [Char] ParserState (F [Blocks])
906+ -> MarkdownParser (F [Blocks])
898907tableLine indices = rawTableLine indices >>=
899908 fmap sequence . mapM (parseFromString (mconcat <$> many plain))
900909
901910-- Parse a multiline table row and return a list of blocks (columns).
902911multilineRow :: [Int]
903− -> Parser [Char] ParserState (F [Blocks])
912+ -> MarkdownParser (F [Blocks])
904913multilineRow indices = do
905914 colLines <- many1 (rawTableLine indices)
906915 let cols = map unlines $ transpose colLines
@@ -908,7 +917,7 @@ multilineRow indices = do
908917
909918-- Parses a table caption: inlines beginning with 'Table:'
910919-- and followed by blank lines.
911−tableCaption :: Parser [Char] ParserState (F Inlines)
920+tableCaption :: MarkdownParser (F Inlines)
912921tableCaption = try $ do
913922 guardEnabled Ext_table_captions
914923 skipNonindentSpaces
@@ -917,7 +926,7 @@ tableCaption = try $ do
917926
918927-- Parse a simple table with '---' header and one line per row.
919928simpleTable :: Bool -- ^ Headerless table
920− -> Parser [Char] ParserState ([Alignment], [Double], F [Blocks], F [[Blocks]])
929+ -> MarkdownParser ([Alignment], [Double], F [Blocks], F [[Blocks]])
921930simpleTable headless = do
922931 (aligns, _widths, heads', lines') <-
923932 tableWith (simpleTableHeader headless) tableLine
@@ -931,12 +940,12 @@ simpleTable headless = do
931940-- which may be multiline, separated by blank lines, and
932941-- ending with a footer (dashed line followed by blank line).
933942multilineTable :: Bool -- ^ Headerless table
934− -> Parser [Char] ParserState ([Alignment], [Double], F [Blocks], F [[Blocks]])
943+ -> MarkdownParser ([Alignment], [Double], F [Blocks], F [[Blocks]])
935944multilineTable headless =
936945 tableWith (multilineTableHeader headless) multilineRow blanklines tableFooter
937946
938947multilineTableHeader :: Bool -- ^ Headerless table
939− -> Parser [Char] ParserState (F [Blocks], [Alignment], [Int])
948+ -> MarkdownParser (F [Blocks], [Alignment], [Int])
940949multilineTableHeader headless = try $ do
941950 if headless
942951 then return '\n'
@@ -970,7 +979,7 @@ multilineTableHeader headless = try $ do
970979-- which may be grid, separated by blank lines, and
971980-- ending with a footer (dashed line followed by blank line).
972981gridTable :: Bool -- ^ Headerless table
973− -> Parser [Char] ParserState ([Alignment], [Double], F [Blocks], F [[Blocks]])
982+ -> MarkdownParser ([Alignment], [Double], F [Blocks], F [[Blocks]])
974983gridTable headless =
975984 tableWith (gridTableHeader headless) gridTableRow
976985 (gridTableSep '-') gridTableFooter
@@ -993,12 +1002,12 @@ removeFinalBar =
9931002 reverse . dropWhile (`elem` " \t") . dropWhile (=='|') . reverse
9941003
9951004-- | Separator between rows of grid table.
996−gridTableSep :: Char -> Parser [Char] ParserState Char
1005+gridTableSep :: Char -> MarkdownParser Char
9971006gridTableSep ch = try $ gridDashedLines ch >> return '\n'
9981007
9991008-- | Parse header for a grid table.
10001009gridTableHeader :: Bool -- ^ Headerless table
1001− -> Parser [Char] ParserState (F [Blocks], [Alignment], [Int])
1010+ -> MarkdownParser (F [Blocks], [Alignment], [Int])
10021011gridTableHeader headless = try $ do
10031012 optional blanklines
10041013 dashes <- gridDashedLines '-'
@@ -1022,7 +1031,7 @@ gridTableHeader headless = try $ do
10221031 map trim rawHeads
10231032 return (heads, aligns, indices)
10241033
1025−gridTableRawLine :: [Int] -> Parser [Char] ParserState [String]
1034+gridTableRawLine :: [Int] -> MarkdownParser [String]
10261035gridTableRawLine indices = do
10271036 char '|'
10281037 line <- many1Till anyChar newline
@@ -1030,7 +1039,7 @@ gridTableRawLine indices = do
10301039
10311040-- | Parse row of grid table.
10321041gridTableRow :: [Int]
1033− -> Parser [Char] ParserState (F [Blocks])
1042+ -> MarkdownParser (F [Blocks])
10341043gridTableRow indices = do
10351044 colLines <- many1 (gridTableRawLine indices)
10361045 let cols = map ((++ "\n") . unlines . removeOneLeadingSpace) $
@@ -1046,10 +1055,10 @@ removeOneLeadingSpace xs =
10461055 startsWithSpace (y:_) = y == ' '
10471056
10481057-- | Parse footer for a grid table.
1049−gridTableFooter :: Parser [Char] ParserState [Char]
1058+gridTableFooter :: MarkdownParser [Char]
10501059gridTableFooter = blanklines
10511060
1052−pipeTable :: Parser [Char] ParserState ([Alignment], [Double], F [Blocks], F [[Blocks]])
1061+pipeTable :: MarkdownParser ([Alignment], [Double], F [Blocks], F [[Blocks]])
10531062pipeTable = try $ do
10541063 let pipeBreak = nonindentSpaces *> optional (char '|') *>
10551064 pipeTableHeaderPart `sepBy1` sepPipe <*
@@ -1064,13 +1073,13 @@ pipeTable = try $ do
10641073 let widths = replicate (length aligns) 0.0
10651074 return $ (aligns, widths, heads, lines')
10661075
1067−sepPipe :: Parser [Char] ParserState ()
1076+sepPipe :: MarkdownParser ()
10681077sepPipe = try $ do
10691078 char '|' <|> char '+'
10701079 notFollowedBy blankline
10711080
10721081-- parse a row, also returning probable alignments for org-table cells
1073−pipeTableRow :: Parser [Char] ParserState (F [Blocks])
1082+pipeTableRow :: MarkdownParser (F [Blocks])
10741083pipeTableRow = do
10751084 nonindentSpaces
10761085 optional (char '|')
@@ -1109,11 +1118,11 @@ scanForPipe = lookAhead (manyTill (satisfy (/='\n')) (char '|')) >> return ()
11091118-- | Parse a table using 'headerParser', 'rowParser',
11101119-- 'lineParser', and 'footerParser'. Variant of the version in
11111120-- Text.Pandoc.Parsing.
1112−tableWith :: Parser [Char] ParserState (F [Blocks], [Alignment], [Int])
1113− -> ([Int] -> Parser [Char] ParserState (F [Blocks]))
1114− -> Parser [Char] ParserState sep
1115− -> Parser [Char] ParserState end
1116− -> Parser [Char] ParserState ([Alignment], [Double], F [Blocks], F [[Blocks]])
1121+tableWith :: MarkdownParser (F [Blocks], [Alignment], [Int])
1122+ -> ([Int] -> MarkdownParser (F [Blocks]))
1123+ -> MarkdownParser sep
1124+ -> MarkdownParser end
1125+ -> MarkdownParser ([Alignment], [Double], F [Blocks], F [[Blocks]])
11171126tableWith headerParser rowParser lineParser footerParser = try $ do
11181127 (heads, aligns, indices) <- headerParser
11191128 lines' <- fmap sequence $ rowParser indices `sepEndBy1` lineParser
@@ -1124,7 +1133,7 @@ tableWith headerParser rowParser lineParser footerParser = try $ do
11241133 else widthsFromIndices numColumns indices
11251134 return $ (aligns, widths, heads, lines')
11261135
1127−table :: Parser [Char] ParserState (F Blocks)
1136+table :: MarkdownParser (F Blocks)
11281137table = try $ do
11291138 frontCaption <- option Nothing (Just <$> tableCaption)
11301139 (aligns, widths, heads, lns) <-
@@ -1151,7 +1160,7 @@ table = try $ do
11511160-- inline
11521161--
11531162
1154−inline :: Parser [Char] ParserState (F Inlines)
1163+inline :: MarkdownParser (F Inlines)
11551164inline = choice [ whitespace
11561165 , bareURL
11571166 , str
@@ -1180,13 +1189,13 @@ inline = choice [ whitespace
11801189 , ltSign
11811190 ] <?> "inline"
11821191
1183−escapedChar' :: Parser [Char] ParserState Char
1192+escapedChar' :: MarkdownParser Char
11841193escapedChar' = try $ do
11851194 char '\\'
11861195 (guardEnabled Ext_all_symbols_escapable >> satisfy (not . isAlphaNum))
11871196 <|> oneOf "\\`*_{}[]()>#+-.!~"
11881197
1189−escapedChar :: Parser [Char] ParserState (F Inlines)
1198+escapedChar :: MarkdownParser (F Inlines)
11901199escapedChar = do
11911200 result <- escapedChar'
11921201 case result of
@@ -1195,7 +1204,7 @@ escapedChar = do
11951204 return (return B.linebreak) -- "\[newline]" is a linebreak
11961205 _ -> return $ return $ B.str [result]
11971206
1198−ltSign :: Parser [Char] ParserState (F Inlines)
1207+ltSign :: MarkdownParser (F Inlines)
11991208ltSign = do
12001209 guardDisabled Ext_raw_html
12011210 <|> guardDisabled Ext_markdown_in_html_blocks
@@ -1203,7 +1212,7 @@ ltSign = do
12031212 char '<'
12041213 return $ return $ B.str "<"
12051214
1206−exampleRef :: Parser [Char] ParserState (F Inlines)
1215+exampleRef :: MarkdownParser (F Inlines)
12071216exampleRef = try $ do
12081217 guardEnabled Ext_example_lists
12091218 char '@'
@@ -1214,7 +1223,7 @@ exampleRef = try $ do
12141223 Just n -> B.str (show n)
12151224 Nothing -> B.str ('@':lab)
12161225
1217−symbol :: Parser [Char] ParserState (F Inlines)
1226+symbol :: MarkdownParser (F Inlines)
12181227symbol = do
12191228 result <- noneOf "<\\\n\t "
12201229 <|> try (do lookAhead $ char '\\'
@@ -1223,7 +1232,7 @@ symbol = do
12231232 return $ return $ B.str [result]
12241233
12251234-- parses inline code, between n `s and n `s
1226−code :: Parser [Char] ParserState (F Inlines)
1235+code :: MarkdownParser (F Inlines)
12271236code = try $ do
12281237 starts <- many1 (char '`')
12291238 skipSpaces
@@ -1235,11 +1244,11 @@ code = try $ do
12351244 optional whitespace >> attributes)
12361245 return $ return $ B.codeWith attr $ trim $ concat result
12371246
1238−math :: Parser [Char] ParserState (F Inlines)
1247+math :: MarkdownParser (F Inlines)
12391248math = (return . B.displayMath <$> (mathDisplay >>= applyMacros'))
12401249 <|> (return . B.math <$> (mathInline >>= applyMacros'))
12411250
1242−mathDisplay :: Parser [Char] ParserState String
1251+mathDisplay :: MarkdownParser String
12431252mathDisplay =
12441253 (guardEnabled Ext_tex_math_dollars >> mathDisplayWith "$$" "$$")
12451254 <|> (guardEnabled Ext_tex_math_single_backslash >>
@@ -1247,12 +1256,12 @@ mathDisplay =
12471256 <|> (guardEnabled Ext_tex_math_double_backslash >>
12481257 mathDisplayWith "\\\\[" "\\\\]")
12491258
1250−mathDisplayWith :: String -> String -> Parser [Char] ParserState String
1259+mathDisplayWith :: String -> String -> MarkdownParser String
12511260mathDisplayWith op cl = try $ do
12521261 string op
12531262 many1Till (noneOf "\n" <|> (newline >>~ notFollowedBy' blankline)) (try $ string cl)
12541263
1255−mathInline :: Parser [Char] ParserState String
1264+mathInline :: MarkdownParser String
12561265mathInline =
12571266 (guardEnabled Ext_tex_math_dollars >> mathInlineWith "$" "$")
12581267 <|> (guardEnabled Ext_tex_math_single_backslash >>
@@ -1260,7 +1269,7 @@ mathInline =
12601269 <|> (guardEnabled Ext_tex_math_double_backslash >>
12611270 mathInlineWith "\\\\(" "\\\\)")
12621271
1263−mathInlineWith :: String -> String -> Parser [Char] ParserState String
1272+mathInlineWith :: String -> String -> MarkdownParser String
12641273mathInlineWith op cl = try $ do
12651274 string op
12661275 notFollowedBy space
@@ -1283,15 +1292,15 @@ fours = try $ do
12831292
12841293-- | Parses a list of inlines between start and end delimiters.
12851294inlinesBetween :: (Show b)
1286− => Parser [Char] ParserState a
1287− -> Parser [Char] ParserState b
1288− -> Parser [Char] ParserState (F Inlines)
1295+ => MarkdownParser a
1296+ -> MarkdownParser b
1297+ -> MarkdownParser (F Inlines)
12891298inlinesBetween start end =
12901299 (trimInlinesF . mconcat) <$> try (start >> many1Till inner end)
12911300 where inner = innerSpace <|> (notFollowedBy' (() <$ whitespace) >> inline)
12921301 innerSpace = try $ whitespace >>~ notFollowedBy' end
12931302
1294−emph :: Parser [Char] ParserState (F Inlines)
1303+emph :: MarkdownParser (F Inlines)
12951304emph = fmap B.emph <$> nested
12961305 (inlinesBetween starStart starEnd <|> inlinesBetween ulStart ulEnd)
12971306 where starStart = char '*' >> lookAhead nonspaceChar
@@ -1299,7 +1308,7 @@ emph = fmap B.emph <$> nested
12991308 ulStart = char '_' >> lookAhead nonspaceChar
13001309 ulEnd = notFollowedBy' (() <$ strong) >> char '_'
13011310
1302−strong :: Parser [Char] ParserState (F Inlines)
1311+strong :: MarkdownParser (F Inlines)
13031312strong = fmap B.strong <$> nested
13041313 (inlinesBetween starStart starEnd <|> inlinesBetween ulStart ulEnd)
13051314 where starStart = string "**" >> lookAhead nonspaceChar
@@ -1307,26 +1316,26 @@ strong = fmap B.strong <$> nested
13071316 ulStart = string "__" >> lookAhead nonspaceChar
13081317 ulEnd = try $ string "__"
13091318
1310−strikeout :: Parser [Char] ParserState (F Inlines)
1319+strikeout :: MarkdownParser (F Inlines)
13111320strikeout = fmap B.strikeout <$>
13121321 (guardEnabled Ext_strikeout >> inlinesBetween strikeStart strikeEnd)
13131322 where strikeStart = string "~~" >> lookAhead nonspaceChar
13141323 >> notFollowedBy (char '~')
13151324 strikeEnd = try $ string "~~"
13161325
1317−superscript :: Parser [Char] ParserState (F Inlines)
1326+superscript :: MarkdownParser (F Inlines)
13181327superscript = fmap B.superscript <$> try (do
13191328 guardEnabled Ext_superscript
13201329 char '^'
13211330 mconcat <$> many1Till (notFollowedBy spaceChar >> inline) (char '^'))
13221331
1323−subscript :: Parser [Char] ParserState (F Inlines)
1332+subscript :: MarkdownParser (F Inlines)
13241333subscript = fmap B.subscript <$> try (do
13251334 guardEnabled Ext_subscript
13261335 char '~'
13271336 mconcat <$> many1Till (notFollowedBy spaceChar >> inline) (char '~'))
13281337
1329−whitespace :: Parser [Char] ParserState (F Inlines)
1338+whitespace :: MarkdownParser (F Inlines)
13301339whitespace = spaceChar >> return <$> (lb <|> regsp) <?> "whitespace"
13311340 where lb = spaceChar >> skipMany spaceChar >> option B.space (endline >> return B.linebreak)
13321341 regsp = skipMany spaceChar >> return B.space
@@ -1334,7 +1343,7 @@ whitespace = spaceChar >> return <$> (lb <|> regsp) <?> "whitespace"
13341343nonEndline :: Parser [Char] st Char
13351344nonEndline = satisfy (/='\n')
13361345
1337−str :: Parser [Char] ParserState (F Inlines)
1346+str :: MarkdownParser (F Inlines)
13381347str = do
13391348 isSmart <- readerSmart . stateOptions <$> getState
13401349 a <- alphaNum
@@ -1374,7 +1383,7 @@ likelyAbbrev x =
13741383 in map snd $ filter (\(y,_) -> y == x) abbrPairs
13751384
13761385-- an endline character that can be treated as a space, not a structural break
1377−endline :: Parser [Char] ParserState (F Inlines)
1386+endline :: MarkdownParser (F Inlines)
13781387endline = try $ do
13791388 newline
13801389 notFollowedBy blankline
@@ -1393,19 +1402,19 @@ endline = try $ do
13931402--
13941403
13951404-- a reference label for a link
1396−reference :: Parser [Char] ParserState (F Inlines, String)
1405+reference :: MarkdownParser (F Inlines, String)
13971406reference = do notFollowedBy' (string "[^") -- footnote reference
13981407 withRaw $ trimInlinesF <$> inlinesInBalancedBrackets
13991408
14001409-- source for a link, with optional title
1401−source :: Parser [Char] ParserState (String, String)
1410+source :: MarkdownParser (String, String)
14021411source =
14031412 (try $ charsInBalanced '(' ')' litChar >>= parseFromString source') <|>
14041413 -- the following is needed for cases like: [ref](/url(a).
14051414 (enclosed (char '(') (char ')') litChar >>= parseFromString source')
14061415
14071416-- auxiliary function for source
1408−source' :: Parser [Char] ParserState (String, String)
1417+source' :: MarkdownParser (String, String)
14091418source' = do
14101419 skipSpaces
14111420 let nl = char '\n' >>~ notFollowedBy blankline
@@ -1423,7 +1432,7 @@ source' = do
14231432 eof
14241433 return (escapeURI $ trimr src, tit)
14251434
1426−linkTitle :: Parser [Char] ParserState String
1435+linkTitle :: MarkdownParser String
14271436linkTitle = try $ do
14281437 (many1 spaceChar >> option '\n' newline) <|> newline
14291438 skipSpaces
@@ -1431,7 +1440,7 @@ linkTitle = try $ do
14311440 tit <- manyTill litChar (try (char delim >> skipSpaces >> eof))
14321441 return $ fromEntities tit
14331442
1434−link :: Parser [Char] ParserState (F Inlines)
1443+link :: MarkdownParser (F Inlines)
14351444link = try $ do
14361445 st <- getState
14371446 guard $ stateAllowLinks st
@@ -1441,51 +1450,62 @@ link = try $ do
14411450 regLink B.link lab <|> referenceLink B.link (lab,raw)
14421451
14431452regLink :: (String -> String -> Inlines -> Inlines)
1444− -> F Inlines -> Parser [Char] ParserState (F Inlines)
1453+ -> F Inlines -> MarkdownParser (F Inlines)
14451454regLink constructor lab = try $ do
14461455 (src, tit) <- source
14471456 return $ constructor src tit <$> lab
14481457
14491458-- a link like [this][ref] or [this][] or [this]
14501459referenceLink :: (String -> String -> Inlines -> Inlines)
1451− -> (F Inlines, String) -> Parser [Char] ParserState (F Inlines)
1460+ -> (F Inlines, String) -> MarkdownParser (F Inlines)
14521461referenceLink constructor (lab, raw) = do
1453− raw' <- try (optional (char ' ') >>
1454− optional (newline >> skipSpaces) >>
1455− (snd <$> reference)) <|> return ""
1456− let key = toKey $ if raw' == "[]" || raw' == "" then raw else raw'
1462+ (ref,raw') <- try (optional (char ' ') >>
1463+ optional (newline >> skipSpaces) >>
1464+ reference) <|> return (mempty, "")
1465+ let labIsRef = raw' == "" || raw' == "[]"
1466+ let key = toKey $ if labIsRef then raw else raw'
14571467 let dropRB (']':xs) = xs
14581468 dropRB xs = xs
14591469 let dropLB ('[':xs) = xs
14601470 dropLB xs = xs
14611471 let dropBrackets = reverse . dropRB . reverse . dropLB
14621472 fallback <- parseFromString (mconcat <$> many inline) $ dropBrackets raw
1473+ implicitHeaderRefs <- option False $
1474+ True <$ guardEnabled Ext_implicit_header_references
14631475 return $ do
14641476 keys <- asksF stateKeys
14651477 case M.lookup key keys of
1466− Nothing -> (\x -> B.str "[" <> x <> B.str "]" <> B.str raw') <$> fallback
1478+ Nothing -> do
1479+ headers <- asksF stateHeaders
1480+ let ref' = B.toList $ runF (if labIsRef then lab else ref)
1481+ defaultParserState
1482+ if implicitHeaderRefs && ref' `elem` headers
1483+ then do
1484+ let src = '#' : uniqueIdent ref' []
1485+ constructor src "" <$> lab
1486+ else (\x -> B.str "[" <> x <> B.str "]" <> B.str raw') <$> fallback
14671487 Just (src,tit) -> constructor src tit <$> lab
14681488
1469−bareURL :: Parser [Char] ParserState (F Inlines)
1489+bareURL :: MarkdownParser (F Inlines)
14701490bareURL = try $ do
14711491 guardEnabled Ext_autolink_urls
14721492 (orig, src) <- uri <|> emailAddress
14731493 return $ return $ B.link src "" (B.codeWith ("",["url"],[]) orig)
14741494
1475−autoLink :: Parser [Char] ParserState (F Inlines)
1495+autoLink :: MarkdownParser (F Inlines)
14761496autoLink = try $ do
14771497 char '<'
14781498 (orig, src) <- uri <|> emailAddress
14791499 char '>'
14801500 return $ return $ B.link src "" (B.codeWith ("",["url"],[]) orig)
14811501
1482−image :: Parser [Char] ParserState (F Inlines)
1502+image :: MarkdownParser (F Inlines)
14831503image = try $ do
14841504 char '!'
14851505 (lab,raw) <- reference
14861506 regLink B.image lab <|> referenceLink B.image (lab,raw)
14871507
1488−note :: Parser [Char] ParserState (F Inlines)
1508+note :: MarkdownParser (F Inlines)
14891509note = try $ do
14901510 guardEnabled Ext_footnotes
14911511 ref <- noteMarker
@@ -1501,14 +1521,14 @@ note = try $ do
15011521 let contents' = runF contents st{ stateNotes' = [] }
15021522 return $ B.note contents'
15031523
1504−inlineNote :: Parser [Char] ParserState (F Inlines)
1524+inlineNote :: MarkdownParser (F Inlines)
15051525inlineNote = try $ do
15061526 guardEnabled Ext_inline_notes
15071527 char '^'
15081528 contents <- inlinesInBalancedBrackets
15091529 return $ B.note . B.para <$> contents
15101530
1511−rawLaTeXInline' :: Parser [Char] ParserState (F Inlines)
1531+rawLaTeXInline' :: MarkdownParser (F Inlines)
15121532rawLaTeXInline' = try $ do
15131533 guardEnabled Ext_raw_tex
15141534 lookAhead $ char '\\' >> notFollowedBy' (string "start") -- context env
@@ -1532,7 +1552,7 @@ inBrackets parser = do
15321552 char ']'
15331553 return $ "[" ++ contents ++ "]"
15341554
1535−rawHtmlInline :: Parser [Char] ParserState (F Inlines)
1555+rawHtmlInline :: MarkdownParser (F Inlines)
15361556rawHtmlInline = do
15371557 guardEnabled Ext_raw_html
15381558 mdInHtml <- option False $
@@ -1544,14 +1564,14 @@ rawHtmlInline = do
15441564
15451565-- Citations
15461566
1547−cite :: Parser [Char] ParserState (F Inlines)
1567+cite :: MarkdownParser (F Inlines)
15481568cite = do
15491569 guardEnabled Ext_citations
15501570 getOption readerReferences >>= guard . not . null
15511571 citations <- textualCite <|> normalCite
15521572 return $ flip B.cite mempty <$> citations
15531573
1554−textualCite :: Parser [Char] ParserState (F [Citation])
1574+textualCite :: MarkdownParser (F [Citation])
15551575textualCite = try $ do
15561576 (_, key) <- citeKey
15571577 let first = Citation{ citationId = key
@@ -1566,7 +1586,7 @@ textualCite = try $ do
15661586 Just rest -> return $ (first:) <$> rest
15671587 Nothing -> option (return [first]) $ bareloc first
15681588
1569−bareloc :: Citation -> Parser [Char] ParserState (F [Citation])
1589+bareloc :: Citation -> MarkdownParser (F [Citation])
15701590bareloc c = try $ do
15711591 spnl
15721592 char '['
@@ -1579,7 +1599,7 @@ bareloc c = try $ do
15791599 rest' <- rest
15801600 return $ c{ citationSuffix = B.toList suff' } : rest'
15811601
1582−normalCite :: Parser [Char] ParserState (F [Citation])
1602+normalCite :: MarkdownParser (F [Citation])
15831603normalCite = try $ do
15841604 char '['
15851605 spnl
@@ -1588,7 +1608,7 @@ normalCite = try $ do
15881608 char ']'
15891609 return citations
15901610
1591−citeKey :: Parser [Char] ParserState (Bool, String)
1611+citeKey :: MarkdownParser (Bool, String)
15921612citeKey = try $ do
15931613 suppress_author <- option False (char '-' >> return True)
15941614 char '@'
@@ -1600,7 +1620,7 @@ citeKey = try $ do
16001620 guard $ key `elem` citations'
16011621 return (suppress_author, key)
16021622
1603−suffix :: Parser [Char] ParserState (F Inlines)
1623+suffix :: MarkdownParser (F Inlines)
16041624suffix = try $ do
16051625 hasSpace <- option False (notFollowedBy nonspaceChar >> return True)
16061626 spnl
@@ -1609,14 +1629,14 @@ suffix = try $ do
16091629 then (B.space <>) <$> rest
16101630 else rest
16111631
1612−prefix :: Parser [Char] ParserState (F Inlines)
1632+prefix :: MarkdownParser (F Inlines)
16131633prefix = trimInlinesF . mconcat <$>
16141634 manyTill inline (char ']' <|> liftM (const ']') (lookAhead citeKey))
16151635
1616−citeList :: Parser [Char] ParserState (F [Citation])
1636+citeList :: MarkdownParser (F [Citation])
16171637citeList = fmap sequence $ sepBy1 citation (try $ char ';' >> spnl)
16181638
1619−citation :: Parser [Char] ParserState (F Citation)
1639+citation :: MarkdownParser (F Citation)
16201640citation = try $ do
16211641 pref <- prefix
16221642 (suppress_author, key) <- citeKey
@@ -1634,20 +1654,20 @@ citation = try $ do
16341654 , citationHash = 0
16351655 }
16361656
1637−smart :: Parser [Char] ParserState (F Inlines)
1657+smart :: MarkdownParser (F Inlines)
16381658smart = do
16391659 getOption readerSmart >>= guard
16401660 doubleQuoted <|> singleQuoted <|>
16411661 choice (map (return . B.singleton <$>) [apostrophe, dash, ellipses])
16421662
1643−singleQuoted :: Parser [Char] ParserState (F Inlines)
1663+singleQuoted :: MarkdownParser (F Inlines)
16441664singleQuoted = try $ do
16451665 singleQuoteStart
16461666 withQuoteContext InSingleQuote $
16471667 fmap B.singleQuoted . trimInlinesF . mconcat <$>
16481668 many1Till inline singleQuoteEnd
16491669
1650−doubleQuoted :: Parser [Char] ParserState (F Inlines)
1670+doubleQuoted :: MarkdownParser (F Inlines)
16511671doubleQuoted = try $ do
16521672 doubleQuoteStart
16531673 withQuoteContext InDoubleQuote $