summaryrefslogtreecommitdiff
path: root/src/Text/Pandoc/Readers/MediaWiki.hs
diff options
context:
space:
mode:
Diffstat (limited to 'src/Text/Pandoc/Readers/MediaWiki.hs')
-rw-r--r--src/Text/Pandoc/Readers/MediaWiki.hs308
1 files changed, 168 insertions, 140 deletions
diff --git a/src/Text/Pandoc/Readers/MediaWiki.hs b/src/Text/Pandoc/Readers/MediaWiki.hs
index 0dea22c53..c19ef2f46 100644
--- a/src/Text/Pandoc/Readers/MediaWiki.hs
+++ b/src/Text/Pandoc/Readers/MediaWiki.hs
@@ -1,7 +1,9 @@
-{-# LANGUAGE RelaxedPolyRec, FlexibleInstances, TypeSynonymInstances #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE RelaxedPolyRec #-}
+{-# LANGUAGE TypeSynonymInstances #-}
-- RelaxedPolyRec needed for inlinesBetween on GHC < 7
{-
- Copyright (C) 2012-2015 John MacFarlane <jgm@berkeley.edu>
+ Copyright (C) 2012-2018 John MacFarlane <jgm@berkeley.edu>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -20,7 +22,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
{- |
Module : Text.Pandoc.Readers.MediaWiki
- Copyright : Copyright (C) 2012-2015 John MacFarlane
+ Copyright : Copyright (C) 2012-2018 John MacFarlane
License : GNU GPL, version 2 or above
Maintainer : John MacFarlane <jgm@berkeley.edu>
@@ -36,43 +38,50 @@ _ parse templates?
-}
module Text.Pandoc.Readers.MediaWiki ( readMediaWiki ) where
-import Text.Pandoc.Definition
-import qualified Text.Pandoc.Builder as B
-import Text.Pandoc.Builder (Inlines, Blocks, trimInlines)
-import Data.Monoid ((<>))
-import Text.Pandoc.Options
-import Text.Pandoc.Readers.HTML ( htmlTag, isBlockTag, isCommentTag )
-import Text.Pandoc.XML ( fromEntities )
-import Text.Pandoc.Parsing hiding ( nested )
-import Text.Pandoc.Walk ( walk )
-import Text.Pandoc.Shared ( stripTrailingNewlines, safeRead, stringify, trim )
import Control.Monad
-import Data.List (intersperse, intercalate, isPrefixOf )
-import Text.HTML.TagSoup
-import Data.Sequence (viewl, ViewL(..), (<|))
+import Control.Monad.Except (throwError)
+import Data.Char (isDigit, isSpace)
import qualified Data.Foldable as F
+import Data.List (intercalate, intersperse, isPrefixOf)
import qualified Data.Map as M
+import Data.Maybe (fromMaybe, maybeToList)
+import Data.Monoid ((<>))
+import Data.Sequence (ViewL (..), viewl, (<|))
import qualified Data.Set as Set
-import Data.Char (isDigit, isSpace)
-import Data.Maybe (fromMaybe)
-import Text.Printf (printf)
-import Debug.Trace (trace)
-
-import Text.Pandoc.Error
+import Data.Text (Text, unpack)
+import Text.HTML.TagSoup
+import Text.Pandoc.Builder (Blocks, Inlines, trimInlines)
+import qualified Text.Pandoc.Builder as B
+import Text.Pandoc.Class (PandocMonad (..))
+import Text.Pandoc.Definition
+import Text.Pandoc.Logging
+import Text.Pandoc.Options
+import Text.Pandoc.Parsing hiding (nested)
+import Text.Pandoc.Readers.HTML (htmlTag, isBlockTag, isCommentTag)
+import Text.Pandoc.Shared (crFilter, safeRead, stringify, stripTrailingNewlines,
+ trim)
+import Text.Pandoc.Walk (walk)
+import Text.Pandoc.XML (fromEntities)
-- | Read mediawiki from an input string and return a Pandoc document.
-readMediaWiki :: ReaderOptions -- ^ Reader options
- -> String -- ^ String to parse (assuming @'\n'@ line endings)
- -> Either PandocError Pandoc
-readMediaWiki opts s =
- readWith parseMediaWiki MWState{ mwOptions = opts
- , mwMaxNestingLevel = 4
- , mwNextLinkNumber = 1
- , mwCategoryLinks = []
- , mwHeaderMap = M.empty
- , mwIdentifierList = Set.empty
- }
- (s ++ "\n")
+readMediaWiki :: PandocMonad m
+ => ReaderOptions -- ^ Reader options
+ -> Text -- ^ String to parse (assuming @'\n'@ line endings)
+ -> m Pandoc
+readMediaWiki opts s = do
+ parsed <- readWithM parseMediaWiki MWState{ mwOptions = opts
+ , mwMaxNestingLevel = 4
+ , mwNextLinkNumber = 1
+ , mwCategoryLinks = []
+ , mwHeaderMap = M.empty
+ , mwIdentifierList = Set.empty
+ , mwLogMessages = []
+ , mwInTT = False
+ }
+ (unpack (crFilter s) ++ "\n")
+ case parsed of
+ Right result -> return result
+ Left e -> throwError e
data MWState = MWState { mwOptions :: ReaderOptions
, mwMaxNestingLevel :: Int
@@ -80,9 +89,11 @@ data MWState = MWState { mwOptions :: ReaderOptions
, mwCategoryLinks :: [Inlines]
, mwHeaderMap :: M.Map Inlines String
, mwIdentifierList :: Set.Set String
+ , mwLogMessages :: [LogMessage]
+ , mwInTT :: Bool
}
-type MWParser = Parser [Char] MWState
+type MWParser m = ParserT [Char] MWState m
instance HasReaderOptions MWState where
extractReaderOptions = mwOptions
@@ -95,13 +106,17 @@ instance HasIdentifierList MWState where
extractIdentifierList = mwIdentifierList
updateIdentifierList f st = st{ mwIdentifierList = f $ mwIdentifierList st }
+instance HasLogMessages MWState where
+ addLogMessage m s = s{ mwLogMessages = m : mwLogMessages s }
+ getLogMessages = reverse . mwLogMessages
+
--
-- auxiliary functions
--
-- This is used to prevent exponential blowups for things like:
-- ''a'''a''a'''a''a'''a''a'''a
-nested :: MWParser a -> MWParser a
+nested :: PandocMonad m => MWParser m a -> MWParser m a
nested p = do
nestlevel <- mwMaxNestingLevel `fmap` getState
guard $ nestlevel > 0
@@ -116,7 +131,7 @@ specialChars = "'[]<=&*{}|\":\\"
spaceChars :: [Char]
spaceChars = " \n\t"
-sym :: String -> MWParser ()
+sym :: PandocMonad m => String -> MWParser m ()
sym s = () <$ try (string s)
newBlockTags :: [String]
@@ -131,16 +146,16 @@ isBlockTag' tag = isBlockTag tag
isInlineTag' :: Tag String -> Bool
isInlineTag' (TagComment _) = True
-isInlineTag' t = not (isBlockTag' t)
+isInlineTag' t = not (isBlockTag' t)
eitherBlockOrInline :: [String]
eitherBlockOrInline = ["applet", "button", "del", "iframe", "ins",
"map", "area", "object"]
-htmlComment :: MWParser ()
+htmlComment :: PandocMonad m => MWParser m ()
htmlComment = () <$ htmlTag isCommentTag
-inlinesInTags :: String -> MWParser Inlines
+inlinesInTags :: PandocMonad m => String -> MWParser m Inlines
inlinesInTags tag = try $ do
(_,raw) <- htmlTag (~== TagOpen tag [])
if '/' `elem` raw -- self-closing tag
@@ -148,7 +163,7 @@ inlinesInTags tag = try $ do
else trimInlines . mconcat <$>
manyTill inline (htmlTag (~== TagClose tag))
-blocksInTags :: String -> MWParser Blocks
+blocksInTags :: PandocMonad m => String -> MWParser m Blocks
blocksInTags tag = try $ do
(_,raw) <- htmlTag (~== TagOpen tag [])
let closer = if tag == "li"
@@ -162,7 +177,7 @@ blocksInTags tag = try $ do
then return mempty
else mconcat <$> manyTill block closer
-charsInTags :: String -> MWParser [Char]
+charsInTags :: PandocMonad m => String -> MWParser m [Char]
charsInTags tag = try $ do
(_,raw) <- htmlTag (~== TagOpen tag [])
if '/' `elem` raw -- self-closing tag
@@ -173,7 +188,7 @@ charsInTags tag = try $ do
-- main parser
--
-parseMediaWiki :: MWParser Pandoc
+parseMediaWiki :: PandocMonad m => MWParser m Pandoc
parseMediaWiki = do
bs <- mconcat <$> many block
spaces
@@ -182,16 +197,15 @@ parseMediaWiki = do
let categories = if null categoryLinks
then mempty
else B.para $ mconcat $ intersperse B.space categoryLinks
+ reportLogMessages
return $ B.doc $ bs <> categories
--
-- block parsers
--
-block :: MWParser Blocks
+block :: PandocMonad m => MWParser m Blocks
block = do
- tr <- getOption readerTrace
- pos <- getPosition
res <- mempty <$ skipMany1 blankline
<|> table
<|> header
@@ -204,28 +218,28 @@ block = do
<|> blockTag
<|> (B.rawBlock "mediawiki" <$> template)
<|> para
- when tr $
- trace (printf "line %d: %s" (sourceLine pos)
- (take 60 $ show $ B.toList res)) (return ())
+ trace (take 60 $ show $ B.toList res)
return res
-para :: MWParser Blocks
+para :: PandocMonad m => MWParser m Blocks
para = do
contents <- trimInlines . mconcat <$> many1 inline
if F.all (==Space) contents
then return mempty
else return $ B.para contents
-table :: MWParser Blocks
+table :: PandocMonad m => MWParser m Blocks
table = do
tableStart
- styles <- option [] parseAttrs <* blankline
+ styles <- option [] parseAttrs
+ skipMany spaceChar
+ optional blanklines
let tableWidth = case lookup "width" styles of
Just w -> fromMaybe 1.0 $ parseWidth w
Nothing -> 1.0
caption <- option mempty tableCaption
optional rowsep
- hasheader <- option False $ True <$ (lookAhead (skipSpaces *> char '!'))
+ hasheader <- option False $ True <$ lookAhead (skipSpaces *> char '!')
(cellspecs',hdr) <- unzip <$> tableRow
let widths = map ((tableWidth *) . snd) cellspecs'
let restwidth = tableWidth - sum widths
@@ -244,10 +258,10 @@ table = do
else (replicate cols mempty, hdr:rows')
return $ B.table caption cellspecs headers rows
-parseAttrs :: MWParser [(String,String)]
+parseAttrs :: PandocMonad m => MWParser m [(String,String)]
parseAttrs = many1 parseAttr
-parseAttr :: MWParser (String, String)
+parseAttr :: PandocMonad m => MWParser m (String, String)
parseAttr = try $ do
skipMany spaceChar
k <- many1 letter
@@ -256,27 +270,23 @@ parseAttr = try $ do
<|> many1 (satisfy $ \c -> not (isSpace c) && c /= '|')
return (k,v)
-tableStart :: MWParser ()
+tableStart :: PandocMonad m => MWParser m ()
tableStart = try $ guardColumnOne *> skipSpaces *> sym "{|"
-tableEnd :: MWParser ()
+tableEnd :: PandocMonad m => MWParser m ()
tableEnd = try $ guardColumnOne *> skipSpaces *> sym "|}"
-rowsep :: MWParser ()
+rowsep :: PandocMonad m => MWParser m ()
rowsep = try $ guardColumnOne *> skipSpaces *> sym "|-" <*
- optional parseAttr <* blanklines
-
-cellsep :: MWParser ()
-cellsep = try $
- (guardColumnOne *> skipSpaces <*
- ( (char '|' <* notFollowedBy (oneOf "-}+"))
- <|> (char '!')
- )
- )
- <|> (() <$ try (string "||"))
- <|> (() <$ try (string "!!"))
-
-tableCaption :: MWParser Inlines
+ many (char '-') <* optional parseAttr <* blanklines
+
+cellsep :: PandocMonad m => MWParser m ()
+cellsep = try $ do
+ skipSpaces
+ (char '|' *> notFollowedBy (oneOf "-}+") *> optional (char '|'))
+ <|> (char '!' *> optional (char '!'))
+
+tableCaption :: PandocMonad m => MWParser m Inlines
tableCaption = try $ do
guardColumnOne
skipSpaces
@@ -284,19 +294,21 @@ tableCaption = try $ do
optional (try $ parseAttr *> skipSpaces *> char '|' *> skipSpaces)
(trimInlines . mconcat) <$> many (notFollowedBy (cellsep <|> rowsep) *> inline)
-tableRow :: MWParser [((Alignment, Double), Blocks)]
+tableRow :: PandocMonad m => MWParser m [((Alignment, Double), Blocks)]
tableRow = try $ skipMany htmlComment *> many tableCell
-tableCell :: MWParser ((Alignment, Double), Blocks)
+tableCell :: PandocMonad m => MWParser m ((Alignment, Double), Blocks)
tableCell = try $ do
cellsep
skipMany spaceChar
attrs <- option [] $ try $ parseAttrs <* skipSpaces <* char '|' <*
notFollowedBy (char '|')
skipMany spaceChar
+ pos' <- getPosition
ls <- concat <$> many (notFollowedBy (cellsep <|> rowsep <|> tableEnd) *>
((snd <$> withRaw table) <|> count 1 anyChar))
- bs <- parseFromString (mconcat <$> many block) ls
+ bs <- parseFromString (do setPosition pos'
+ mconcat <$> many block) ls
let align = case lookup "align" attrs of
Just "left" -> AlignLeft
Just "right" -> AlignRight
@@ -311,9 +323,9 @@ parseWidth :: String -> Maybe Double
parseWidth s =
case reverse s of
('%':ds) | all isDigit ds -> safeRead ('0':'.':reverse ds)
- _ -> Nothing
+ _ -> Nothing
-template :: MWParser String
+template :: PandocMonad m => MWParser m String
template = try $ do
string "{{"
notFollowedBy (char '{')
@@ -322,7 +334,7 @@ template = try $ do
contents <- manyTill chunk (try $ string "}}")
return $ "{{" ++ concat contents ++ "}}"
-blockTag :: MWParser Blocks
+blockTag :: PandocMonad m => MWParser m Blocks
blockTag = do
(tag, _) <- lookAhead $ htmlTag isBlockTag'
case tag of
@@ -341,27 +353,27 @@ trimCode :: String -> String
trimCode ('\n':xs) = stripTrailingNewlines xs
trimCode xs = stripTrailingNewlines xs
-syntaxhighlight :: String -> [Attribute String] -> MWParser Blocks
+syntaxhighlight :: PandocMonad m => String -> [Attribute String] -> MWParser m Blocks
syntaxhighlight tag attrs = try $ do
let mblang = lookup "lang" attrs
let mbstart = lookup "start" attrs
let mbline = lookup "line" attrs
- let classes = maybe [] (:[]) mblang ++ maybe [] (const ["numberLines"]) mbline
+ let classes = maybeToList mblang ++ maybe [] (const ["numberLines"]) mbline
let kvs = maybe [] (\x -> [("startFrom",x)]) mbstart
contents <- charsInTags tag
return $ B.codeBlockWith ("",classes,kvs) $ trimCode contents
-hrule :: MWParser Blocks
+hrule :: PandocMonad m => MWParser m Blocks
hrule = B.horizontalRule <$ try (string "----" *> many (char '-') *> newline)
-guardColumnOne :: MWParser ()
+guardColumnOne :: PandocMonad m => MWParser m ()
guardColumnOne = getPosition >>= \pos -> guard (sourceColumn pos == 1)
-preformatted :: MWParser Blocks
+preformatted :: PandocMonad m => MWParser m Blocks
preformatted = try $ do
guardColumnOne
char ' '
- let endline' = B.linebreak <$ (try $ newline <* char ' ')
+ let endline' = B.linebreak <$ try (newline <* char ' ')
let whitespace' = B.str <$> many1 ('\160' <$ spaceChar)
let spToNbsp ' ' = '\160'
spToNbsp x = x
@@ -370,7 +382,7 @@ preformatted = try $ do
(htmlTag (~== TagOpen "nowiki" []) *>
manyTill anyChar (htmlTag (~== TagClose "nowiki")))
let inline' = whitespace' <|> endline' <|> nowiki'
- <|> (try $ notFollowedBy newline *> inline)
+ <|> try (notFollowedBy newline *> inline)
contents <- mconcat <$> many1 inline'
let spacesStr (Str xs) = all isSpace xs
spacesStr _ = False
@@ -385,10 +397,10 @@ encode = B.fromList . normalizeCode . B.toList . walk strToCode
strToCode x = x
normalizeCode [] = []
normalizeCode (Code a1 x : Code a2 y : zs) | a1 == a2 =
- normalizeCode $ (Code a1 (x ++ y)) : zs
+ normalizeCode $ Code a1 (x ++ y) : zs
normalizeCode (x:xs) = x : normalizeCode xs
-header :: MWParser Blocks
+header :: PandocMonad m => MWParser m Blocks
header = try $ do
guardColumnOne
eqs <- many1 (char '=')
@@ -398,13 +410,13 @@ header = try $ do
attr <- registerHeader nullAttr contents
return $ B.headerWith attr lev contents
-bulletList :: MWParser Blocks
+bulletList :: PandocMonad m => MWParser m Blocks
bulletList = B.bulletList <$>
( many1 (listItem '*')
<|> (htmlTag (~== TagOpen "ul" []) *> spaces *> many (listItem '*' <|> li) <*
optional (htmlTag (~== TagClose "ul"))) )
-orderedList :: MWParser Blocks
+orderedList :: PandocMonad m => MWParser m Blocks
orderedList =
(B.orderedList <$> many1 (listItem '#'))
<|> try
@@ -415,10 +427,10 @@ orderedList =
let start = fromMaybe 1 $ safeRead $ fromAttrib "start" tag
return $ B.orderedListWith (start, DefaultStyle, DefaultDelim) items)
-definitionList :: MWParser Blocks
+definitionList :: PandocMonad m => MWParser m Blocks
definitionList = B.definitionList <$> many1 defListItem
-defListItem :: MWParser (Inlines, [Blocks])
+defListItem :: PandocMonad m => MWParser m (Inlines, [Blocks])
defListItem = try $ do
terms <- mconcat . intersperse B.linebreak <$> many defListTerm
-- we allow dd with no dt, or dt with no dd
@@ -429,44 +441,49 @@ defListItem = try $ do
else many (listItem ':')
return (terms, defs)
-defListTerm :: MWParser Inlines
-defListTerm = char ';' >> skipMany spaceChar >> anyLine >>=
- parseFromString (trimInlines . mconcat <$> many inline)
+defListTerm :: PandocMonad m => MWParser m Inlines
+defListTerm = do
+ guardColumnOne
+ char ';'
+ skipMany spaceChar
+ pos' <- getPosition
+ anyLine >>= parseFromString (do setPosition pos'
+ trimInlines . mconcat <$> many inline)
-listStart :: Char -> MWParser ()
+listStart :: PandocMonad m => Char -> MWParser m ()
listStart c = char c *> notFollowedBy listStartChar
-listStartChar :: MWParser Char
+listStartChar :: PandocMonad m => MWParser m Char
listStartChar = oneOf "*#;:"
-anyListStart :: MWParser Char
-anyListStart = char '*'
- <|> char '#'
- <|> char ':'
- <|> char ';'
+anyListStart :: PandocMonad m => MWParser m Char
+anyListStart = guardColumnOne >> oneOf "*#:;"
-li :: MWParser Blocks
+li :: PandocMonad m => MWParser m Blocks
li = lookAhead (htmlTag (~== TagOpen "li" [])) *>
(firstParaToPlain <$> blocksInTags "li") <* spaces
-listItem :: Char -> MWParser Blocks
+listItem :: PandocMonad m => Char -> MWParser m Blocks
listItem c = try $ do
+ guardColumnOne
extras <- many (try $ char c <* lookAhead listStartChar)
if null extras
then listItem' c
else do
skipMany spaceChar
+ pos' <- getPosition
first <- concat <$> manyTill listChunk newline
rest <- many
(try $ string extras *> lookAhead listStartChar *>
(concat <$> manyTill listChunk newline))
- contents <- parseFromString (many1 $ listItem' c)
+ contents <- parseFromString (do setPosition pos'
+ many1 $ listItem' c)
(unlines (first : rest))
case c of
- '*' -> return $ B.bulletList contents
- '#' -> return $ B.orderedList contents
- ':' -> return $ B.definitionList [(mempty, contents)]
- _ -> mzero
+ '*' -> return $ B.bulletList contents
+ '#' -> return $ B.orderedList contents
+ ':' -> return $ B.definitionList [(mempty, contents)]
+ _ -> mzero
-- The point of this is to handle stuff like
-- * {{cite book
@@ -475,30 +492,32 @@ listItem c = try $ do
-- }}
-- * next list item
-- which seems to be valid mediawiki.
-listChunk :: MWParser String
+listChunk :: PandocMonad m => MWParser m String
listChunk = template <|> count 1 anyChar
-listItem' :: Char -> MWParser Blocks
+listItem' :: PandocMonad m => Char -> MWParser m Blocks
listItem' c = try $ do
listStart c
skipMany spaceChar
+ pos' <- getPosition
first <- concat <$> manyTill listChunk newline
rest <- many (try $ char c *> lookAhead listStartChar *>
(concat <$> manyTill listChunk newline))
- parseFromString (firstParaToPlain . mconcat <$> many1 block)
+ parseFromString (do setPosition pos'
+ firstParaToPlain . mconcat <$> many1 block)
$ unlines $ first : rest
firstParaToPlain :: Blocks -> Blocks
firstParaToPlain contents =
case viewl (B.unMany contents) of
- (Para xs) :< ys -> B.Many $ (Plain xs) <| ys
- _ -> contents
+ Para xs :< ys -> B.Many $ Plain xs <| ys
+ _ -> contents
--
-- inline parsers
--
-inline :: MWParser Inlines
+inline :: PandocMonad m => MWParser m Inlines
inline = whitespace
<|> url
<|> str
@@ -516,10 +535,10 @@ inline = whitespace
<|> (B.rawInline "mediawiki" <$> template)
<|> special
-str :: MWParser Inlines
+str :: PandocMonad m => MWParser m Inlines
str = B.str <$> many1 (noneOf $ specialChars ++ spaceChars)
-math :: MWParser Inlines
+math :: PandocMonad m => MWParser m Inlines
math = (B.displayMath . trim <$> try (many1 (char ':') >> charsInTags "math"))
<|> (B.math . trim <$> charsInTags "math")
<|> (B.displayMath . trim <$> try (dmStart *> manyTill anyChar dmEnd))
@@ -529,13 +548,13 @@ math = (B.displayMath . trim <$> try (many1 (char ':') >> charsInTags "math"))
mStart = string "\\("
mEnd = try (string "\\)")
-variable :: MWParser String
+variable :: PandocMonad m => MWParser m String
variable = try $ do
string "{{{"
contents <- manyTill anyChar (try $ string "}}}")
return $ "{{{" ++ contents ++ "}}}"
-inlineTag :: MWParser Inlines
+inlineTag :: PandocMonad m => MWParser m Inlines
inlineTag = do
(tag, _) <- lookAhead $ htmlTag isInlineTag'
case tag of
@@ -553,22 +572,27 @@ inlineTag = do
TagOpen "sub" _ -> B.subscript <$> inlinesInTags "sub"
TagOpen "sup" _ -> B.superscript <$> inlinesInTags "sup"
TagOpen "code" _ -> encode <$> inlinesInTags "code"
- TagOpen "tt" _ -> encode <$> inlinesInTags "tt"
+ TagOpen "tt" _ -> do
+ inTT <- mwInTT <$> getState
+ updateState $ \st -> st{ mwInTT = True }
+ result <- encode <$> inlinesInTags "tt"
+ updateState $ \st -> st{ mwInTT = inTT }
+ return result
TagOpen "hask" _ -> B.codeWith ("",["haskell"],[]) <$> charsInTags "hask"
_ -> B.rawInline "html" . snd <$> htmlTag (~== tag)
-special :: MWParser Inlines
+special :: PandocMonad m => MWParser m Inlines
special = B.str <$> count 1 (notFollowedBy' (htmlTag isBlockTag') *>
oneOf specialChars)
-inlineHtml :: MWParser Inlines
+inlineHtml :: PandocMonad m => MWParser m Inlines
inlineHtml = B.rawInline "html" . snd <$> htmlTag isInlineTag'
-whitespace :: MWParser Inlines
+whitespace :: PandocMonad m => MWParser m Inlines
whitespace = B.space <$ (skipMany1 spaceChar <|> htmlComment)
<|> B.softbreak <$ endline
-endline :: MWParser ()
+endline :: PandocMonad m => MWParser m ()
endline = () <$ try (newline <*
notFollowedBy spaceChar <*
notFollowedBy newline <*
@@ -577,30 +601,30 @@ endline = () <$ try (newline <*
notFollowedBy' header <*
notFollowedBy anyListStart)
-imageIdentifiers :: [MWParser ()]
+imageIdentifiers :: PandocMonad m => [MWParser m ()]
imageIdentifiers = [sym (identifier ++ ":") | identifier <- identifiers]
where identifiers = ["File", "Image", "Archivo", "Datei", "Fichier",
"Bild"]
-image :: MWParser Inlines
+image :: PandocMonad m => MWParser m Inlines
image = try $ do
sym "[["
choice imageIdentifiers
fname <- addUnderscores <$> many1 (noneOf "|]")
_ <- many imageOption
- dims <- try (char '|' *> (sepBy (many digit) (char 'x')) <* string "px")
+ dims <- try (char '|' *> sepBy (many digit) (char 'x') <* string "px")
<|> return []
_ <- many imageOption
let kvs = case dims of
- w:[] -> [("width", w)]
- w:(h:[]) -> [("width", w), ("height", h)]
- _ -> []
+ [w] -> [("width", w)]
+ [w, h] -> [("width", w), ("height", h)]
+ _ -> []
let attr = ("", [], kvs)
caption <- (B.str fname <$ sym "]]")
<|> try (char '|' *> (mconcat <$> manyTill inline (sym "]]")))
return $ B.imageWith attr fname ("fig:" ++ stringify caption) caption
-imageOption :: MWParser String
+imageOption :: PandocMonad m => MWParser m String
imageOption = try $ char '|' *> opt
where
opt = try (oneOfStrings [ "border", "thumbnail", "frameless"
@@ -612,14 +636,14 @@ imageOption = try $ char '|' *> opt
<|> try (oneOfStrings ["link=","alt=","page=","class="] <* many (noneOf "|]"))
collapseUnderscores :: String -> String
-collapseUnderscores [] = []
+collapseUnderscores [] = []
collapseUnderscores ('_':'_':xs) = collapseUnderscores ('_':xs)
-collapseUnderscores (x:xs) = x : collapseUnderscores xs
+collapseUnderscores (x:xs) = x : collapseUnderscores xs
addUnderscores :: String -> String
addUnderscores = collapseUnderscores . intercalate "_" . words
-internalLink :: MWParser Inlines
+internalLink :: PandocMonad m => MWParser m Inlines
internalLink = try $ do
sym "[["
pagename <- unwords . words <$> many (noneOf "|]")
@@ -627,7 +651,7 @@ internalLink = try $ do
( (mconcat <$> many1 (notFollowedBy (char ']') *> inline))
-- the "pipe trick"
-- [[Help:Contents|] -> "Contents"
- <|> (return $ B.text $ drop 1 $ dropWhile (/=':') pagename) )
+ <|> return (B.text $ drop 1 $ dropWhile (/=':') pagename) )
sym "]]"
linktrail <- B.text <$> many letter
let link = B.link (addUnderscores pagename) "wikilink" (label <> linktrail)
@@ -637,7 +661,7 @@ internalLink = try $ do
return mempty
else return link
-externalLink :: MWParser Inlines
+externalLink :: PandocMonad m => MWParser m Inlines
externalLink = try $ do
char '['
(_, src) <- uri
@@ -649,29 +673,33 @@ externalLink = try $ do
return $ B.str $ show num
return $ B.link src "" lab
-url :: MWParser Inlines
+url :: PandocMonad m => MWParser m Inlines
url = do
(orig, src) <- uri
return $ B.link src "" (B.str orig)
-- | Parses a list of inlines between start and end delimiters.
-inlinesBetween :: (Show b) => MWParser a -> MWParser b -> MWParser Inlines
+inlinesBetween :: (PandocMonad m, Show b) => MWParser m a -> MWParser m b -> MWParser m Inlines
inlinesBetween start end =
(trimInlines . mconcat) <$> try (start >> many1Till inner end)
where inner = innerSpace <|> (notFollowedBy' (() <$ whitespace) >> inline)
innerSpace = try $ whitespace <* notFollowedBy' end
-emph :: MWParser Inlines
+emph :: PandocMonad m => MWParser m Inlines
emph = B.emph <$> nested (inlinesBetween start end)
where start = sym "''" >> lookAhead nonspaceChar
end = try $ notFollowedBy' (() <$ strong) >> sym "''"
-strong :: MWParser Inlines
+strong :: PandocMonad m => MWParser m Inlines
strong = B.strong <$> nested (inlinesBetween start end)
where start = sym "'''" >> lookAhead nonspaceChar
end = try $ sym "'''"
-doubleQuotes :: MWParser Inlines
-doubleQuotes = B.doubleQuoted <$> nested (inlinesBetween openDoubleQuote closeDoubleQuote)
+doubleQuotes :: PandocMonad m => MWParser m Inlines
+doubleQuotes = do
+ guardEnabled Ext_smart
+ inTT <- mwInTT <$> getState
+ guard (not inTT)
+ B.doubleQuoted <$> nested (inlinesBetween openDoubleQuote closeDoubleQuote)
where openDoubleQuote = sym "\"" >> lookAhead nonspaceChar
closeDoubleQuote = try $ sym "\""