Use readerExtensions instead of readerStrict in readers.

Test individually for the extensions.
This commit is contained in:
John MacFarlane 2012-07-26 20:29:08 -07:00
parent 5186da929d
commit 33fdea67b5
3 changed files with 118 additions and 123 deletions

View file

@ -37,19 +37,33 @@ import qualified Data.Set as Set
import Data.Default
-- | Individually selectable syntax extensions.
data Extension = Footnotes
| Tex_math
| Delimited_code_blocks
| Markdown_in_html_blocks
| Fancy_lists
| Startnum
| Definition_lists
| Header_identifiers
| All_symbols_escapable
| Intraword_underscores
| Blank_before_blockquote
| Blank_before_header
| Significant_bullets
data Extension = Ext_footnotes
| Ext_inline_notes
| Ext_pandoc_title_blocks
| Ext_table_captions
| Ext_simple_tables
| Ext_multiline_tables
| Ext_grid_tables
| Ext_pipe_tables
| Ext_citations
| Ext_raw_tex
| Ext_tex_math
| Ext_latex_macros
| Ext_delimited_code_blocks
| Ext_markdown_in_html_blocks
| Ext_autolink_code_spans
| Ext_fancy_lists
| Ext_startnum
| Ext_definition_lists
| Ext_header_identifiers
| Ext_all_symbols_escapable
| Ext_intraword_underscores
| Ext_blank_before_blockquote
| Ext_blank_before_header
| Ext_significant_bullets
| Ext_strikeout
| Ext_superscript
| Ext_subscript
deriving (Show, Read, Enum, Eq, Ord, Bounded)
data ReaderOptions = ReaderOptions{

View file

@ -125,25 +125,22 @@ pBulletList = try $ do
pOrderedList :: TagParser [Block]
pOrderedList = try $ do
TagOpen _ attribs <- pSatisfy (~== TagOpen "ol" [])
st <- getState
let (start, style) = if readerStrict (stateOptions st)
then (1, DefaultStyle)
else (sta', sty')
where sta = fromMaybe "1" $
lookup "start" attribs
sta' = if all isDigit sta
then read sta
else 1
sty = fromMaybe (fromMaybe "" $
lookup "style" attribs) $
lookup "class" attribs
sty' = case sty of
"lower-roman" -> LowerRoman
"upper-roman" -> UpperRoman
"lower-alpha" -> LowerAlpha
"upper-alpha" -> UpperAlpha
"decimal" -> Decimal
_ -> DefaultStyle
let (start, style) = (sta', sty')
where sta = fromMaybe "1" $
lookup "start" attribs
sta' = if all isDigit sta
then read sta
else 1
sty = fromMaybe (fromMaybe "" $
lookup "style" attribs) $
lookup "class" attribs
sty' = case sty of
"lower-roman" -> LowerRoman
"upper-roman" -> UpperRoman
"lower-alpha" -> LowerAlpha
"upper-alpha" -> UpperAlpha
"decimal" -> Decimal
_ -> DefaultStyle
let nonItem = pSatisfy (\t ->
not (tagOpen (`elem` ["li","ol","ul","dl"]) (const True) t) &&
not (t ~== TagClose "ol"))
@ -280,10 +277,7 @@ pCodeBlock = try $ do
let attribsId = fromMaybe "" $ lookup "id" attr
let attribsClasses = words $ fromMaybe "" $ lookup "class" attr
let attribsKV = filter (\(k,_) -> k /= "class" && k /= "id") attr
st <- getState
let attribs = if readerStrict (stateOptions st)
then ("",[],[])
else (attribsId, attribsClasses, attribsKV)
let attribs = (attribsId, attribsClasses, attribsKV)
return [CodeBlock attribs result]
inline :: TagParser [Inline]
@ -331,14 +325,13 @@ pStrong :: TagParser [Inline]
pStrong = pInlinesInTags "strong" Strong <|> pInlinesInTags "b" Strong
pSuperscript :: TagParser [Inline]
pSuperscript = failIfStrict >> pInlinesInTags "sup" Superscript
pSuperscript = pInlinesInTags "sup" Superscript
pSubscript :: TagParser [Inline]
pSubscript = failIfStrict >> pInlinesInTags "sub" Subscript
pSubscript = pInlinesInTags "sub" Subscript
pStrikeout :: TagParser [Inline]
pStrikeout = do
failIfStrict
pInlinesInTags "s" Strikeout <|>
pInlinesInTags "strike" Strikeout <|>
pInlinesInTags "del" Strikeout <|>

View file

@ -112,12 +112,6 @@ litChar = escapedChar'
<|> noneOf "\n"
<|> (newline >> notFollowedBy blankline >> return ' ')
-- | Fail unless we're at beginning of a line.
failUnlessBeginningOfLine :: Parser [tok] st ()
failUnlessBeginningOfLine = do
pos <- getPosition
if sourceColumn pos == 1 then return () else fail "not beginning of line"
-- | Parse a sequence of inline elements between square brackets,
-- including inlines between balanced pairs of square brackets.
inlinesInBalancedBrackets :: Parser [Char] ParserState Inline
@ -165,7 +159,7 @@ dateLine = try $ do
titleBlock :: Parser [Char] ParserState ([Inline], [[Inline]], [Inline])
titleBlock = try $ do
failIfStrict
guardEnabled Ext_pandoc_title_blocks
title <- option [] titleLine
author <- option [] authorsLine
date <- option [] dateLine
@ -181,10 +175,10 @@ parseMarkdown = do
startPos <- getPosition
-- go through once just to get list of reference keys and notes
-- docMinusKeys is the raw document with blanks where the keys/notes were...
st <- getState
let firstPassParser = referenceKey
<|> (if readerStrict (stateOptions st) then mzero else noteBlock)
<|> liftM snd (withRaw codeBlockDelimited)
<|> (guardEnabled Ext_footnotes >> noteBlock)
<|> (guardEnabled Ext_delimited_code_blocks >>
liftM snd (withRaw codeBlockDelimited))
<|> lineClump
docMinusKeys <- liftM concat $ manyTill firstPassParser eof
setInput docMinusKeys
@ -292,35 +286,22 @@ parseBlocks :: Parser [Char] ParserState [Block]
parseBlocks = manyTill block eof
block :: Parser [Char] ParserState Block
block = do
st <- getState
choice (if readerStrict (stateOptions st)
then [ header
, codeBlockIndented
, blockQuote
, hrule
, bulletList
, orderedList
, htmlBlock
, para
, plain
, nullBlock ]
else [ codeBlockDelimited
, macro
, header
, table
, codeBlockIndented
, lhsCodeBlock
, blockQuote
, hrule
, bulletList
, orderedList
, definitionList
, rawTeXBlock
, para
, rawHtmlBlocks
, plain
, nullBlock ]) <?> "block"
block = choice [ codeBlockDelimited
, guardEnabled Ext_latex_macros >> macro
, header
, table
, codeBlockIndented
, lhsCodeBlock
, blockQuote
, hrule
, bulletList
, orderedList
, definitionList
, rawTeXBlock
, para
, htmlBlock
, plain
, nullBlock ] <?> "block"
--
-- header blocks
@ -431,8 +412,9 @@ keyValAttr = try $ do
<|> many nonspaceChar
return ("",[],[(key,val)])
codeBlockDelimited :: Parser [Char] st Block
codeBlockDelimited :: Parser [Char] ParserState Block
codeBlockDelimited = try $ do
guardEnabled Ext_delimited_code_blocks
(size, attr, c) <- blockDelimiter (\c -> c == '~' || c == '`') Nothing
contents <- manyTill anyLine (blockDelimiter (== c) (Just size))
blanklines
@ -635,6 +617,7 @@ defListMarker = do
definitionListItem :: Parser [Char] ParserState ([Inline], [[Block]])
definitionListItem = try $ do
guardEnabled Ext_definition_lists
-- first, see if this has any chance of being a definition list:
lookAhead (anyLine >> optional blankline >> defListMarker)
term <- manyTill inline newline
@ -694,9 +677,9 @@ para = try $ do
guard $ not . all isHtmlOrBlank $ result
option (Plain result) $ try $ do
newline
blanklines <|>
(getState >>= guard . readerStrict . stateOptions >>
lookAhead (blockQuote <|> header) >> return "")
(blanklines >> return Null)
<|> (guardDisabled Ext_blank_before_blockquote >> lookAhead blockQuote)
<|> (guardDisabled Ext_blank_before_header >> lookAhead header)
return $ Para result
plain :: Parser [Char] ParserState Block
@ -710,12 +693,16 @@ htmlElement :: Parser [Char] ParserState [Char]
htmlElement = strictHtmlBlock <|> liftM snd (htmlTag isBlockTag)
htmlBlock :: Parser [Char] ParserState Block
htmlBlock = try $ do
failUnlessBeginningOfLine
htmlBlock = RawBlock "html" `fmap`
((guardEnabled Ext_markdown_in_html_blocks >> rawHtmlBlocks)
<|> htmlBlock')
htmlBlock' :: Parser [Char] ParserState String
htmlBlock' = try $ do
first <- htmlElement
finalSpace <- many spaceChar
finalNewlines <- many newline
return $ RawBlock "html" $ first ++ finalSpace ++ finalNewlines
return $ first ++ finalSpace ++ finalNewlines
strictHtmlBlock :: Parser [Char] ParserState [Char]
strictHtmlBlock = htmlInBalanced (not . isInlineTag)
@ -730,13 +717,13 @@ rawVerbatimBlock = try $ do
rawTeXBlock :: Parser [Char] ParserState Block
rawTeXBlock = do
failIfStrict
guardEnabled Ext_raw_tex
result <- liftM (RawBlock "latex") rawLaTeXBlock
<|> liftM (RawBlock "context") rawConTeXtEnvironment
spaces
return result
rawHtmlBlocks :: Parser [Char] ParserState Block
rawHtmlBlocks :: Parser [Char] ParserState String
rawHtmlBlocks = do
htmlBlocks <- many1 $ do blk <- rawVerbatimBlock <|>
liftM snd (htmlTag isBlockTag)
@ -750,8 +737,7 @@ rawHtmlBlocks = do
-- by a blank line
return $ blk ++ sps
let combined = concat htmlBlocks
let combined' = if last combined == '\n' then init combined else combined
return $ RawBlock "html" combined'
return $ if last combined == '\n' then init combined else combined
--
-- Tables
@ -826,6 +812,7 @@ multilineRow indices = do
-- and followed by blank lines.
tableCaption :: Parser [Char] ParserState [Inline]
tableCaption = try $ do
guardEnabled Ext_table_captions
skipNonindentSpaces
string ":" <|> string "Table:"
result <- many1 inline
@ -961,10 +948,14 @@ table :: Parser [Char] ParserState Block
table = try $ do
frontCaption <- option [] tableCaption
Table _ aligns widths heads lines' <-
try (scanForPipe >> (pipeTable True <|> pipeTable False)) <|>
multilineTable False <|> simpleTable True <|>
simpleTable False <|> multilineTable True <|>
gridTable False <|> gridTable True <?> "table"
try (guardEnabled Ext_pipe_tables >> scanForPipe >>
(pipeTable True <|> pipeTable False)) <|>
try (guardEnabled Ext_multiline_tables >>
(multilineTable False <|> simpleTable True)) <|>
try (guardEnabled Ext_simple_tables >>
(simpleTable False <|> multilineTable True)) <|>
try (guardEnabled Ext_grid_tables >>
(gridTable False <|> gridTable True)) <?> "table"
optional blanklines
caption <- if null frontCaption
then option [] tableCaption
@ -1008,10 +999,8 @@ inlineParsers = [ whitespace
escapedChar' :: Parser [Char] ParserState Char
escapedChar' = try $ do
char '\\'
state <- getState
if readerStrict (stateOptions state)
then oneOf "\\`*_{}[]()>#+-.!~"
else satisfy (not . isAlphaNum)
(guardEnabled Ext_all_symbols_escapable >> satisfy (not . isAlphaNum))
<|> oneOf "\\`*_{}[]()>#+-.!~"
escapedChar :: Parser [Char] ParserState Inline
escapedChar = do
@ -1023,10 +1012,9 @@ escapedChar = do
ltSign :: Parser [Char] ParserState Inline
ltSign = do
st <- getState
if readerStrict (stateOptions st)
then char '<'
else notFollowedBy' rawHtmlBlocks >> char '<' -- unless it starts html
guardDisabled Ext_markdown_in_html_blocks
<|> (notFollowedBy' rawHtmlBlocks >> return ())
char '<'
return $ Str ['<']
exampleRef :: Parser [Char] ParserState Inline
@ -1072,13 +1060,13 @@ math = (mathDisplay >>= applyMacros' >>= return . Math DisplayMath)
mathDisplay :: Parser [Char] ParserState String
mathDisplay = try $ do
failIfStrict
guardEnabled Ext_tex_math
string "$$"
many1Till (noneOf "\n" <|> (newline >>~ notFollowedBy' blankline)) (try $ string "$$")
mathInline :: Parser [Char] ParserState String
mathInline = try $ do
failIfStrict
guardEnabled Ext_tex_math
char '$'
notFollowedBy space
words' <- sepBy1 mathWord (many1 (spaceChar <|> (newline >>~ notFollowedBy' blankline)))
@ -1135,18 +1123,18 @@ strong = Strong `liftM` nested
strikeout :: Parser [Char] ParserState Inline
strikeout = Strikeout `liftM`
(failIfStrict >> inlinesBetween strikeStart strikeEnd)
(guardEnabled Ext_strikeout >> inlinesBetween strikeStart strikeEnd)
where strikeStart = string "~~" >> lookAhead nonspaceChar
>> notFollowedBy (char '~')
strikeEnd = try $ string "~~"
superscript :: Parser [Char] ParserState Inline
superscript = failIfStrict >> enclosed (char '^') (char '^')
superscript = guardEnabled Ext_superscript >> enclosed (char '^') (char '^')
(notFollowedBy spaceChar >> inline) >>= -- may not contain Space
return . Superscript
subscript :: Parser [Char] ParserState Inline
subscript = failIfStrict >> enclosed (char '~') (char '~')
subscript = guardEnabled Ext_subscript >> enclosed (char '~') (char '~')
(notFollowedBy spaceChar >> inline) >>= -- may not contain Space
return . Subscript
@ -1163,7 +1151,8 @@ str = do
smart <- (readerSmart . stateOptions) `fmap` getState
a <- alphaNum
as <- many $ alphaNum
<|> (try $ char '_' >>~ lookAhead alphaNum)
<|> (guardEnabled Ext_intraword_underscores >>
try (char '_' >>~ lookAhead alphaNum))
<|> if smart
then (try $ satisfy (\c -> c == '\'' || c == '\x2019') >>
lookAhead alphaNum >> return '\x2019')
@ -1200,11 +1189,10 @@ endline :: Parser [Char] ParserState Inline
endline = try $ do
newline
notFollowedBy blankline
st <- getState
when (readerStrict (stateOptions st)) $ do
notFollowedBy emailBlockQuoteStart
notFollowedBy (char '#') -- atx header
guardEnabled Ext_blank_before_blockquote <|> notFollowedBy emailBlockQuoteStart
guardEnabled Ext_blank_before_header <|> notFollowedBy (char '#') -- atx header
-- parse potential list-starts differently if in a list:
st <- getState
when (stateParserContext st == ListItemState) $ do
notFollowedBy' bulletListStart
notFollowedBy' anyOrderedListStart
@ -1282,10 +1270,9 @@ autoLink = try $ do
char '<'
(orig, src) <- uri <|> emailAddress
char '>'
st <- getState
return $ if readerStrict (stateOptions st)
then Link [Str orig] (src, "")
else Link [Code ("",["url"],[]) orig] (src, "")
(guardEnabled Ext_autolink_code_spans >>
return (Link [Code ("",["url"],[]) orig] (src, "")))
<|> return (Link [Str orig] (src, ""))
image :: Parser [Char] ParserState Inline
image = try $ do
@ -1296,7 +1283,7 @@ image = try $ do
note :: Parser [Char] ParserState Inline
note = try $ do
failIfStrict
guardEnabled Ext_footnotes
ref <- noteMarker
state <- getState
let notes = stateNotes state
@ -1313,14 +1300,14 @@ note = try $ do
inlineNote :: Parser [Char] ParserState Inline
inlineNote = try $ do
failIfStrict
guardEnabled Ext_inline_notes
char '^'
contents <- inlinesInBalancedBrackets inline
return $ Note [Para contents]
rawLaTeXInline' :: Parser [Char] ParserState Inline
rawLaTeXInline' = try $ do
failIfStrict
guardEnabled Ext_raw_tex
lookAhead $ char '\\' >> notFollowedBy' (string "start") -- context env
RawInline _ s <- rawLaTeXInline
return $ RawInline "tex" s -- "tex" because it might be context or latex
@ -1343,17 +1330,18 @@ inBrackets parser = do
rawHtmlInline :: Parser [Char] ParserState Inline
rawHtmlInline = do
st <- getState
(_,result) <- if readerStrict (stateOptions st)
then htmlTag (not . isTextTag)
else htmlTag isInlineTag
mdInHtml <- option False $
guardEnabled Ext_markdown_in_html_blocks >> return True
(_,result) <- if mdInHtml
then htmlTag isInlineTag
else htmlTag (not . isTextTag)
return $ RawInline "html" result
-- Citations
cite :: Parser [Char] ParserState Inline
cite = do
failIfStrict
guardEnabled Ext_citations
citations <- textualCite <|> normalCite
return $ Cite citations []