git.iko.soy/typeable/pandoc
on master help sign in
Working on readers.
b53ebcdJesse Rosenthal
src/Text/Pandoc.hs+49−46
@@ -69,7 +69,6 @@ module Text.Pandoc
69 , writers
69 , writers
70 -- * Readers: converting /to/ Pandoc format
70 -- * Readers: converting /to/ Pandoc format
71 , Reader (..)
71 , Reader (..)
72− , mkStringReader
73 , readDocx
72 , readDocx
74 , readOdt
73 , readOdt
75 , readMarkdown
74 , readMarkdown
@@ -183,7 +182,7 @@ import Text.Pandoc.Options
183import Text.Pandoc.Shared (safeRead, warn, mapLeft, pandocVersion)
182import Text.Pandoc.Shared (safeRead, warn, mapLeft, pandocVersion)
184import Text.Pandoc.MediaBag (MediaBag)
183import Text.Pandoc.MediaBag (MediaBag)
185import Text.Pandoc.Error
184import Text.Pandoc.Error
186−import Text.Pandoc.Class (PandocMonad, runIOorExplode)
185+import Text.Pandoc.Class (PandocMonad, runIOorExplode, PandocExecutionError(..))
187import Data.Aeson
186import Data.Aeson
188import qualified Data.ByteString.Lazy as BL
187import qualified Data.ByteString.Lazy as BL
189import Data.List (intercalate)
188import Data.List (intercalate)
@@ -192,6 +191,7 @@ import qualified Data.Set as Set
192import Text.Parsec
191import Text.Parsec
193import Text.Parsec.Error
192import Text.Parsec.Error
194import qualified Text.Pandoc.UTF8 as UTF8
193import qualified Text.Pandoc.UTF8 as UTF8
194+import Control.Monad.Except (throwError)
195
195
196parseFormatSpec :: String
196parseFormatSpec :: String
197 -> Either ParseError (String, Set Extension -> Set Extension)
197 -> Either ParseError (String, Set Extension -> Set Extension)
@@ -216,55 +216,58 @@ parseFormatSpec = parse formatSpec ""
216-- TODO: when we get the PandocMonad stuff all sorted out,
216-- TODO: when we get the PandocMonad stuff all sorted out,
217-- we can simply these types considerably. Errors/MediaBag can be
217-- we can simply these types considerably. Errors/MediaBag can be
218-- part of the monad's internal state.
218-- part of the monad's internal state.
219−data Reader m = StringReader (ReaderOptions -> String -> m (Either PandocError Pandoc))
219+data Reader m = StringReader (ReaderOptions -> String -> m Pandoc)
220− | ByteStringReader (ReaderOptions -> BL.ByteString -> m (Either PandocError (Pandoc,MediaBag)))
220+ | ByteStringReader (ReaderOptions -> BL.ByteString -> m Pandoc)
221
221
222−mkStringReader :: (ReaderOptions -> String -> Either PandocError Pandoc) -> Reader IO
222+-- mkStringReader :: (ReaderOptions -> String -> Either PandocError Pandoc) -> Reader IO
223−mkStringReader r = StringReader (\o s -> return $ r o s)
223+-- mkStringReader r = StringReader (\o s -> return $ r o s)
224
224
225−mkStringReaderWithWarnings :: (ReaderOptions -> String -> Either PandocError (Pandoc, [String])) -> Reader IO
225+-- mkStringReaderWithWarnings :: (ReaderOptions -> String -> Either PandocError (Pandoc, [String])) -> Reader IO
226−mkStringReaderWithWarnings r = StringReader $ \o s ->
226+-- mkStringReaderWithWarnings r = StringReader $ \o s ->
227− case r o s of
227+-- case r o s of
228− Left err -> return $ Left err
228+-- Left err -> return $ Left err
229− Right (doc, warnings) -> do
229+-- Right (doc, warnings) -> do
230− mapM_ warn warnings
230+-- mapM_ warn warnings
231− return (Right doc)
231+-- return (Right doc)
232
232
233−mkBSReader :: (ReaderOptions -> BL.ByteString -> Either PandocError (Pandoc, MediaBag)) -> Reader IO
233+-- mkBSReader :: (ReaderOptions -> BL.ByteString -> Either PandocError (Pandoc, MediaBag)) -> Reader IO
234−mkBSReader r = ByteStringReader (\o s -> return $ r o s)
234+-- mkBSReader r = ByteStringReader (\o s -> return $ r o s)
235
235
236−mkBSReaderWithWarnings :: (ReaderOptions -> BL.ByteString -> Either PandocError (Pandoc, MediaBag, [String])) -> Reader IO
236+-- mkBSReaderWithWarnings :: (ReaderOptions -> BL.ByteString -> Either PandocError (Pandoc, MediaBag, [String])) -> Reader IO
237−mkBSReaderWithWarnings r = ByteStringReader $ \o s ->
237+-- mkBSReaderWithWarnings r = ByteStringReader $ \o s ->
238− case r o s of
238+-- case r o s of
239− Left err -> return $ Left err
239+-- Left err -> return $ Left err
240− Right (doc, mediaBag, warnings) -> do
240+-- Right (doc, mediaBag, warnings) -> do
241− mapM_ warn warnings
241+-- mapM_ warn warnings
242− return $ Right (doc, mediaBag)
242+-- return $ Right (doc, mediaBag)
243
243
244-- | Association list of formats and readers.
244-- | Association list of formats and readers.
245−readers :: [(String, Reader IO)]
245+readers :: PandocMonad m => [(String, Reader m)]
246−readers = [ ("native" , StringReader $ \_ s -> runIOorExplode (readNative s))
246+readers = [ ("native" , StringReader $ \_ s -> readNative s)
247− ,("json" , mkStringReader readJSON )
247+ ,("json" , StringReader $ \o s ->
248− ,("markdown" , mkStringReaderWithWarnings readMarkdownWithWarnings)
248+ case readJSON o s of
249− ,("markdown_strict" , mkStringReaderWithWarnings readMarkdownWithWarnings)
249+ Right doc -> return doc
250− ,("markdown_phpextra" , mkStringReaderWithWarnings readMarkdownWithWarnings)
250+ Left _ -> throwError $ PandocParseError "JSON parse error")
251− ,("markdown_github" , mkStringReaderWithWarnings readMarkdownWithWarnings)
251+ ,("markdown" , StringReader readMarkdown)
252− ,("markdown_mmd", mkStringReaderWithWarnings readMarkdownWithWarnings)
252+ ,("markdown_strict" , StringReader readMarkdown)
253+ ,("markdown_phpextra" , StringReader readMarkdown)
254+ ,("markdown_github" , StringReader readMarkdown)
255+ ,("markdown_mmd", StringReader readMarkdown)
253− ,("commonmark" , mkStringReader readCommonMark)
256+ ,("commonmark" , StringReader readCommonMark)
254− ,("rst" , mkStringReaderWithWarnings readRSTWithWarnings )
257+ ,("rst" , StringReader readRSTWithWarnings )
255− ,("mediawiki" , mkStringReader readMediaWiki)
258+ ,("mediawiki" , StringReader readMediaWiki)
256− ,("docbook" , mkStringReader readDocBook)
259+ ,("docbook" , StringReader readDocBook)
257− ,("opml" , mkStringReader readOPML)
260+ ,("opml" , StringReader readOPML)
258− ,("org" , mkStringReader readOrg)
261+ ,("org" , StringReader readOrg)
259− ,("textile" , mkStringReader readTextile) -- TODO : textile+lhs
262+ ,("textile" , StringReader readTextile) -- TODO : textile+lhs
260− ,("html" , mkStringReader readHtml)
263+ ,("html" , StringReader readHtml)
261− ,("latex" , mkStringReader readLaTeX)
264+ ,("latex" , StringReader readLaTeX)
262− ,("haddock" , mkStringReader readHaddock)
265+ ,("haddock" , StringReader readHaddock)
263− ,("twiki" , mkStringReader readTWiki)
266+ ,("twiki" , StringReader readTWiki)
264− ,("docx" , mkBSReaderWithWarnings readDocxWithWarnings)
267+ ,("docx" , ByteStringReader readDocx)
265− ,("odt" , mkBSReader readOdt)
268+ ,("odt" , ByteStringReader readOdt)
266− ,("t2t" , mkStringReader readTxt2TagsNoMacros)
269+ -- ,("t2t" , mkStringReader readTxt2TagsNoMacros)
267− ,("epub" , mkBSReader readEPUB)
270+ ,("epub" , ByteStringReader readEPUB)
268 ]
271 ]
269
272
270data Writer m = StringWriter (WriterOptions -> Pandoc -> m String)
273data Writer m = StringWriter (WriterOptions -> Pandoc -> m String)
@@ -351,7 +354,7 @@ getDefaultExtensions "epub" = Set.fromList [Ext_raw_html,
351getDefaultExtensions _ = Set.fromList [Ext_auto_identifiers]
354getDefaultExtensions _ = Set.fromList [Ext_auto_identifiers]
352
355
353-- | Retrieve reader based on formatSpec (format+extensions).
356-- | Retrieve reader based on formatSpec (format+extensions).
354−getReader :: String -> Either String (Reader IO)
357+getReader :: PandocMonad m => String -> Either String (Reader m)
355getReader s =
358getReader s =
356 case parseFormatSpec s of
359 case parseFormatSpec s of
357 Left e -> Left $ intercalate "\n" [m | Message m <- errorMessages e]
360 Left e -> Left $ intercalate "\n" [m | Message m <- errorMessages e]
src/Text/Pandoc/Class.hs+10
@@ -35,6 +35,7 @@ module Text.Pandoc.Class ( PandocMonad(..)
35 , PureState(..)
35 , PureState(..)
36 , PureEnv(..)
36 , PureEnv(..)
37 , getPOSIXTime
37 , getPOSIXTime
38+ , addWarningWithPos
38 , PandocIO(..)
39 , PandocIO(..)
39 , PandocPure(..)
40 , PandocPure(..)
40 , PandocExecutionError(..)
41 , PandocExecutionError(..)
@@ -57,6 +58,7 @@ import qualified Text.Pandoc.Shared as IO ( fetchItem
57 , warn
58 , warn
58 , readDataFile)
59 , readDataFile)
59import Text.Pandoc.Compat.Time (UTCTime)
60import Text.Pandoc.Compat.Time (UTCTime)
61+import Text.Pandoc.Parsing (ParserT, ParserState, SourcePos)
60import qualified Text.Pandoc.Compat.Time as IO (getCurrentTime)
62import qualified Text.Pandoc.Compat.Time as IO (getCurrentTime)
61import Data.Time.Clock.POSIX ( utcTimeToPOSIXSeconds
63import Data.Time.Clock.POSIX ( utcTimeToPOSIXSeconds
62 , posixSecondsToUTCTime
64 , posixSecondsToUTCTime
@@ -109,6 +111,14 @@ class (Functor m, Applicative m, Monad m, MonadError PandocExecutionError m) =>
109getPOSIXTime :: (PandocMonad m) => m POSIXTime
111getPOSIXTime :: (PandocMonad m) => m POSIXTime
110getPOSIXTime = utcTimeToPOSIXSeconds <$> getCurrentTime
112getPOSIXTime = utcTimeToPOSIXSeconds <$> getCurrentTime
111
113
114+addWarningWithPos :: PandocMonad m
115+ => Maybe SourcePos
116+ -> String
117+ -> ParserT [Char] ParserState m ()
118+addWarningWithPos mbpos msg =
119+ lift $
120+ warn $
121+ msg ++ maybe "" (\pos -> " " ++ show pos) mbpos
112
122
113-- We can add to this as we go
123-- We can add to this as we go
114data PandocExecutionError = PandocFileReadError FilePath
124data PandocExecutionError = PandocFileReadError FilePath
src/Text/Pandoc/Readers/CommonMark.hs+4−3
@@ -37,11 +37,12 @@ import Data.Text (unpack, pack)
37import Data.List (groupBy)
37import Data.List (groupBy)
38import Text.Pandoc.Definition
38import Text.Pandoc.Definition
39import Text.Pandoc.Options
39import Text.Pandoc.Options
40−import Text.Pandoc.Error
40+import Text.Pandoc.Class (PandocMonad)
41
41
42-- | Parse a CommonMark formatted string into a 'Pandoc' structure.
42-- | Parse a CommonMark formatted string into a 'Pandoc' structure.
43−readCommonMark :: ReaderOptions -> String -> Either PandocError Pandoc
43+readCommonMark :: PandocMonad m => ReaderOptions -> String -> m Pandoc
44+readCommonMark opts s = return $
44−readCommonMark opts = Right . nodeToPandoc . commonmarkToNode opts' . pack
45+ nodeToPandoc $ commonmarkToNode opts' $ pack s
45 where opts' = if readerSmart opts
46 where opts' = if readerSmart opts
46 then [optNormalize, optSmart]
47 then [optNormalize, optSmart]
47 else [optNormalize]
48 else [optNormalize]
src/Text/Pandoc/Readers/DocBook.hs+16−16
@@ -13,10 +13,9 @@ import Control.Monad.State
13import Data.List (intersperse)
13import Data.List (intersperse)
14import Data.Maybe (fromMaybe)
14import Data.Maybe (fromMaybe)
15import Text.TeXMath (readMathML, writeTeX)
15import Text.TeXMath (readMathML, writeTeX)
16−import Text.Pandoc.Error (PandocError)
17−import Control.Monad.Except
18import Data.Default
16import Data.Default
19import Data.Foldable (asum)
17import Data.Foldable (asum)
18+import Text.Pandoc.Class (PandocMonad)
20
19
21{-
20{-
22
21
@@ -502,7 +501,7 @@ List of all DocBook tags, with [x] indicating implemented,
502[x] ?asciidoc-br? - line break from asciidoc docbook output
501[x] ?asciidoc-br? - line break from asciidoc docbook output
503-}
502-}
504
503
505−type DB = ExceptT PandocError (State DBState)
504+type DB m = StateT DBState m
506
505
507data DBState = DBState{ dbSectionLevel :: Int
506data DBState = DBState{ dbSectionLevel :: Int
508 , dbQuoteType :: QuoteType
507 , dbQuoteType :: QuoteType
@@ -523,10 +522,11 @@ instance Default DBState where
523 , dbContent = [] }
522 , dbContent = [] }
524
523
525
524
526−readDocBook :: ReaderOptions -> String -> Either PandocError Pandoc
525+readDocBook :: PandocMonad m => ReaderOptions -> String -> m Pandoc
527−readDocBook _ inp = (\blocks -> Pandoc (dbMeta st') (toList . mconcat $ blocks)) <$> bs
526+readDocBook _ inp = do
527+ let tree = normalizeTree . parseXML . handleInstructions $ inp
528− where (bs , st') = flip runState (def{ dbContent = tree }) . runExceptT . mapM parseBlock $ tree
528+ (bs, st') <- flip runStateT (def{ dbContent = tree }) $ mapM parseBlock $ tree
529− tree = normalizeTree . parseXML . handleInstructions $ inp
529+ return $ Pandoc (dbMeta st') (toList . mconcat $ bs)
530
530
531-- We treat <?asciidoc-br?> specially (issue #1236), converting it
531-- We treat <?asciidoc-br?> specially (issue #1236), converting it
532-- to <br/>, since xml-light doesn't parse the instruction correctly.
532-- to <br/>, since xml-light doesn't parse the instruction correctly.
@@ -538,7 +538,7 @@ handleInstructions xs = case break (=='<') xs of
538 ([], '<':zs) -> '<' : handleInstructions zs
538 ([], '<':zs) -> '<' : handleInstructions zs
539 (ys, zs) -> ys ++ handleInstructions zs
539 (ys, zs) -> ys ++ handleInstructions zs
540
540
541−getFigure :: Element -> DB Blocks
541+getFigure :: PandocMonad m => Element -> DB m Blocks
542getFigure e = do
542getFigure e = do
543 tit <- case filterChild (named "title") e of
543 tit <- case filterChild (named "title") e of
544 Just t -> getInlines t
544 Just t -> getInlines t
@@ -579,20 +579,20 @@ named s e = qName (elName e) == s
579
579
580--
580--
581
581
582−acceptingMetadata :: DB a -> DB a
582+acceptingMetadata :: PandocMonad m => DB m a -> DB m a
583acceptingMetadata p = do
583acceptingMetadata p = do
584 modify (\s -> s { dbAcceptsMeta = True } )
584 modify (\s -> s { dbAcceptsMeta = True } )
585 res <- p
585 res <- p
586 modify (\s -> s { dbAcceptsMeta = False })
586 modify (\s -> s { dbAcceptsMeta = False })
587 return res
587 return res
588
588
589−checkInMeta :: Monoid a => DB () -> DB a
589+checkInMeta :: (PandocMonad m, Monoid a) => DB m () -> DB m a
590checkInMeta p = do
590checkInMeta p = do
591 accepts <- dbAcceptsMeta <$> get
591 accepts <- dbAcceptsMeta <$> get
592 when accepts p
592 when accepts p
593 return mempty
593 return mempty
594
594
595−addMeta :: ToMetaValue a => String -> a -> DB ()
595+addMeta :: PandocMonad m => ToMetaValue a => String -> a -> DB m ()
596addMeta field val = modify (setMeta field val)
596addMeta field val = modify (setMeta field val)
597
597
598instance HasMeta DBState where
598instance HasMeta DBState where
@@ -631,7 +631,7 @@ addToStart toadd bs =
631-- function that is used by both mediaobject (in parseBlock)
631-- function that is used by both mediaobject (in parseBlock)
632-- and inlinemediaobject (in parseInline)
632-- and inlinemediaobject (in parseInline)
633-- A DocBook mediaobject is a wrapper around a set of alternative presentations
633-- A DocBook mediaobject is a wrapper around a set of alternative presentations
634−getMediaobject :: Element -> DB Inlines
634+getMediaobject :: PandocMonad m => Element -> DB m Inlines
635getMediaobject e = do
635getMediaobject e = do
636 (imageUrl, attr) <-
636 (imageUrl, attr) <-
637 case filterChild (named "imageobject") e of
637 case filterChild (named "imageobject") e of
@@ -658,11 +658,11 @@ getMediaobject e = do
658 else (return figTitle, "fig:")
658 else (return figTitle, "fig:")
659 liftM (imageWith attr imageUrl title) caption
659 liftM (imageWith attr imageUrl title) caption
660
660
661−getBlocks :: Element -> DB Blocks
661+getBlocks :: PandocMonad m => Element -> DB m Blocks
662getBlocks e = mconcat <$> (mapM parseBlock $ elContent e)
662getBlocks e = mconcat <$> (mapM parseBlock $ elContent e)
663
663
664
664
665−parseBlock :: Content -> DB Blocks
665+parseBlock :: PandocMonad m => Content -> DB m Blocks
666parseBlock (Text (CData CDataRaw _ _)) = return mempty -- DOCTYPE
666parseBlock (Text (CData CDataRaw _ _)) = return mempty -- DOCTYPE
667parseBlock (Text (CData _ s _)) = if all isSpace s
667parseBlock (Text (CData _ s _)) = if all isSpace s
668 then return mempty
668 then return mempty
@@ -902,7 +902,7 @@ parseBlock (Elem e) =
902 lineItems = mapM getInlines $ filterChildren (named "line") e
902 lineItems = mapM getInlines $ filterChildren (named "line") e
903 metaBlock = acceptingMetadata (getBlocks e) >> return mempty
903 metaBlock = acceptingMetadata (getBlocks e) >> return mempty
904
904
905−getInlines :: Element -> DB Inlines
905+getInlines :: PandocMonad m => Element -> DB m Inlines
906getInlines e' = (trimInlines . mconcat) <$> (mapM parseInline $ elContent e')
906getInlines e' = (trimInlines . mconcat) <$> (mapM parseInline $ elContent e')
907
907
908strContentRecursive :: Element -> String
908strContentRecursive :: Element -> String
@@ -913,7 +913,7 @@ elementToStr :: Content -> Content
913elementToStr (Elem e') = Text $ CData CDataText (strContentRecursive e') Nothing
913elementToStr (Elem e') = Text $ CData CDataText (strContentRecursive e') Nothing
914elementToStr x = x
914elementToStr x = x
915
915
916−parseInline :: Content -> DB Inlines
916+parseInline :: PandocMonad m => Content -> DB m Inlines
917parseInline (Text (CData _ s _)) = return $ text s
917parseInline (Text (CData _ s _)) = return $ text s
918parseInline (CRef ref) =
918parseInline (CRef ref) =
919 return $ maybe (text $ map toUpper ref) (text) $ lookupEntity ref
919 return $ maybe (text $ map toUpper ref) (text) $ lookupEntity ref
src/Text/Pandoc/Readers/Docx.hs+44−52
@@ -82,7 +82,7 @@ import Text.Pandoc.Readers.Docx.Parse
82import Text.Pandoc.Readers.Docx.Lists
82import Text.Pandoc.Readers.Docx.Lists
83import Text.Pandoc.Readers.Docx.Combine
83import Text.Pandoc.Readers.Docx.Combine
84import Text.Pandoc.Shared
84import Text.Pandoc.Shared
85−import Text.Pandoc.MediaBag (insertMedia, MediaBag)
85+import Text.Pandoc.MediaBag (MediaBag)
86import Data.List (delete, intersect)
86import Data.List (delete, intersect)
87import Text.TeXMath (writeTeX)
87import Text.TeXMath (writeTeX)
88import Data.Default (Default)
88import Data.Default (Default)
@@ -96,27 +96,28 @@ import qualified Data.Sequence as Seq (null)
96#if !(MIN_VERSION_base(4,8,0))
96#if !(MIN_VERSION_base(4,8,0))
97import Data.Traversable (traverse)
97import Data.Traversable (traverse)
98#endif
98#endif
99+import Control.Monad.Except (throwError)
100+import Text.Pandoc.Class (PandocMonad, PandocExecutionError(..))
101+import qualified Text.Pandoc.Class as P
99
102
100−import Text.Pandoc.Error
103+readDocx :: PandocMonad m
101−import Control.Monad.Except
102−
103−readDocxWithWarnings :: ReaderOptions
104+ => ReaderOptions
104− -> B.ByteString
105+ -> B.ByteString
105− -> Either PandocError (Pandoc, MediaBag, [String])
106+ -> m Pandoc
106−readDocxWithWarnings opts bytes
107+readDocx opts bytes
107 | Right archive <- toArchiveOrFail bytes
108 | Right archive <- toArchiveOrFail bytes
108 , Right (docx, parserWarnings) <- archiveToDocxWithWarnings archive = do
109 , Right (docx, parserWarnings) <- archiveToDocxWithWarnings archive = do
110+ mapM_ P.warn parserWarnings
109− (meta, blks, mediaBag, warnings) <- docxToOutput opts docx
111+ (meta, blks) <- docxToOutput opts docx
110− return (Pandoc meta blks, mediaBag, parserWarnings ++ warnings)
112+ return $ Pandoc meta blks
111−readDocxWithWarnings _ _ =
113+readDocx _ _ =
112− Left (ParseFailure "couldn't parse docx file")
114+ throwError $ PandocSomeError "couldn't parse docx file"
113−
115+
116+readDocxWithWarnings :: PandocMonad m
114−readDocx :: ReaderOptions
117+ => ReaderOptions
115 -> B.ByteString
118 -> B.ByteString
116− -> Either PandocError (Pandoc, MediaBag)
119+ -> m Pandoc
117−readDocx opts bytes = do
118− (pandoc, mediaBag, _) <- readDocxWithWarnings opts bytes
120+readDocxWithWarnings = readDocx
119− return (pandoc, mediaBag)
120
121
121data DState = DState { docxAnchorMap :: M.Map String String
122data DState = DState { docxAnchorMap :: M.Map String String
122 , docxMediaBag :: MediaBag
123 , docxMediaBag :: MediaBag
@@ -137,15 +138,10 @@ data DEnv = DEnv { docxOptions :: ReaderOptions
137instance Default DEnv where
138instance Default DEnv where
138 def = DEnv def False
139 def = DEnv def False
139
140
140−type DocxContext = ExceptT PandocError (ReaderT DEnv (State DState))
141+type DocxContext m = ReaderT DEnv (StateT DState m)
141
142
142−evalDocxContext :: DocxContext a -> DEnv -> DState -> Either PandocError a
143+evalDocxContext :: PandocMonad m => DocxContext m a -> DEnv -> DState -> m a
143−evalDocxContext ctx env st = flip evalState st . flip runReaderT env . runExceptT $ ctx
144+evalDocxContext ctx env st = flip evalStateT st $ flip runReaderT env $ ctx
144−
145−addDocxWarning :: String -> DocxContext ()
146−addDocxWarning msg = do
147− warnings <- gets docxWarnings
148− modify $ \s -> s {docxWarnings = msg : warnings}
149
145
150-- This is empty, but we put it in for future-proofing.
146-- This is empty, but we put it in for future-proofing.
151spansToKeep :: [String]
147spansToKeep :: [String]
@@ -179,7 +175,7 @@ isEmptyPar (Paragraph _ parParts) =
179 isEmptyElem _ = True
175 isEmptyElem _ = True
180isEmptyPar _ = False
176isEmptyPar _ = False
181
177
182−bodyPartsToMeta' :: [BodyPart] -> DocxContext (M.Map String MetaValue)
178+bodyPartsToMeta' :: PandocMonad m => [BodyPart] -> DocxContext m (M.Map String MetaValue)
183bodyPartsToMeta' [] = return M.empty
179bodyPartsToMeta' [] = return M.empty
184bodyPartsToMeta' (bp : bps)
180bodyPartsToMeta' (bp : bps)
185 | (Paragraph pPr parParts) <- bp
181 | (Paragraph pPr parParts) <- bp
@@ -195,7 +191,7 @@ bodyPartsToMeta' (bp : bps)
195 return $ M.insertWith f metaField (MetaInlines (toList inlines)) remaining
191 return $ M.insertWith f metaField (MetaInlines (toList inlines)) remaining
196bodyPartsToMeta' (_ : bps) = bodyPartsToMeta' bps
192bodyPartsToMeta' (_ : bps) = bodyPartsToMeta' bps
197
193
198−bodyPartsToMeta :: [BodyPart] -> DocxContext Meta
194+bodyPartsToMeta :: PandocMonad m => [BodyPart] -> DocxContext m Meta
199bodyPartsToMeta bps = do
195bodyPartsToMeta bps = do
200 mp <- bodyPartsToMeta' bps
196 mp <- bodyPartsToMeta' bps
201 let mp' =
197 let mp' =
@@ -297,7 +293,7 @@ runStyleToTransform rPr
297 emph . (runStyleToTransform rPr {rUnderline = Nothing})
293 emph . (runStyleToTransform rPr {rUnderline = Nothing})
298 | otherwise = id
294 | otherwise = id
299
295
300−runToInlines :: Run -> DocxContext Inlines
296+runToInlines :: PandocMonad m => Run -> DocxContext m Inlines
301runToInlines (Run rs runElems)
297runToInlines (Run rs runElems)
302 | Just (s, _) <- rStyle rs
298 | Just (s, _) <- rStyle rs
303 , s `elem` codeStyles =
299 , s `elem` codeStyles =
@@ -318,8 +314,7 @@ runToInlines (Endnote bps) = do
318 blksList <- smushBlocks <$> (mapM bodyPartToBlocks bps)
314 blksList <- smushBlocks <$> (mapM bodyPartToBlocks bps)
319 return $ note blksList
315 return $ note blksList
320runToInlines (InlineDrawing fp title alt bs ext) = do
316runToInlines (InlineDrawing fp title alt bs ext) = do
321− mediaBag <- gets docxMediaBag
322− modify $ \s -> s { docxMediaBag = insertMedia fp Nothing bs mediaBag }
317+ (lift . lift) $ P.insertMedia fp Nothing bs
323 return $ imageWith (extentToAttr ext) fp title $ text alt
318 return $ imageWith (extentToAttr ext) fp title $ text alt
324runToInlines InlineChart = return $ spanWith ("", ["chart"], []) $ text "[CHART]"
319runToInlines InlineChart = return $ spanWith ("", ["chart"], []) $ text "[CHART]"
325
320
@@ -330,7 +325,7 @@ extentToAttr (Just (w, h)) =
330 showDim d = show (d / 914400) ++ "in"
325 showDim d = show (d / 914400) ++ "in"
331extentToAttr _ = nullAttr
326extentToAttr _ = nullAttr
332
327
333−blocksToInlinesWarn :: String -> Blocks -> DocxContext Inlines
328+blocksToInlinesWarn :: PandocMonad m => String -> Blocks -> DocxContext m Inlines
334blocksToInlinesWarn cmtId blks = do
329blocksToInlinesWarn cmtId blks = do
335 let blkList = toList blks
330 let blkList = toList blks
336 notParaOrPlain :: Block -> Bool
331 notParaOrPlain :: Block -> Bool
@@ -338,10 +333,10 @@ blocksToInlinesWarn cmtId blks = do
338 notParaOrPlain (Plain _) = False
333 notParaOrPlain (Plain _) = False
339 notParaOrPlain _ = True
334 notParaOrPlain _ = True
340 when (not $ null $ filter notParaOrPlain blkList)
335 when (not $ null $ filter notParaOrPlain blkList)
341− (addDocxWarning $ "Docx comment " ++ cmtId ++ " will not retain formatting")
336+ ((lift . lift) $ P.warn $ "Docx comment " ++ cmtId ++ " will not retain formatting")
342 return $ fromList $ blocksToInlines blkList
337 return $ fromList $ blocksToInlines blkList
343
338
344−parPartToInlines :: ParPart -> DocxContext Inlines
339+parPartToInlines :: PandocMonad m => ParPart -> DocxContext m Inlines
345parPartToInlines (PlainRun r) = runToInlines r
340parPartToInlines (PlainRun r) = runToInlines r
346parPartToInlines (Insertion _ author date runs) = do
341parPartToInlines (Insertion _ author date runs) = do
347 opts <- asks docxOptions
342 opts <- asks docxOptions
@@ -403,8 +398,7 @@ parPartToInlines (BookMark _ anchor) =
403 (modify $ \s -> s { docxAnchorMap = M.insert anchor newAnchor anchorMap})
398 (modify $ \s -> s { docxAnchorMap = M.insert anchor newAnchor anchorMap})
404 return $ spanWith (newAnchor, ["anchor"], []) mempty
399 return $ spanWith (newAnchor, ["anchor"], []) mempty
405parPartToInlines (Drawing fp title alt bs ext) = do
400parPartToInlines (Drawing fp title alt bs ext) = do
406− mediaBag <- gets docxMediaBag
407− modify $ \s -> s { docxMediaBag = insertMedia fp Nothing bs mediaBag }
401+ (lift . lift) $ P.insertMedia fp Nothing bs
408 return $ imageWith (extentToAttr ext) fp title $ text alt
402 return $ imageWith (extentToAttr ext) fp title $ text alt
409parPartToInlines Chart = do
403parPartToInlines Chart = do
410 return $ spanWith ("", ["chart"], []) $ text "[CHART]"
404 return $ spanWith ("", ["chart"], []) $ text "[CHART]"
@@ -426,10 +420,10 @@ isAnchorSpan _ = False
426dummyAnchors :: [String]
420dummyAnchors :: [String]
427dummyAnchors = ["_GoBack"]
421dummyAnchors = ["_GoBack"]
428
422
429−makeHeaderAnchor :: Blocks -> DocxContext Blocks
423+makeHeaderAnchor :: PandocMonad m => Blocks -> DocxContext m Blocks
430makeHeaderAnchor bs = traverse makeHeaderAnchor' bs
424makeHeaderAnchor bs = traverse makeHeaderAnchor' bs
431
425
432−makeHeaderAnchor' :: Block -> DocxContext Block
426+makeHeaderAnchor' :: PandocMonad m => Block -> DocxContext m Block
433-- If there is an anchor already there (an anchor span in the header,
427-- If there is an anchor already there (an anchor span in the header,
434-- to be exact), we rename and associate the new id with the old one.
428-- to be exact), we rename and associate the new id with the old one.
435makeHeaderAnchor' (Header n (ident, classes, kvs) ils)
429makeHeaderAnchor' (Header n (ident, classes, kvs) ils)
@@ -463,12 +457,12 @@ singleParaToPlain blks
463 singleton $ Plain ils
457 singleton $ Plain ils
464singleParaToPlain blks = blks
458singleParaToPlain blks = blks
465
459
466−cellToBlocks :: Cell -> DocxContext Blocks
460+cellToBlocks :: PandocMonad m => Cell -> DocxContext m Blocks
467cellToBlocks (Cell bps) = do
461cellToBlocks (Cell bps) = do
468 blks <- smushBlocks <$> mapM bodyPartToBlocks bps
462 blks <- smushBlocks <$> mapM bodyPartToBlocks bps
469 return $ fromList $ blocksToDefinitions $ blocksToBullets $ toList blks
463 return $ fromList $ blocksToDefinitions $ blocksToBullets $ toList blks
470
464
471−rowToBlocksList :: Row -> DocxContext [Blocks]
465+rowToBlocksList :: PandocMonad m => Row -> DocxContext m [Blocks]
472rowToBlocksList (Row cells) = do
466rowToBlocksList (Row cells) = do
473 blksList <- mapM cellToBlocks cells
467 blksList <- mapM cellToBlocks cells
474 return $ map singleParaToPlain blksList
468 return $ map singleParaToPlain blksList
@@ -518,7 +512,7 @@ parStyleToTransform pPr
518 False -> parStyleToTransform pPr'
512 False -> parStyleToTransform pPr'
519parStyleToTransform _ = id
513parStyleToTransform _ = id
520
514
521−bodyPartToBlocks :: BodyPart -> DocxContext Blocks
515+bodyPartToBlocks :: PandocMonad m => BodyPart -> DocxContext m Blocks
522bodyPartToBlocks (Paragraph pPr parparts)
516bodyPartToBlocks (Paragraph pPr parparts)
523 | not $ null $ codeDivs `intersect` (pStyle pPr) =
517 | not $ null $ codeDivs `intersect` (pStyle pPr) =
524 return
518 return
@@ -597,7 +591,7 @@ bodyPartToBlocks (OMathPara e) = do
597
591
598
592
599-- replace targets with generated anchors.
593-- replace targets with generated anchors.
600−rewriteLink' :: Inline -> DocxContext Inline
594+rewriteLink' :: PandocMonad m => Inline -> DocxContext m Inline
601rewriteLink' l@(Link attr ils ('#':target, title)) = do
595rewriteLink' l@(Link attr ils ('#':target, title)) = do
602 anchorMap <- gets docxAnchorMap
596 anchorMap <- gets docxAnchorMap
603 return $ case M.lookup target anchorMap of
597 return $ case M.lookup target anchorMap of
@@ -605,23 +599,21 @@ rewriteLink' l@(Link attr ils ('#':target, title)) = do
605 Nothing -> l
599 Nothing -> l
606rewriteLink' il = return il
600rewriteLink' il = return il
607
601
608−rewriteLinks :: [Block] -> DocxContext [Block]
602+rewriteLinks :: PandocMonad m => [Block] -> DocxContext m [Block]
609rewriteLinks = mapM (walkM rewriteLink')
603rewriteLinks = mapM (walkM rewriteLink')
610
604
611−bodyToOutput :: Body -> DocxContext (Meta, [Block], MediaBag, [String])
605+bodyToOutput :: PandocMonad m => Body -> DocxContext m (Meta, [Block])
612bodyToOutput (Body bps) = do
606bodyToOutput (Body bps) = do
613 let (metabps, blkbps) = sepBodyParts bps
607 let (metabps, blkbps) = sepBodyParts bps
614 meta <- bodyPartsToMeta metabps
608 meta <- bodyPartsToMeta metabps
615 blks <- smushBlocks <$> mapM bodyPartToBlocks blkbps
609 blks <- smushBlocks <$> mapM bodyPartToBlocks blkbps
616 blks' <- rewriteLinks $ blocksToDefinitions $ blocksToBullets $ toList blks
610 blks' <- rewriteLinks $ blocksToDefinitions $ blocksToBullets $ toList blks
617− mediaBag <- gets docxMediaBag
618− warnings <- gets docxWarnings
619− return $ (meta,
611+ return $ (meta, blks')
620− blks',
612+
621− mediaBag,
613+docxToOutput :: PandocMonad m
622− warnings)
614+ => ReaderOptions
623−
615+ -> Docx
624−docxToOutput :: ReaderOptions -> Docx -> Either PandocError (Meta, [Block], MediaBag, [String])
616+ -> m (Meta, [Block])
625docxToOutput opts (Docx (Document _ body)) =
617docxToOutput opts (Docx (Document _ body)) =
626 let dEnv = def { docxOptions = opts} in
618 let dEnv = def { docxOptions = opts} in
627 evalDocxContext (bodyToOutput body) dEnv def
619 evalDocxContext (bodyToOutput body) dEnv def
src/Text/Pandoc/Readers/EPUB.hs+24−26
@@ -11,13 +11,12 @@ module Text.Pandoc.Readers.EPUB
11import Text.XML.Light
11import Text.XML.Light
12import Text.Pandoc.Definition hiding (Attr)
12import Text.Pandoc.Definition hiding (Attr)
13import Text.Pandoc.Readers.HTML (readHtml)
13import Text.Pandoc.Readers.HTML (readHtml)
14−import Text.Pandoc.Error
15import Text.Pandoc.Walk (walk, query)
14import Text.Pandoc.Walk (walk, query)
16import Text.Pandoc.Options ( ReaderOptions(..), readerTrace)
15import Text.Pandoc.Options ( ReaderOptions(..), readerTrace)
17import Text.Pandoc.Shared (escapeURI, collapseFilePath, addMetaField)
16import Text.Pandoc.Shared (escapeURI, collapseFilePath, addMetaField)
18import Network.URI (unEscapeString)
17import Network.URI (unEscapeString)
19import Text.Pandoc.MediaBag (MediaBag, insertMedia)
18import Text.Pandoc.MediaBag (MediaBag, insertMedia)
20−import Control.Monad.Except (MonadError, throwError, runExcept, Except)
19+import Control.Monad.Except (throwError)
21import Text.Pandoc.MIME (MimeType)
20import Text.Pandoc.MIME (MimeType)
22import qualified Text.Pandoc.Builder as B
21import qualified Text.Pandoc.Builder as B
23import Codec.Archive.Zip ( Archive (..), toArchiveOrFail, fromEntry
22import Codec.Archive.Zip ( Archive (..), toArchiveOrFail, fromEntry
@@ -33,23 +32,25 @@ import Data.Maybe (mapMaybe, fromMaybe)
33import qualified Data.Map as M (Map, lookup, fromList, elems)
32import qualified Data.Map as M (Map, lookup, fromList, elems)
34import Data.Monoid ((<>))
33import Data.Monoid ((<>))
35import Control.DeepSeq (deepseq, NFData)
34import Control.DeepSeq (deepseq, NFData)
35+import Text.Pandoc.Class (PandocMonad, PandocExecutionError(..))
36+import qualified Text.Pandoc.Class as P
36
37
37import Debug.Trace (trace)
38import Debug.Trace (trace)
38
39
39type Items = M.Map String (FilePath, MimeType)
40type Items = M.Map String (FilePath, MimeType)
40
41
41−readEPUB :: ReaderOptions -> BL.ByteString -> Either PandocError (Pandoc, MediaBag)
42+readEPUB :: PandocMonad m => ReaderOptions -> BL.ByteString -> m Pandoc
42readEPUB opts bytes = case toArchiveOrFail bytes of
43readEPUB opts bytes = case toArchiveOrFail bytes of
43− Right archive -> runEPUB $ archiveToEPUB opts $ archive
44+ Right archive -> archiveToEPUB opts $ archive
44− Left _ -> Left $ ParseFailure "Couldn't extract ePub file"
45+ Left _ -> throwError $ PandocParseError "Couldn't extract ePub file"
45
46
46−runEPUB :: Except PandocError a -> Either PandocError a
47+-- runEPUB :: Except PandocError a -> Either PandocError a
47−runEPUB = runExcept
48+-- runEPUB = runExcept
48
49
49-- Note that internal reference are aggresively normalised so that all ids
50-- Note that internal reference are aggresively normalised so that all ids
50-- are of the form "filename#id"
51-- are of the form "filename#id"
51--
52--
52−archiveToEPUB :: (MonadError PandocError m) => ReaderOptions -> Archive -> m (Pandoc, MediaBag)
53+archiveToEPUB :: (PandocMonad m) => ReaderOptions -> Archive -> m Pandoc
53archiveToEPUB os archive = do
54archiveToEPUB os archive = do
54 -- root is path to folder with manifest file in
55 -- root is path to folder with manifest file in
55 (root, content) <- getManifest archive
56 (root, content) <- getManifest archive
@@ -63,24 +64,21 @@ archiveToEPUB os archive = do
63 foldM' (\a b -> ((a <>) . walk (prependHash escapedSpine))
64 foldM' (\a b -> ((a <>) . walk (prependHash escapedSpine))
64 `liftM` parseSpineElem root b) mempty spine
65 `liftM` parseSpineElem root b) mempty spine
65 let ast = coverDoc <> (Pandoc meta bs)
66 let ast = coverDoc <> (Pandoc meta bs)
66− let mediaBag = fetchImages (M.elems items) root archive ast
67+ P.setMediaBag $ fetchImages (M.elems items) root archive ast
67− return $ (ast, mediaBag)
68+ return ast
68 where
69 where
69 os' = os {readerParseRaw = True}
70 os' = os {readerParseRaw = True}
70− parseSpineElem :: MonadError PandocError m => FilePath -> (FilePath, MimeType) -> m Pandoc
71+ parseSpineElem :: PandocMonad m => FilePath -> (FilePath, MimeType) -> m Pandoc
71 parseSpineElem (normalise -> r) (normalise -> path, mime) = do
72 parseSpineElem (normalise -> r) (normalise -> path, mime) = do
72 when (readerTrace os) (traceM path)
73 when (readerTrace os) (traceM path)
73 doc <- mimeToReader mime r path
74 doc <- mimeToReader mime r path
74 let docSpan = B.doc $ B.para $ B.spanWith (takeFileName path, [], []) mempty
75 let docSpan = B.doc $ B.para $ B.spanWith (takeFileName path, [], []) mempty
75 return $ docSpan <> doc
76 return $ docSpan <> doc
76− mimeToReader :: MonadError PandocError m => MimeType -> FilePath -> FilePath -> m Pandoc
77+ mimeToReader :: PandocMonad m => MimeType -> FilePath -> FilePath -> m Pandoc
77 mimeToReader "application/xhtml+xml" (unEscapeString -> root)
78 mimeToReader "application/xhtml+xml" (unEscapeString -> root)
78 (unEscapeString -> path) = do
79 (unEscapeString -> path) = do
79 fname <- findEntryByPathE (root </> path) archive
80 fname <- findEntryByPathE (root </> path) archive
80− html <- either throwError return .
81− readHtml os' .
82− UTF8.toStringLazy $
81+ html <- readHtml os' . UTF8.toStringLazy $ fromEntry fname
83− fromEntry fname
84 return $ fixInternalReferences path html
82 return $ fixInternalReferences path html
85 mimeToReader s _ (unEscapeString -> path)
83 mimeToReader s _ (unEscapeString -> path)
86 | s `elem` imageMimes = return $ imageToPandoc path
84 | s `elem` imageMimes = return $ imageToPandoc path
@@ -121,7 +119,7 @@ imageMimes = ["image/gif", "image/jpeg", "image/png"]
121
119
122type CoverImage = FilePath
120type CoverImage = FilePath
123
121
124−parseManifest :: (MonadError PandocError m) => Element -> m (Maybe CoverImage, Items)
122+parseManifest :: (PandocMonad m) => Element -> m (Maybe CoverImage, Items)
125parseManifest content = do
123parseManifest content = do
126 manifest <- findElementE (dfName "manifest") content
124 manifest <- findElementE (dfName "manifest") content
127 let items = findChildren (dfName "item") manifest
125 let items = findChildren (dfName "item") manifest
@@ -137,7 +135,7 @@ parseManifest content = do
137 mime <- findAttrE (emptyName "media-type") e
135 mime <- findAttrE (emptyName "media-type") e
138 return (uid, (href, mime))
136 return (uid, (href, mime))
139
137
140−parseSpine :: MonadError PandocError m => Items -> Element -> m [(FilePath, MimeType)]
138+parseSpine :: PandocMonad m => Items -> Element -> m [(FilePath, MimeType)]
141parseSpine is e = do
139parseSpine is e = do
142 spine <- findElementE (dfName "spine") e
140 spine <- findElementE (dfName "spine") e
143 let itemRefs = findChildren (dfName "itemref") spine
141 let itemRefs = findChildren (dfName "itemref") spine
@@ -148,7 +146,7 @@ parseSpine is e = do
148 guard linear
146 guard linear
149 findAttr (emptyName "idref") ref
147 findAttr (emptyName "idref") ref
150
148
151−parseMeta :: MonadError PandocError m => Element -> m Meta
149+parseMeta :: PandocMonad m => Element -> m Meta
152parseMeta content = do
150parseMeta content = do
153 meta <- findElementE (dfName "metadata") content
151 meta <- findElementE (dfName "metadata") content
154 let dcspace (QName _ (Just "http://purl.org/dc/elements/1.1/") (Just "dc")) = True
152 let dcspace (QName _ (Just "http://purl.org/dc/elements/1.1/") (Just "dc")) = True
@@ -166,7 +164,7 @@ renameMeta :: String -> String
166renameMeta "creator" = "author"
164renameMeta "creator" = "author"
167renameMeta s = s
165renameMeta s = s
168
166
169−getManifest :: MonadError PandocError m => Archive -> m (String, Element)
167+getManifest :: PandocMonad m => Archive -> m (String, Element)
170getManifest archive = do
168getManifest archive = do
171 metaEntry <- findEntryByPathE ("META-INF" </> "container.xml") archive
169 metaEntry <- findEntryByPathE ("META-INF" </> "container.xml") archive
172 docElem <- (parseXMLDocE . UTF8.toStringLazy . fromEntry) metaEntry
170 docElem <- (parseXMLDocE . UTF8.toStringLazy . fromEntry) metaEntry
@@ -268,18 +266,18 @@ emptyName s = QName s Nothing Nothing
268
266
269-- Convert Maybe interface to Either
267-- Convert Maybe interface to Either
270
268
271−findAttrE :: MonadError PandocError m => QName -> Element -> m String
269+findAttrE :: PandocMonad m => QName -> Element -> m String
272findAttrE q e = mkE "findAttr" $ findAttr q e
270findAttrE q e = mkE "findAttr" $ findAttr q e
273
271
274−findEntryByPathE :: MonadError PandocError m => FilePath -> Archive -> m Entry
272+findEntryByPathE :: PandocMonad m => FilePath -> Archive -> m Entry
275findEntryByPathE (normalise -> path) a =
273findEntryByPathE (normalise -> path) a =
276 mkE ("No entry on path: " ++ path) $ findEntryByPath path a
274 mkE ("No entry on path: " ++ path) $ findEntryByPath path a
277
275
278−parseXMLDocE :: MonadError PandocError m => String -> m Element
276+parseXMLDocE :: PandocMonad m => String -> m Element
279parseXMLDocE doc = mkE "Unable to parse XML doc" $ parseXMLDoc doc
277parseXMLDocE doc = mkE "Unable to parse XML doc" $ parseXMLDoc doc
280
278
281−findElementE :: MonadError PandocError m => QName -> Element -> m Element
279+findElementE :: PandocMonad m => QName -> Element -> m Element
282findElementE e x = mkE ("Unable to find element: " ++ show e) $ findElement e x
280findElementE e x = mkE ("Unable to find element: " ++ show e) $ findElement e x
283
281
284−mkE :: MonadError PandocError m => String -> Maybe a -> m a
282+mkE :: PandocMonad m => String -> Maybe a -> m a
285−mkE s = maybe (throwError . ParseFailure $ s) return
283+mkE s = maybe (throwError . PandocParseError $ s) return
src/Text/Pandoc/Readers/HTML.hs+115−98
@@ -44,7 +44,7 @@ import Text.Pandoc.Definition
44import qualified Text.Pandoc.Builder as B
44import qualified Text.Pandoc.Builder as B
45import Text.Pandoc.Builder (Blocks, Inlines, trimInlines, HasMeta(..))
45import Text.Pandoc.Builder (Blocks, Inlines, trimInlines, HasMeta(..))
46import Text.Pandoc.Shared ( extractSpaces, renderTags', addMetaField
46import Text.Pandoc.Shared ( extractSpaces, renderTags', addMetaField
47− , escapeURI, safeRead, mapLeft )
47+ , escapeURI, safeRead )
48import Text.Pandoc.Options (ReaderOptions(readerParseRaw, readerTrace)
48import Text.Pandoc.Options (ReaderOptions(readerParseRaw, readerTrace)
49 , Extension (Ext_epub_html_exts,
49 , Extension (Ext_epub_html_exts,
50 Ext_native_divs, Ext_native_spans))
50 Ext_native_divs, Ext_native_spans))
@@ -62,38 +62,46 @@ import Text.Printf (printf)
62import Debug.Trace (trace)
62import Debug.Trace (trace)
63import Text.TeXMath (readMathML, writeTeX)
63import Text.TeXMath (readMathML, writeTeX)
64import Data.Default (Default (..), def)
64import Data.Default (Default (..), def)
65−import Control.Monad.Reader (Reader,ask, asks, local, runReader)
65+import Control.Monad.Reader (ask, asks, local, ReaderT, runReaderT, lift)
66import Network.URI (URI, parseURIReference, nonStrictRelativeTo)
66import Network.URI (URI, parseURIReference, nonStrictRelativeTo)
67−import Text.Pandoc.Error
68import Text.Pandoc.CSS (foldOrElse, pickStyleAttrProps)
67import Text.Pandoc.CSS (foldOrElse, pickStyleAttrProps)
69import Data.Monoid ((<>))
68import Data.Monoid ((<>))
70import Text.Parsec.Error
69import Text.Parsec.Error
71import qualified Data.Set as Set
70import qualified Data.Set as Set
71+import Text.Pandoc.Class (PandocMonad, PandocExecutionError(..))
72+import Control.Monad.Except (throwError)
73+
72
74
73-- | Convert HTML-formatted string to 'Pandoc' document.
75-- | Convert HTML-formatted string to 'Pandoc' document.
76+readHtml :: PandocMonad m
74−readHtml :: ReaderOptions -- ^ Reader options
77+ => ReaderOptions -- ^ Reader options
75 -> String -- ^ String to parse (assumes @'\n'@ line endings)
78 -> String -- ^ String to parse (assumes @'\n'@ line endings)
76− -> Either PandocError Pandoc
79+ -> m Pandoc
77−readHtml opts inp =
80+readHtml opts inp = do
78− mapLeft (ParseFailure . getError) . flip runReader def $
79− runParserT parseDoc
80− (HTMLState def{ stateOptions = opts } [] Nothing Set.empty M.empty)
81− "source" tags
82− where tags = stripPrefixes . canonicalizeTags $
81+ let tags = stripPrefixes . canonicalizeTags $
83− parseTagsOptions parseOptions{ optTagPosition = True } inp
82+ parseTagsOptions parseOptions{ optTagPosition = True } inp
84− parseDoc = do
83+ parseDoc = do
85− blocks <- (fixPlains False) . mconcat <$> manyTill block eof
84+ blocks <- (fixPlains False) . mconcat <$> manyTill block eof
86− meta <- stateMeta . parserState <$> getState
85+ meta <- stateMeta . parserState <$> getState
87− bs' <- replaceNotes (B.toList blocks)
86+ bs' <- replaceNotes (B.toList blocks)
88− return $ Pandoc meta bs'
87+ return $ Pandoc meta bs'
89− getError (errorMessages -> ms) = case ms of
88+ getError (errorMessages -> ms) = case ms of
90− [] -> ""
89+ [] -> ""
91− (m:_) -> messageString m
90+ (m:_) -> messageString m
92−
91+ result <- flip runReaderT def $
92+ runParserT parseDoc
93+ (HTMLState def{ stateOptions = opts } [] Nothing Set.empty M.empty)
94+ "source" tags
95+ case result of
96+ Right doc -> return doc
97+ Left err -> throwError $ PandocParseError $ getError err
98+
99+ where
100+
93−replaceNotes :: [Block] -> TagParser [Block]
101+replaceNotes :: PandocMonad m => [Block] -> TagParser m [Block]
94replaceNotes = walkM replaceNotes'
102replaceNotes = walkM replaceNotes'
95
103
96−replaceNotes' :: Inline -> TagParser Inline
104+replaceNotes' :: PandocMonad m => Inline -> TagParser m Inline
97replaceNotes' (RawInline (Format "noteref") ref) = maybe (Str "") (Note . B.toList) . lookup ref <$> getNotes
105replaceNotes' (RawInline (Format "noteref") ref) = maybe (Str "") (Note . B.toList) . lookup ref <$> getNotes
98 where
106 where
99 getNotes = noteTable <$> getState
107 getNotes = noteTable <$> getState
@@ -113,20 +121,20 @@ data HTMLLocal = HTMLLocal { quoteContext :: QuoteContext
113 , inPlain :: Bool -- ^ Set if in pPlain
121 , inPlain :: Bool -- ^ Set if in pPlain
114 }
122 }
115
123
116−setInChapter :: HTMLParser s a -> HTMLParser s a
124+setInChapter :: PandocMonad m => HTMLParser m s a -> HTMLParser m s a
117setInChapter = local (\s -> s {inChapter = True})
125setInChapter = local (\s -> s {inChapter = True})
118
126
119−setInPlain :: HTMLParser s a -> HTMLParser s a
127+setInPlain :: PandocMonad m => HTMLParser m s a -> HTMLParser m s a
120setInPlain = local (\s -> s {inPlain = True})
128setInPlain = local (\s -> s {inPlain = True})
121
129
122−type HTMLParser s = ParserT s HTMLState (Reader HTMLLocal)
130+type HTMLParser m s = ParserT s HTMLState (ReaderT HTMLLocal m)
123
131
124−type TagParser = HTMLParser [Tag String]
132+type TagParser m = HTMLParser m [Tag String]
125
133
126−pBody :: TagParser Blocks
134+pBody :: PandocMonad m => TagParser m Blocks
127pBody = pInTags "body" block
135pBody = pInTags "body" block
128
136
129−pHead :: TagParser Blocks
137+pHead :: PandocMonad m => TagParser m Blocks
130pHead = pInTags "head" $ pTitle <|> pMetaTag <|> pBaseTag <|> (mempty <$ pAnyTag)
138pHead = pInTags "head" $ pTitle <|> pMetaTag <|> pBaseTag <|> (mempty <$ pAnyTag)
131 where pTitle = pInTags "title" inline >>= setTitle . trimInlines
139 where pTitle = pInTags "title" inline >>= setTitle . trimInlines
132 setTitle t = mempty <$ (updateState $ B.setMeta "title" t)
140 setTitle t = mempty <$ (updateState $ B.setMeta "title" t)
@@ -149,7 +157,7 @@ pHead = pInTags "head" $ pTitle <|> pMetaTag <|> pBaseTag <|> (mempty <$ pAnyTag
149 parseURIReference $ fromAttrib "href" bt }
157 parseURIReference $ fromAttrib "href" bt }
150 return mempty
158 return mempty
151
159
152−block :: TagParser Blocks
160+block :: PandocMonad m => TagParser m Blocks
153block = do
161block = do
154 tr <- getOption readerTrace
162 tr <- getOption readerTrace
155 pos <- getPosition
163 pos <- getPosition
@@ -176,13 +184,16 @@ block = do
176 (take 60 $ show $ B.toList res)) (return ())
184 (take 60 $ show $ B.toList res)) (return ())
177 return res
185 return res
178
186
179−namespaces :: [(String, TagParser Inlines)]
187+namespaces :: PandocMonad m => [(String, TagParser m Inlines)]
180namespaces = [(mathMLNamespace, pMath True)]
188namespaces = [(mathMLNamespace, pMath True)]
181
189
182mathMLNamespace :: String
190mathMLNamespace :: String
183mathMLNamespace = "http://www.w3.org/1998/Math/MathML"
191mathMLNamespace = "http://www.w3.org/1998/Math/MathML"
184
192
185−eSwitch :: Monoid a => (Inlines -> a) -> TagParser a -> TagParser a
193+eSwitch :: (PandocMonad m, Monoid a)
194+ => (Inlines -> a)
195+ -> TagParser m a
196+ -> TagParser m a
186eSwitch constructor parser = try $ do
197eSwitch constructor parser = try $ do
187 guardEnabled Ext_epub_html_exts
198 guardEnabled Ext_epub_html_exts
188 pSatisfy (~== TagOpen "switch" [])
199 pSatisfy (~== TagOpen "switch" [])
@@ -195,7 +206,7 @@ eSwitch constructor parser = try $ do
195 pSatisfy (~== TagClose "switch")
206 pSatisfy (~== TagClose "switch")
196 return $ maybe fallback constructor cases
207 return $ maybe fallback constructor cases
197
208
198−eCase :: TagParser (Maybe Inlines)
209+eCase :: PandocMonad m => TagParser m (Maybe Inlines)
199eCase = do
210eCase = do
200 skipMany pBlank
211 skipMany pBlank
201 TagOpen _ attr <- lookAhead $ pSatisfy $ (~== TagOpen "case" [])
212 TagOpen _ attr <- lookAhead $ pSatisfy $ (~== TagOpen "case" [])
@@ -203,7 +214,7 @@ eCase = do
203 Just p -> Just <$> (pInTags "case" (skipMany pBlank *> p <* skipMany pBlank))
214 Just p -> Just <$> (pInTags "case" (skipMany pBlank *> p <* skipMany pBlank))
204 Nothing -> Nothing <$ manyTill pAnyTag (pSatisfy (~== TagClose "case"))
215 Nothing -> Nothing <$ manyTill pAnyTag (pSatisfy (~== TagClose "case"))
205
216
206−eFootnote :: TagParser ()
217+eFootnote :: PandocMonad m => TagParser m ()
207eFootnote = try $ do
218eFootnote = try $ do
208 let notes = ["footnote", "rearnote"]
219 let notes = ["footnote", "rearnote"]
209 guardEnabled Ext_epub_html_exts
220 guardEnabled Ext_epub_html_exts
@@ -213,10 +224,10 @@ eFootnote = try $ do
213 content <- pInTags tag block
224 content <- pInTags tag block
214 addNote ident content
225 addNote ident content
215
226
216−addNote :: String -> Blocks -> TagParser ()
227+addNote :: PandocMonad m => String -> Blocks -> TagParser m ()
217addNote uid cont = updateState (\s -> s {noteTable = (uid, cont) : (noteTable s)})
228addNote uid cont = updateState (\s -> s {noteTable = (uid, cont) : (noteTable s)})
218
229
219−eNoteref :: TagParser Inlines
230+eNoteref :: PandocMonad m => TagParser m Inlines
220eNoteref = try $ do
231eNoteref = try $ do
221 guardEnabled Ext_epub_html_exts
232 guardEnabled Ext_epub_html_exts
222 TagOpen tag attr <- lookAhead $ pAnyTag
233 TagOpen tag attr <- lookAhead $ pAnyTag
@@ -227,17 +238,17 @@ eNoteref = try $ do
227 return $ B.rawInline "noteref" ident
238 return $ B.rawInline "noteref" ident
228
239
229-- Strip TOC if there is one, better to generate again
240-- Strip TOC if there is one, better to generate again
230−eTOC :: TagParser ()
241+eTOC :: PandocMonad m => TagParser m ()
231eTOC = try $ do
242eTOC = try $ do
232 guardEnabled Ext_epub_html_exts
243 guardEnabled Ext_epub_html_exts
233 (TagOpen tag attr) <- lookAhead $ pAnyTag
244 (TagOpen tag attr) <- lookAhead $ pAnyTag
234 guard (maybe False (== "toc") (lookup "type" attr))
245 guard (maybe False (== "toc") (lookup "type" attr))
235 void (pInTags tag block)
246 void (pInTags tag block)
236
247
237−pList :: TagParser Blocks
248+pList :: PandocMonad m => TagParser m Blocks
238pList = pBulletList <|> pOrderedList <|> pDefinitionList
249pList = pBulletList <|> pOrderedList <|> pDefinitionList
239
250
240−pBulletList :: TagParser Blocks
251+pBulletList :: PandocMonad m => TagParser m Blocks
241pBulletList = try $ do
252pBulletList = try $ do
242 pSatisfy (~== TagOpen "ul" [])
253 pSatisfy (~== TagOpen "ul" [])
243 let nonItem = pSatisfy (\t ->
254 let nonItem = pSatisfy (\t ->
@@ -249,7 +260,7 @@ pBulletList = try $ do
249 items <- manyTill (pListItem nonItem) (pCloses "ul")
260 items <- manyTill (pListItem nonItem) (pCloses "ul")
250 return $ B.bulletList $ map (fixPlains True) items
261 return $ B.bulletList $ map (fixPlains True) items
251
262
252−pListItem :: TagParser a -> TagParser Blocks
263+pListItem :: PandocMonad m => TagParser m a -> TagParser m Blocks
253pListItem nonItem = do
264pListItem nonItem = do
254 TagOpen _ attr <- lookAhead $ pSatisfy (~== TagOpen "li" [])
265 TagOpen _ attr <- lookAhead $ pSatisfy (~== TagOpen "li" [])
255 let liDiv = maybe mempty (\x -> B.divWith (x, [], []) mempty) (lookup "id" attr)
266 let liDiv = maybe mempty (\x -> B.divWith (x, [], []) mempty) (lookup "id" attr)
@@ -271,7 +282,7 @@ parseTypeAttr "A" = UpperAlpha
271parseTypeAttr "1" = Decimal
282parseTypeAttr "1" = Decimal
272parseTypeAttr _ = DefaultStyle
283parseTypeAttr _ = DefaultStyle
273
284
274−pOrderedList :: TagParser Blocks
285+pOrderedList :: PandocMonad m => TagParser m Blocks
275pOrderedList = try $ do
286pOrderedList = try $ do
276 TagOpen _ attribs <- pSatisfy (~== TagOpen "ol" [])
287 TagOpen _ attribs <- pSatisfy (~== TagOpen "ol" [])
277 let (start, style) = (sta', sty')
288 let (start, style) = (sta', sty')
@@ -302,13 +313,13 @@ pOrderedList = try $ do
302 items <- manyTill (pListItem nonItem) (pCloses "ol")
313 items <- manyTill (pListItem nonItem) (pCloses "ol")
303 return $ B.orderedListWith (start, style, DefaultDelim) $ map (fixPlains True) items
314 return $ B.orderedListWith (start, style, DefaultDelim) $ map (fixPlains True) items
304
315
305−pDefinitionList :: TagParser Blocks
316+pDefinitionList :: PandocMonad m => TagParser m Blocks
306pDefinitionList = try $ do
317pDefinitionList = try $ do
307 pSatisfy (~== TagOpen "dl" [])
318 pSatisfy (~== TagOpen "dl" [])
308 items <- manyTill pDefListItem (pCloses "dl")
319 items <- manyTill pDefListItem (pCloses "dl")
309 return $ B.definitionList items
320 return $ B.definitionList items
310
321
311−pDefListItem :: TagParser (Inlines, [Blocks])
322+pDefListItem :: PandocMonad m => TagParser m (Inlines, [Blocks])
312pDefListItem = try $ do
323pDefListItem = try $ do
313 let nonItem = pSatisfy (\t -> not (t ~== TagOpen "dt" []) &&
324 let nonItem = pSatisfy (\t -> not (t ~== TagOpen "dt" []) &&
314 not (t ~== TagOpen "dd" []) && not (t ~== TagClose "dl"))
325 not (t ~== TagOpen "dd" []) && not (t ~== TagClose "dl"))
@@ -334,7 +345,7 @@ fixPlains inList bs = if any isParaish bs'
334 plainToPara x = x
345 plainToPara x = x
335 bs' = B.toList bs
346 bs' = B.toList bs
336
347
337−pRawTag :: TagParser String
348+pRawTag :: PandocMonad m => TagParser m String
338pRawTag = do
349pRawTag = do
339 tag <- pAnyTag
350 tag <- pAnyTag
340 let ignorable x = x `elem` ["html","head","body","!DOCTYPE","?xml"]
351 let ignorable x = x `elem` ["html","head","body","!DOCTYPE","?xml"]
@@ -342,7 +353,7 @@ pRawTag = do
342 then return []
353 then return []
343 else return $ renderTags' [tag]
354 else return $ renderTags' [tag]
344
355
345−pDiv :: TagParser Blocks
356+pDiv :: PandocMonad m => TagParser m Blocks
346pDiv = try $ do
357pDiv = try $ do
347 guardEnabled Ext_native_divs
358 guardEnabled Ext_native_divs
348 let isDivLike "div" = True
359 let isDivLike "div" = True
@@ -356,7 +367,7 @@ pDiv = try $ do
356 else classes
367 else classes
357 return $ B.divWith (ident, classes', kvs) contents
368 return $ B.divWith (ident, classes', kvs) contents
358
369
359−pRawHtmlBlock :: TagParser Blocks
370+pRawHtmlBlock :: PandocMonad m => TagParser m Blocks
360pRawHtmlBlock = do
371pRawHtmlBlock = do
361 raw <- pHtmlBlock "script" <|> pHtmlBlock "style" <|> pRawTag
372 raw <- pHtmlBlock "script" <|> pHtmlBlock "style" <|> pRawTag
362 parseRaw <- getOption readerParseRaw
373 parseRaw <- getOption readerParseRaw
@@ -364,21 +375,21 @@ pRawHtmlBlock = do
364 then return $ B.rawBlock "html" raw
375 then return $ B.rawBlock "html" raw
365 else return mempty
376 else return mempty
366
377
367−pHtmlBlock :: String -> TagParser String
378+pHtmlBlock :: PandocMonad m => String -> TagParser m String
368pHtmlBlock t = try $ do
379pHtmlBlock t = try $ do
369 open <- pSatisfy (~== TagOpen t [])
380 open <- pSatisfy (~== TagOpen t [])
370 contents <- manyTill pAnyTag (pSatisfy (~== TagClose t))
381 contents <- manyTill pAnyTag (pSatisfy (~== TagClose t))
371 return $ renderTags' $ [open] ++ contents ++ [TagClose t]
382 return $ renderTags' $ [open] ++ contents ++ [TagClose t]
372
383
373-- Sets chapter context
384-- Sets chapter context
374−eSection :: TagParser Blocks
385+eSection :: PandocMonad m => TagParser m Blocks
375eSection = try $ do
386eSection = try $ do
376 let matchChapter as = maybe False (isInfixOf "chapter") (lookup "type" as)
387 let matchChapter as = maybe False (isInfixOf "chapter") (lookup "type" as)
377 let sectTag = tagOpen (`elem` sectioningContent) matchChapter
388 let sectTag = tagOpen (`elem` sectioningContent) matchChapter
378 TagOpen tag _ <- lookAhead $ pSatisfy sectTag
389 TagOpen tag _ <- lookAhead $ pSatisfy sectTag
379 setInChapter (pInTags tag block)
390 setInChapter (pInTags tag block)
380
391
381−headerLevel :: String -> TagParser Int
392+headerLevel :: PandocMonad m => String -> TagParser m Int
382headerLevel tagtype = do
393headerLevel tagtype = do
383 let level = read (drop 1 tagtype)
394 let level = read (drop 1 tagtype)
384 (try $ do
395 (try $ do
@@ -388,7 +399,7 @@ headerLevel tagtype = do
388 <|>
399 <|>
389 return level
400 return level
390
401
391−eTitlePage :: TagParser ()
402+eTitlePage :: PandocMonad m => TagParser m ()
392eTitlePage = try $ do
403eTitlePage = try $ do
393 let isTitlePage as = maybe False (isInfixOf "titlepage") (lookup "type" as)
404 let isTitlePage as = maybe False (isInfixOf "titlepage") (lookup "type" as)
394 let groupTag = tagOpen (\x -> x `elem` groupingContent || x == "section")
405 let groupTag = tagOpen (\x -> x `elem` groupingContent || x == "section")
@@ -396,7 +407,7 @@ eTitlePage = try $ do
396 TagOpen tag _ <- lookAhead $ pSatisfy groupTag
407 TagOpen tag _ <- lookAhead $ pSatisfy groupTag
397 () <$ pInTags tag block
408 () <$ pInTags tag block
398
409
399−pHeader :: TagParser Blocks
410+pHeader :: PandocMonad m => TagParser m Blocks
400pHeader = try $ do
411pHeader = try $ do
401 TagOpen tagtype attr <- pSatisfy $
412 TagOpen tagtype attr <- pSatisfy $
402 tagOpen (`elem` ["h1","h2","h3","h4","h5","h6"])
413 tagOpen (`elem` ["h1","h2","h3","h4","h5","h6"])
@@ -412,12 +423,12 @@ pHeader = try $ do
412 then mempty -- skip a representation of the title in the body
423 then mempty -- skip a representation of the title in the body
413 else B.headerWith attr' level contents
424 else B.headerWith attr' level contents
414
425
415−pHrule :: TagParser Blocks
426+pHrule :: PandocMonad m => TagParser m Blocks
416pHrule = do
427pHrule = do
417 pSelfClosing (=="hr") (const True)
428 pSelfClosing (=="hr") (const True)
418 return B.horizontalRule
429 return B.horizontalRule
419
430
420−pTable :: TagParser Blocks
431+pTable :: PandocMonad m => TagParser m Blocks
421pTable = try $ do
432pTable = try $ do
422 TagOpen _ _ <- pSatisfy (~== TagOpen "table" [])
433 TagOpen _ _ <- pSatisfy (~== TagOpen "table" [])
423 skipMany pBlank
434 skipMany pBlank
@@ -456,7 +467,7 @@ pTable = try $ do
456 else widths'
467 else widths'
457 return $ B.table caption (zip aligns widths) head' rows
468 return $ B.table caption (zip aligns widths) head' rows
458
469
459−pCol :: TagParser Double
470+pCol :: PandocMonad m => TagParser m Double
460pCol = try $ do
471pCol = try $ do
461 TagOpen _ attribs <- pSatisfy (~== TagOpen "col" [])
472 TagOpen _ attribs <- pSatisfy (~== TagOpen "col" [])
462 skipMany pBlank
473 skipMany pBlank
@@ -472,7 +483,7 @@ pCol = try $ do
472 fromMaybe 0.0 $ safeRead ('0':'.':init x)
483 fromMaybe 0.0 $ safeRead ('0':'.':init x)
473 _ -> 0.0
484 _ -> 0.0
474
485
475−pColgroup :: TagParser [Double]
486+pColgroup :: PandocMonad m => TagParser m [Double]
476pColgroup = try $ do
487pColgroup = try $ do
477 pSatisfy (~== TagOpen "colgroup" [])
488 pSatisfy (~== TagOpen "colgroup" [])
478 skipMany pBlank
489 skipMany pBlank
@@ -485,31 +496,31 @@ noColOrRowSpans t = isNullOrOne "colspan" && isNullOrOne "rowspan"
485 "1" -> True
496 "1" -> True
486 _ -> False
497 _ -> False
487
498
488−pCell :: String -> TagParser [Blocks]
499+pCell :: PandocMonad m => String -> TagParser m [Blocks]
489pCell celltype = try $ do
500pCell celltype = try $ do
490 skipMany pBlank
501 skipMany pBlank
491 res <- pInTags' celltype noColOrRowSpans block
502 res <- pInTags' celltype noColOrRowSpans block
492 skipMany pBlank
503 skipMany pBlank
493 return [res]
504 return [res]
494
505
495−pBlockQuote :: TagParser Blocks
506+pBlockQuote :: PandocMonad m => TagParser m Blocks
496pBlockQuote = do
507pBlockQuote = do
497 contents <- pInTags "blockquote" block
508 contents <- pInTags "blockquote" block
498 return $ B.blockQuote $ fixPlains False contents
509 return $ B.blockQuote $ fixPlains False contents
499
510
500−pPlain :: TagParser Blocks
511+pPlain :: PandocMonad m => TagParser m Blocks
501pPlain = do
512pPlain = do
502 contents <- setInPlain $ trimInlines . mconcat <$> many1 inline
513 contents <- setInPlain $ trimInlines . mconcat <$> many1 inline
503 if B.isNull contents
514 if B.isNull contents
504 then return mempty
515 then return mempty
505 else return $ B.plain contents
516 else return $ B.plain contents
506
517
507−pPara :: TagParser Blocks
518+pPara :: PandocMonad m => TagParser m Blocks
508pPara = do
519pPara = do
509 contents <- trimInlines <$> pInTags "p" inline
520 contents <- trimInlines <$> pInTags "p" inline
510 return $ B.para contents
521 return $ B.para contents
511
522
512−pCodeBlock :: TagParser Blocks
523+pCodeBlock :: PandocMonad m => TagParser m Blocks
513pCodeBlock = try $ do
524pCodeBlock = try $ do
514 TagOpen _ attr <- pSatisfy (~== TagOpen "pre" [])
525 TagOpen _ attr <- pSatisfy (~== TagOpen "pre" [])
515 contents <- manyTill pAnyTag (pCloses "pre" <|> eof)
526 contents <- manyTill pAnyTag (pCloses "pre" <|> eof)
@@ -529,7 +540,7 @@ tagToString (TagText s) = s
529tagToString (TagOpen "br" _) = "\n"
540tagToString (TagOpen "br" _) = "\n"
530tagToString _ = ""
541tagToString _ = ""
531
542
532−inline :: TagParser Inlines
543+inline :: PandocMonad m => TagParser m Inlines
533inline = choice
544inline = choice
534 [ eNoteref
545 [ eNoteref
535 , eSwitch id inline
546 , eSwitch id inline
@@ -549,30 +560,31 @@ inline = choice
549 , pRawHtmlInline
560 , pRawHtmlInline
550 ]
561 ]
551
562
552−pLocation :: TagParser ()
563+pLocation :: PandocMonad m => TagParser m ()
553pLocation = do
564pLocation = do
554 (TagPosition r c) <- pSat isTagPosition
565 (TagPosition r c) <- pSat isTagPosition
555 setPosition $ newPos "input" r c
566 setPosition $ newPos "input" r c
556
567
557−pSat :: (Tag String -> Bool) -> TagParser (Tag String)
568+pSat :: PandocMonad m => (Tag String -> Bool) -> TagParser m (Tag String)
558pSat f = do
569pSat f = do
559 pos <- getPosition
570 pos <- getPosition
560 token show (const pos) (\x -> if f x then Just x else Nothing)
571 token show (const pos) (\x -> if f x then Just x else Nothing)
561
572
562−pSatisfy :: (Tag String -> Bool) -> TagParser (Tag String)
573+pSatisfy :: PandocMonad m => (Tag String -> Bool) -> TagParser m (Tag String)
563pSatisfy f = try $ optional pLocation >> pSat f
574pSatisfy f = try $ optional pLocation >> pSat f
564
575
565−pAnyTag :: TagParser (Tag String)
576+pAnyTag :: PandocMonad m => TagParser m (Tag String)
566pAnyTag = pSatisfy (const True)
577pAnyTag = pSatisfy (const True)
567
578
579+pSelfClosing :: PandocMonad m
568−pSelfClosing :: (String -> Bool) -> ([Attribute String] -> Bool)
580+ => (String -> Bool) -> ([Attribute String] -> Bool)
569− -> TagParser (Tag String)
581+ -> TagParser m (Tag String)
570pSelfClosing f g = do
582pSelfClosing f g = do
571 open <- pSatisfy (tagOpen f g)
583 open <- pSatisfy (tagOpen f g)
572 optional $ pSatisfy (tagClose f)
584 optional $ pSatisfy (tagClose f)
573 return open
585 return open
574
586
575−pQ :: TagParser Inlines
587+pQ :: PandocMonad m => TagParser m Inlines
576pQ = do
588pQ = do
577 context <- asks quoteContext
589 context <- asks quoteContext
578 let quoteType = case context of
590 let quoteType = case context of
@@ -587,19 +599,19 @@ pQ = do
587 withQuoteContext innerQuoteContext $
599 withQuoteContext innerQuoteContext $
588 pInlinesInTags "q" constructor
600 pInlinesInTags "q" constructor
589
601
590−pEmph :: TagParser Inlines
602+pEmph :: PandocMonad m => TagParser m Inlines
591pEmph = pInlinesInTags "em" B.emph <|> pInlinesInTags "i" B.emph
603pEmph = pInlinesInTags "em" B.emph <|> pInlinesInTags "i" B.emph
592
604
593−pStrong :: TagParser Inlines
605+pStrong :: PandocMonad m => TagParser m Inlines
594pStrong = pInlinesInTags "strong" B.strong <|> pInlinesInTags "b" B.strong
606pStrong = pInlinesInTags "strong" B.strong <|> pInlinesInTags "b" B.strong
595
607
596−pSuperscript :: TagParser Inlines
608+pSuperscript :: PandocMonad m => TagParser m Inlines
597pSuperscript = pInlinesInTags "sup" B.superscript
609pSuperscript = pInlinesInTags "sup" B.superscript
598
610
599−pSubscript :: TagParser Inlines
611+pSubscript :: PandocMonad m => TagParser m Inlines
600pSubscript = pInlinesInTags "sub" B.subscript
612pSubscript = pInlinesInTags "sub" B.subscript
601
613
602−pStrikeout :: TagParser Inlines
614+pStrikeout :: PandocMonad m => TagParser m Inlines
603pStrikeout = do
615pStrikeout = do
604 pInlinesInTags "s" B.strikeout <|>
616 pInlinesInTags "s" B.strikeout <|>
605 pInlinesInTags "strike" B.strikeout <|>
617 pInlinesInTags "strike" B.strikeout <|>
@@ -608,7 +620,7 @@ pStrikeout = do
608 contents <- mconcat <$> manyTill inline (pCloses "span")
620 contents <- mconcat <$> manyTill inline (pCloses "span")
609 return $ B.strikeout contents)
621 return $ B.strikeout contents)
610
622
611−pLineBreak :: TagParser Inlines
623+pLineBreak :: PandocMonad m => TagParser m Inlines
612pLineBreak = do
624pLineBreak = do
613 pSelfClosing (=="br") (const True)
625 pSelfClosing (=="br") (const True)
614 return B.linebreak
626 return B.linebreak
@@ -619,7 +631,7 @@ maybeFromAttrib :: String -> Tag String -> Maybe String
619maybeFromAttrib name (TagOpen _ attrs) = lookup name attrs
631maybeFromAttrib name (TagOpen _ attrs) = lookup name attrs
620maybeFromAttrib _ _ = Nothing
632maybeFromAttrib _ _ = Nothing
621
633
622−pLink :: TagParser Inlines
634+pLink :: PandocMonad m => TagParser m Inlines
623pLink = try $ do
635pLink = try $ do
624 tag <- pSatisfy $ tagOpenLit "a" (const True)
636 tag <- pSatisfy $ tagOpenLit "a" (const True)
625 let title = fromAttrib "title" tag
637 let title = fromAttrib "title" tag
@@ -639,7 +651,7 @@ pLink = try $ do
639 _ -> url'
651 _ -> url'
640 return $ B.linkWith (uid, cls, []) (escapeURI url) title lab
652 return $ B.linkWith (uid, cls, []) (escapeURI url) title lab
641
653
642−pImage :: TagParser Inlines
654+pImage :: PandocMonad m => TagParser m Inlines
643pImage = do
655pImage = do
644 tag <- pSelfClosing (=="img") (isJust . lookup "src")
656 tag <- pSelfClosing (=="img") (isJust . lookup "src")
645 mbBaseHref <- baseHref <$> getState
657 mbBaseHref <- baseHref <$> getState
@@ -657,13 +669,13 @@ pImage = do
657 let kvs = concat $ map getAtt ["width", "height", "sizes", "srcset"]
669 let kvs = concat $ map getAtt ["width", "height", "sizes", "srcset"]
658 return $ B.imageWith (uid, cls, kvs) (escapeURI url) title (B.text alt)
670 return $ B.imageWith (uid, cls, kvs) (escapeURI url) title (B.text alt)
659
671
660−pCode :: TagParser Inlines
672+pCode :: PandocMonad m => TagParser m Inlines
661pCode = try $ do
673pCode = try $ do
662 (TagOpen open attr) <- pSatisfy $ tagOpen (`elem` ["code","tt"]) (const True)
674 (TagOpen open attr) <- pSatisfy $ tagOpen (`elem` ["code","tt"]) (const True)
663 result <- manyTill pAnyTag (pCloses open)
675 result <- manyTill pAnyTag (pCloses open)
664 return $ B.codeWith (mkAttr attr) $ intercalate " " $ lines $ innerText result
676 return $ B.codeWith (mkAttr attr) $ intercalate " " $ lines $ innerText result
665
677
666−pSpan :: TagParser Inlines
678+pSpan :: PandocMonad m => TagParser m Inlines
667pSpan = try $ do
679pSpan = try $ do
668 guardEnabled Ext_native_spans
680 guardEnabled Ext_native_spans
669 TagOpen _ attr <- lookAhead $ pSatisfy $ tagOpen (=="span") (const True)
681 TagOpen _ attr <- lookAhead $ pSatisfy $ tagOpen (=="span") (const True)
@@ -674,7 +686,7 @@ pSpan = try $ do
674 let tag = if isSmallCaps then B.smallcaps else B.spanWith (mkAttr attr)
686 let tag = if isSmallCaps then B.smallcaps else B.spanWith (mkAttr attr)
675 return $ tag contents
687 return $ tag contents
676
688
677−pRawHtmlInline :: TagParser Inlines
689+pRawHtmlInline :: PandocMonad m => TagParser m Inlines
678pRawHtmlInline = do
690pRawHtmlInline = do
679 inplain <- asks inPlain
691 inplain <- asks inPlain
680 result <- pSatisfy (tagComment (const True))
692 result <- pSatisfy (tagComment (const True))
@@ -689,7 +701,7 @@ pRawHtmlInline = do
689mathMLToTeXMath :: String -> Either String String
701mathMLToTeXMath :: String -> Either String String
690mathMLToTeXMath s = writeTeX <$> readMathML s
702mathMLToTeXMath s = writeTeX <$> readMathML s
691
703
692−pMath :: Bool -> TagParser Inlines
704+pMath :: PandocMonad m => Bool -> TagParser m Inlines
693pMath inCase = try $ do
705pMath inCase = try $ do
694 open@(TagOpen _ attr) <- pSatisfy $ tagOpen (=="math") (const True)
706 open@(TagOpen _ attr) <- pSatisfy $ tagOpen (=="math") (const True)
695 -- we'll assume math tags are MathML unless specially marked
707 -- we'll assume math tags are MathML unless specially marked
@@ -705,22 +717,25 @@ pMath inCase = try $ do
705 Just "block" -> B.displayMath x
717 Just "block" -> B.displayMath x
706 _ -> B.math x
718 _ -> B.math x
707
719
708−pInlinesInTags :: String -> (Inlines -> Inlines)
720+pInlinesInTags :: PandocMonad m => String -> (Inlines -> Inlines)
709− -> TagParser Inlines
721+ -> TagParser m Inlines
710pInlinesInTags tagtype f = extractSpaces f <$> pInTags tagtype inline
722pInlinesInTags tagtype f = extractSpaces f <$> pInTags tagtype inline
711
723
712−pInTags :: (Monoid a) => String -> TagParser a -> TagParser a
724+pInTags :: (PandocMonad m, Monoid a) => String -> TagParser m a -> TagParser m a
713pInTags tagtype parser = pInTags' tagtype (const True) parser
725pInTags tagtype parser = pInTags' tagtype (const True) parser
714
726
727+pInTags' :: (PandocMonad m, Monoid a)
728+ => String
715−pInTags' :: (Monoid a) => String -> (Tag String -> Bool) -> TagParser a
729+ -> (Tag String -> Bool)
730+ -> TagParser m a
716− -> TagParser a
731+ -> TagParser m a
717pInTags' tagtype tagtest parser = try $ do
732pInTags' tagtype tagtest parser = try $ do
718 pSatisfy (\t -> t ~== TagOpen tagtype [] && tagtest t)
733 pSatisfy (\t -> t ~== TagOpen tagtype [] && tagtest t)
719 mconcat <$> manyTill parser (pCloses tagtype <|> eof)
734 mconcat <$> manyTill parser (pCloses tagtype <|> eof)
720
735
721-- parses p, preceeded by an optional opening tag
736-- parses p, preceeded by an optional opening tag
722-- and followed by an optional closing tags
737-- and followed by an optional closing tags
723−pOptInTag :: String -> TagParser a -> TagParser a
738+pOptInTag :: PandocMonad m => String -> TagParser m a -> TagParser m a
724pOptInTag tagtype p = try $ do
739pOptInTag tagtype p = try $ do
725 skipMany pBlank
740 skipMany pBlank
726 optional $ pSatisfy (~== TagOpen tagtype [])
741 optional $ pSatisfy (~== TagOpen tagtype [])
@@ -731,7 +746,7 @@ pOptInTag tagtype p = try $ do
731 skipMany pBlank
746 skipMany pBlank
732 return x
747 return x
733
748
734−pCloses :: String -> TagParser ()
749+pCloses :: PandocMonad m => String -> TagParser m ()
735pCloses tagtype = try $ do
750pCloses tagtype = try $ do
736 t <- lookAhead $ pSatisfy $ \tag -> isTagClose tag || isTagOpen tag
751 t <- lookAhead $ pSatisfy $ \tag -> isTagClose tag || isTagOpen tag
737 case t of
752 case t of
@@ -744,23 +759,25 @@ pCloses tagtype = try $ do
744 (TagClose "table") | tagtype == "tr" -> return ()
759 (TagClose "table") | tagtype == "tr" -> return ()
745 _ -> mzero
760 _ -> mzero
746
761
747−pTagText :: TagParser Inlines
762+pTagText :: PandocMonad m => TagParser m Inlines
748pTagText = try $ do
763pTagText = try $ do
749 (TagText str) <- pSatisfy isTagText
764 (TagText str) <- pSatisfy isTagText
750 st <- getState
765 st <- getState
751 qu <- ask
766 qu <- ask
767+ parsed <- lift $ lift $
752− case flip runReader qu $ runParserT (many pTagContents) st "text" str of
768+ flip runReaderT qu $ runParserT (many pTagContents) st "text" str
769+ case parsed of
753− Left _ -> fail $ "Could not parse `" ++ str ++ "'"
770+ Left _ -> throwError $ PandocParseError $ "Could not parse `" ++ str ++ "'"
754 Right result -> return $ mconcat result
771 Right result -> return $ mconcat result
755
772
756−pBlank :: TagParser ()
773+pBlank :: PandocMonad m => TagParser m ()
757pBlank = try $ do
774pBlank = try $ do
758 (TagText str) <- pSatisfy isTagText
775 (TagText str) <- pSatisfy isTagText
759 guard $ all isSpace str
776 guard $ all isSpace str
760
777
761−type InlinesParser = HTMLParser String
778+type InlinesParser m = HTMLParser m String
762
779
763−pTagContents :: InlinesParser Inlines
780+pTagContents :: PandocMonad m => InlinesParser m Inlines
764pTagContents =
781pTagContents =
765 B.displayMath <$> mathDisplay
782 B.displayMath <$> mathDisplay
766 <|> B.math <$> mathInline
783 <|> B.math <$> mathInline
@@ -770,7 +787,7 @@ pTagContents =
770 <|> pSymbol
787 <|> pSymbol
771 <|> pBad
788 <|> pBad
772
789
773−pStr :: InlinesParser Inlines
790+pStr :: PandocMonad m => InlinesParser m Inlines
774pStr = do
791pStr = do
775 result <- many1 $ satisfy $ \c ->
792 result <- many1 $ satisfy $ \c ->
776 not (isSpace c) && not (isSpecial c) && not (isBad c)
793 not (isSpace c) && not (isSpecial c) && not (isBad c)
@@ -789,13 +806,13 @@ isSpecial '\8220' = True
789isSpecial '\8221' = True
806isSpecial '\8221' = True
790isSpecial _ = False
807isSpecial _ = False
791
808
792−pSymbol :: InlinesParser Inlines
809+pSymbol :: PandocMonad m => InlinesParser m Inlines
793pSymbol = satisfy isSpecial >>= return . B.str . (:[])
810pSymbol = satisfy isSpecial >>= return . B.str . (:[])
794
811
795isBad :: Char -> Bool
812isBad :: Char -> Bool
796isBad c = c >= '\128' && c <= '\159' -- not allowed in HTML
813isBad c = c >= '\128' && c <= '\159' -- not allowed in HTML
797
814
798−pBad :: InlinesParser Inlines
815+pBad :: PandocMonad m => InlinesParser m Inlines
799pBad = do
816pBad = do
800 c <- satisfy isBad
817 c <- satisfy isBad
801 let c' = case c of
818 let c' = case c of
@@ -829,7 +846,7 @@ pBad = do
829 _ -> '?'
846 _ -> '?'
830 return $ B.str [c']
847 return $ B.str [c']
831
848
832−pSpace :: InlinesParser Inlines
849+pSpace :: PandocMonad m => InlinesParser m Inlines
833pSpace = many1 (satisfy isSpace) >>= \xs ->
850pSpace = many1 (satisfy isSpace) >>= \xs ->
834 if '\n' `elem` xs
851 if '\n' `elem` xs
835 then return B.softbreak
852 then return B.softbreak
@@ -1070,7 +1087,7 @@ instance HasHeaderMap HTMLState where
1070
1087
1071-- This signature should be more general
1088-- This signature should be more general
1072-- MonadReader HTMLLocal m => HasQuoteContext st m
1089-- MonadReader HTMLLocal m => HasQuoteContext st m
1073−instance HasQuoteContext st (Reader HTMLLocal) where
1090+instance PandocMonad m => HasQuoteContext st (ReaderT HTMLLocal m) where
1074 getQuoteContext = asks quoteContext
1091 getQuoteContext = asks quoteContext
1075 withQuoteContext q = local (\s -> s{quoteContext = q})
1092 withQuoteContext q = local (\s -> s{quoteContext = q})
1076
1093
src/Text/Pandoc/Readers/Haddock.hs+14−5
@@ -25,14 +25,23 @@ import Text.Pandoc.Options
25import Documentation.Haddock.Parser
25import Documentation.Haddock.Parser
26import Documentation.Haddock.Types
26import Documentation.Haddock.Types
27import Debug.Trace (trace)
27import Debug.Trace (trace)
28+import Control.Monad.Except (throwError)
29+import Text.Pandoc.Class (PandocMonad, PandocExecutionError(..))
28
30
29−import Text.Pandoc.Error
30
31
31-- | Parse Haddock markup and return a 'Pandoc' document.
32-- | Parse Haddock markup and return a 'Pandoc' document.
33+readHaddock :: PandocMonad m
34+ => ReaderOptions
35+ -> String
36+ -> m Pandoc
37+readHaddock opts s = case readHaddockEither opts s of
38+ Right result -> return result
39+ Left e -> throwError e
40+
32−readHaddock :: ReaderOptions -- ^ Reader options
41+readHaddockEither :: ReaderOptions -- ^ Reader options
33− -> String -- ^ String to parse
42+ -> String -- ^ String to parse
34− -> Either PandocError Pandoc
43+ -> Either PandocExecutionError Pandoc
35−readHaddock opts =
44+readHaddockEither opts =
36#if MIN_VERSION_haddock_library(1,2,0)
45#if MIN_VERSION_haddock_library(1,2,0)
37 Right . B.doc . docHToBlocks . trace' . _doc . parseParas
46 Right . B.doc . docHToBlocks . trace' . _doc . parseParas
38#else
47#else
src/Text/Pandoc/Readers/LaTeX.hs+105−98
@@ -56,14 +56,21 @@ import qualified Control.Exception as E
56import Text.Pandoc.Highlighting (fromListingsLanguage)
56import Text.Pandoc.Highlighting (fromListingsLanguage)
57import Text.Pandoc.ImageSize (numUnit, showFl)
57import Text.Pandoc.ImageSize (numUnit, showFl)
58import Text.Pandoc.Error
58import Text.Pandoc.Error
59+import Control.Monad.Except (throwError)
60+import Text.Pandoc.Class (PandocMonad, PandocExecutionError(..), PandocPure)
59
61
60-- | Parse LaTeX from string and return 'Pandoc' document.
62-- | Parse LaTeX from string and return 'Pandoc' document.
63+readLaTeX :: PandocMonad m
61−readLaTeX :: ReaderOptions -- ^ Reader options
64+ => ReaderOptions -- ^ Reader options
62 -> String -- ^ String to parse (assumes @'\n'@ line endings)
65 -> String -- ^ String to parse (assumes @'\n'@ line endings)
63− -> Either PandocError Pandoc
66+ -> m Pandoc
67+readLaTeX opts ltx = do
64−readLaTeX opts = readWith parseLaTeX def{ stateOptions = opts }
68+ parsed <- readWithM parseLaTeX def{ stateOptions = opts } ltx
65−
69+ case parsed of
70+ Right result -> return result
71+ Left _ -> throwError $ PandocParseError "parsing error"
72+
66−parseLaTeX :: LP Pandoc
73+parseLaTeX :: PandocMonad m => LP m Pandoc
67parseLaTeX = do
74parseLaTeX = do
68 bs <- blocks
75 bs <- blocks
69 eof
76 eof
@@ -72,9 +79,9 @@ parseLaTeX = do
72 let (Pandoc _ bs') = doc bs
79 let (Pandoc _ bs') = doc bs
73 return $ Pandoc meta bs'
80 return $ Pandoc meta bs'
74
81
75−type LP = Parser String ParserState
82+type LP m = ParserT String ParserState m
76
83
77−anyControlSeq :: LP String
84+anyControlSeq :: PandocMonad m => LP m String
78anyControlSeq = do
85anyControlSeq = do
79 char '\\'
86 char '\\'
80 next <- option '\n' anyChar
87 next <- option '\n' anyChar
@@ -83,7 +90,7 @@ anyControlSeq = do
83 c | isLetter c -> (c:) <$> (many letter <* optional sp)
90 c | isLetter c -> (c:) <$> (many letter <* optional sp)
84 | otherwise -> return [c]
91 | otherwise -> return [c]
85
92
86−controlSeq :: String -> LP String
93+controlSeq :: PandocMonad m => String -> LP m String
87controlSeq name = try $ do
94controlSeq name = try $ do
88 char '\\'
95 char '\\'
89 case name of
96 case name of
@@ -92,26 +99,26 @@ controlSeq name = try $ do
92 cs -> string cs <* notFollowedBy letter <* optional sp
99 cs -> string cs <* notFollowedBy letter <* optional sp
93 return name
100 return name
94
101
95−dimenarg :: LP String
102+dimenarg :: PandocMonad m => LP m String
96dimenarg = try $ do
103dimenarg = try $ do
97 ch <- option "" $ string "="
104 ch <- option "" $ string "="
98 num <- many1 digit
105 num <- many1 digit
99 dim <- oneOfStrings ["pt","pc","in","bp","cm","mm","dd","cc","sp"]
106 dim <- oneOfStrings ["pt","pc","in","bp","cm","mm","dd","cc","sp"]
100 return $ ch ++ num ++ dim
107 return $ ch ++ num ++ dim
101
108
102−sp :: LP ()
109+sp :: PandocMonad m => LP m ()
103sp = whitespace <|> endline
110sp = whitespace <|> endline
104
111
105−whitespace :: LP ()
112+whitespace :: PandocMonad m => LP m ()
106whitespace = skipMany1 $ satisfy (\c -> c == ' ' || c == '\t')
113whitespace = skipMany1 $ satisfy (\c -> c == ' ' || c == '\t')
107
114
108−endline :: LP ()
115+endline :: PandocMonad m => LP m ()
109endline = try (newline >> lookAhead anyChar >> notFollowedBy blankline)
116endline = try (newline >> lookAhead anyChar >> notFollowedBy blankline)
110
117
111isLowerHex :: Char -> Bool
118isLowerHex :: Char -> Bool
112isLowerHex x = x >= '0' && x <= '9' || x >= 'a' && x <= 'f'
119isLowerHex x = x >= '0' && x <= '9' || x >= 'a' && x <= 'f'
113
120
114−tildeEscape :: LP Char
121+tildeEscape :: PandocMonad m => LP m Char
115tildeEscape = try $ do
122tildeEscape = try $ do
116 string "^^"
123 string "^^"
117 c <- satisfy (\x -> x >= '\0' && x <= '\128')
124 c <- satisfy (\x -> x >= '\0' && x <= '\128')
@@ -124,29 +131,29 @@ tildeEscape = try $ do
124 | otherwise -> return $ chr (x + 64)
131 | otherwise -> return $ chr (x + 64)
125 else return $ chr $ read ('0':'x':c:d)
132 else return $ chr $ read ('0':'x':c:d)
126
133
127−comment :: LP ()
134+comment :: PandocMonad m => LP m ()
128comment = do
135comment = do
129 char '%'
136 char '%'
130 skipMany (satisfy (/='\n'))
137 skipMany (satisfy (/='\n'))
131 optional newline
138 optional newline
132 return ()
139 return ()
133
140
134−bgroup :: LP ()
141+bgroup :: PandocMonad m => LP m ()
135bgroup = try $ do
142bgroup = try $ do
136 skipMany (spaceChar <|> try (newline <* notFollowedBy blankline))
143 skipMany (spaceChar <|> try (newline <* notFollowedBy blankline))
137 () <$ char '{'
144 () <$ char '{'
138 <|> () <$ controlSeq "bgroup"
145 <|> () <$ controlSeq "bgroup"
139 <|> () <$ controlSeq "begingroup"
146 <|> () <$ controlSeq "begingroup"
140
147
141−egroup :: LP ()
148+egroup :: PandocMonad m => LP m ()
142egroup = () <$ char '}'
149egroup = () <$ char '}'
143 <|> () <$ controlSeq "egroup"
150 <|> () <$ controlSeq "egroup"
144 <|> () <$ controlSeq "endgroup"
151 <|> () <$ controlSeq "endgroup"
145
152
146−grouped :: Monoid a => LP a -> LP a
153+grouped :: PandocMonad m => Monoid a => LP m a -> LP m a
147grouped parser = try $ bgroup *> (mconcat <$> manyTill parser egroup)
154grouped parser = try $ bgroup *> (mconcat <$> manyTill parser egroup)
148
155
149−braced :: LP String
156+braced :: PandocMonad m => LP m String
150braced = bgroup *> (concat <$> manyTill
157braced = bgroup *> (concat <$> manyTill
151 ( many1 (satisfy (\c -> c /= '\\' && c /= '}' && c /= '{'))
158 ( many1 (satisfy (\c -> c /= '\\' && c /= '}' && c /= '{'))
152 <|> try (string "\\}")
159 <|> try (string "\\}")
@@ -156,16 +163,16 @@ braced = bgroup *> (concat <$> manyTill
156 <|> count 1 anyChar
163 <|> count 1 anyChar
157 ) egroup)
164 ) egroup)
158
165
159−bracketed :: Monoid a => LP a -> LP a
166+bracketed :: PandocMonad m => Monoid a => LP m a -> LP m a
160bracketed parser = try $ char '[' *> (mconcat <$> manyTill parser (char ']'))
167bracketed parser = try $ char '[' *> (mconcat <$> manyTill parser (char ']'))
161
168
162−mathDisplay :: LP String -> LP Inlines
169+mathDisplay :: PandocMonad m => LP m String -> LP m Inlines
163mathDisplay p = displayMath <$> (try p >>= applyMacros' . trim)
170mathDisplay p = displayMath <$> (try p >>= applyMacros' . trim)
164
171
165−mathInline :: LP String -> LP Inlines
172+mathInline :: PandocMonad m => LP m String -> LP m Inlines
166mathInline p = math <$> (try p >>= applyMacros')
173mathInline p = math <$> (try p >>= applyMacros')
167
174
168−mathChars :: LP String
175+mathChars :: PandocMonad m => LP m String
169mathChars =
176mathChars =
170 concat <$> many (escapedChar
177 concat <$> many (escapedChar
171 <|> (snd <$> withRaw braced)
178 <|> (snd <$> withRaw braced)
@@ -179,7 +186,7 @@ mathChars =
179 isOrdChar '\\' = False
186 isOrdChar '\\' = False
180 isOrdChar _ = True
187 isOrdChar _ = True
181
188
182−quoted' :: (Inlines -> Inlines) -> LP String -> LP () -> LP Inlines
189+quoted' :: PandocMonad m => (Inlines -> Inlines) -> LP m String -> LP m () -> LP m Inlines
183quoted' f starter ender = do
190quoted' f starter ender = do
184 startchs <- starter
191 startchs <- starter
185 smart <- getOption readerSmart
192 smart <- getOption readerSmart
@@ -194,7 +201,7 @@ quoted' f starter ender = do
194 _ -> startchs)
201 _ -> startchs)
195 else lit startchs
202 else lit startchs
196
203
197−doubleQuote :: LP Inlines
204+doubleQuote :: PandocMonad m => LP m Inlines
198doubleQuote = do
205doubleQuote = do
199 quoted' doubleQuoted (try $ string "``") (void $ try $ string "''")
206 quoted' doubleQuoted (try $ string "``") (void $ try $ string "''")
200 <|> quoted' doubleQuoted (string "“") (void $ char '”')
207 <|> quoted' doubleQuoted (string "“") (void $ char '”')
@@ -202,7 +209,7 @@ doubleQuote = do
202 <|> quoted' doubleQuoted (try $ string "\"`") (void $ try $ string "\"'")
209 <|> quoted' doubleQuoted (try $ string "\"`") (void $ try $ string "\"'")
203 <|> quoted' doubleQuoted (string "\"") (void $ char '"')
210 <|> quoted' doubleQuoted (string "\"") (void $ char '"')
204
211
205−singleQuote :: LP Inlines
212+singleQuote :: PandocMonad m => LP m Inlines
206singleQuote = do
213singleQuote = do
207 smart <- getOption readerSmart
214 smart <- getOption readerSmart
208 if smart
215 if smart
@@ -210,7 +217,7 @@ singleQuote = do
210 <|> quoted' singleQuoted (string "‘") (try $ char '’' >> notFollowedBy letter)
217 <|> quoted' singleQuoted (string "‘") (try $ char '’' >> notFollowedBy letter)
211 else str <$> many1 (oneOf "`\'‘’")
218 else str <$> many1 (oneOf "`\'‘’")
212
219
213−inline :: LP Inlines
220+inline :: PandocMonad m => LP m Inlines
214inline = (mempty <$ comment)
221inline = (mempty <$ comment)
215 <|> (space <$ whitespace)
222 <|> (space <$ whitespace)
216 <|> (softbreak <$ endline)
223 <|> (softbreak <$ endline)
@@ -235,10 +242,10 @@ inline = (mempty <$ comment)
235 <|> (str . (:[]) <$> oneOf "#&~^'`\"[]") -- TODO print warning?
242 <|> (str . (:[]) <$> oneOf "#&~^'`\"[]") -- TODO print warning?
236 -- <|> (str <$> count 1 (satisfy (\c -> c /= '\\' && c /='\n' && c /='}' && c /='{'))) -- eat random leftover characters
243 -- <|> (str <$> count 1 (satisfy (\c -> c /= '\\' && c /='\n' && c /='}' && c /='{'))) -- eat random leftover characters
237
244
238−inlines :: LP Inlines
245+inlines :: PandocMonad m => LP m Inlines
239inlines = mconcat <$> many (notFollowedBy (char '}') *> inline)
246inlines = mconcat <$> many (notFollowedBy (char '}') *> inline)
240
247
241−inlineGroup :: LP Inlines
248+inlineGroup :: PandocMonad m => LP m Inlines
242inlineGroup = do
249inlineGroup = do
243 ils <- grouped inline
250 ils <- grouped inline
244 if isNull ils
251 if isNull ils
@@ -247,7 +254,7 @@ inlineGroup = do
247 -- we need the span so we can detitlecase bibtex entries;
254 -- we need the span so we can detitlecase bibtex entries;
248 -- we need to know when something is {C}apitalized
255 -- we need to know when something is {C}apitalized
249
256
250−block :: LP Blocks
257+block :: PandocMonad m => LP m Blocks
251block = (mempty <$ comment)
258block = (mempty <$ comment)
252 <|> (mempty <$ ((spaceChar <|> newline) *> spaces))
259 <|> (mempty <$ ((spaceChar <|> newline) *> spaces))
253 <|> environment
260 <|> environment
@@ -258,10 +265,10 @@ block = (mempty <$ comment)
258 <|> (mempty <$ char '&') -- loose & in table environment
265 <|> (mempty <$ char '&') -- loose & in table environment
259
266
260
267
261−blocks :: LP Blocks
268+blocks :: PandocMonad m => LP m Blocks
262blocks = mconcat <$> many block
269blocks = mconcat <$> many block
263
270
264−getRawCommand :: String -> LP String
271+getRawCommand :: PandocMonad m => String -> LP m String
265getRawCommand name' = do
272getRawCommand name' = do
266 rawargs <- withRaw (many (try (optional sp *> opt)) *>
273 rawargs <- withRaw (many (try (optional sp *> opt)) *>
267 option "" (try (optional sp *> dimenarg)) *>
274 option "" (try (optional sp *> dimenarg)) *>
@@ -273,7 +280,7 @@ lookupListDefault d = (fromMaybe d .) . lookupList
273 where
280 where
274 lookupList l m = msum $ map (`M.lookup` m) l
281 lookupList l m = msum $ map (`M.lookup` m) l
275
282
276−blockCommand :: LP Blocks
283+blockCommand :: PandocMonad m => LP m Blocks
277blockCommand = try $ do
284blockCommand = try $ do
278 name <- anyControlSeq
285 name <- anyControlSeq
279 guard $ name /= "begin" && name /= "end"
286 guard $ name /= "begin" && name /= "end"
@@ -291,21 +298,21 @@ inBrackets :: Inlines -> Inlines
291inBrackets x = str "[" <> x <> str "]"
298inBrackets x = str "[" <> x <> str "]"
292
299
293-- eat an optional argument and one or more arguments in braces
300-- eat an optional argument and one or more arguments in braces
294−ignoreInlines :: String -> (String, LP Inlines)
301+ignoreInlines :: PandocMonad m => String -> (String, LP m Inlines)
295ignoreInlines name = (name, doraw <|> (mempty <$ optargs))
302ignoreInlines name = (name, doraw <|> (mempty <$ optargs))
296 where optargs = skipopts *> skipMany (try $ optional sp *> braced)
303 where optargs = skipopts *> skipMany (try $ optional sp *> braced)
297 contseq = '\\':name
304 contseq = '\\':name
298 doraw = (rawInline "latex" . (contseq ++) . snd) <$>
305 doraw = (rawInline "latex" . (contseq ++) . snd) <$>
299 (getOption readerParseRaw >>= guard >> withRaw optargs)
306 (getOption readerParseRaw >>= guard >> withRaw optargs)
300
307
301−ignoreBlocks :: String -> (String, LP Blocks)
308+ignoreBlocks :: PandocMonad m => String -> (String, LP m Blocks)
302ignoreBlocks name = (name, doraw <|> (mempty <$ optargs))
309ignoreBlocks name = (name, doraw <|> (mempty <$ optargs))
303 where optargs = skipopts *> skipMany (try $ optional sp *> braced)
310 where optargs = skipopts *> skipMany (try $ optional sp *> braced)
304 contseq = '\\':name
311 contseq = '\\':name
305 doraw = (rawBlock "latex" . (contseq ++) . snd) <$>
312 doraw = (rawBlock "latex" . (contseq ++) . snd) <$>
306 (getOption readerParseRaw >>= guard >> withRaw optargs)
313 (getOption readerParseRaw >>= guard >> withRaw optargs)
307
314
308−blockCommands :: M.Map String (LP Blocks)
315+blockCommands :: PandocMonad m => M.Map String (LP m Blocks)
309blockCommands = M.fromList $
316blockCommands = M.fromList $
310 [ ("par", mempty <$ skipopts)
317 [ ("par", mempty <$ skipopts)
311 , ("title", mempty <$ (skipopts *>
318 , ("title", mempty <$ (skipopts *>
@@ -370,14 +377,14 @@ blockCommands = M.fromList $
370 , "newpage"
377 , "newpage"
371 ]
378 ]
372
379
373−addMeta :: ToMetaValue a => String -> a -> LP ()
380+addMeta :: PandocMonad m => ToMetaValue a => String -> a -> LP m ()
374addMeta field val = updateState $ \st ->
381addMeta field val = updateState $ \st ->
375 st{ stateMeta = addMetaField field val $ stateMeta st }
382 st{ stateMeta = addMetaField field val $ stateMeta st }
376
383
377splitBibs :: String -> [Inlines]
384splitBibs :: String -> [Inlines]
378splitBibs = map (str . flip replaceExtension "bib" . trim) . splitBy (==',')
385splitBibs = map (str . flip replaceExtension "bib" . trim) . splitBy (==',')
379
386
380−setCaption :: LP Blocks
387+setCaption :: PandocMonad m => LP m Blocks
381setCaption = do
388setCaption = do
382 ils <- tok
389 ils <- tok
383 mblabel <- option Nothing $
390 mblabel <- option Nothing $
@@ -389,10 +396,10 @@ setCaption = do
389 updateState $ \st -> st{ stateCaption = Just ils' }
396 updateState $ \st -> st{ stateCaption = Just ils' }
390 return mempty
397 return mempty
391
398
392−resetCaption :: LP ()
399+resetCaption :: PandocMonad m => LP m ()
393resetCaption = updateState $ \st -> st{ stateCaption = Nothing }
400resetCaption = updateState $ \st -> st{ stateCaption = Nothing }
394
401
395−authors :: LP ()
402+authors :: PandocMonad m => LP m ()
396authors = try $ do
403authors = try $ do
397 char '{'
404 char '{'
398 let oneAuthor = mconcat <$>
405 let oneAuthor = mconcat <$>
@@ -403,7 +410,7 @@ authors = try $ do
403 char '}'
410 char '}'
404 addMeta "author" (map trimInlines auths)
411 addMeta "author" (map trimInlines auths)
405
412
406−section :: Attr -> Int -> LP Blocks
413+section :: PandocMonad m => Attr -> Int -> LP m Blocks
407section (ident, classes, kvs) lvl = do
414section (ident, classes, kvs) lvl = do
408 hasChapters <- stateHasChapters `fmap` getState
415 hasChapters <- stateHasChapters `fmap` getState
409 let lvl' = if hasChapters then lvl + 1 else lvl
416 let lvl' = if hasChapters then lvl + 1 else lvl
@@ -413,7 +420,7 @@ section (ident, classes, kvs) lvl = do
413 attr' <- registerHeader (lab, classes, kvs) contents
420 attr' <- registerHeader (lab, classes, kvs) contents
414 return $ headerWith attr' lvl' contents
421 return $ headerWith attr' lvl' contents
415
422
416−inlineCommand :: LP Inlines
423+inlineCommand :: PandocMonad m => LP m Inlines
417inlineCommand = try $ do
424inlineCommand = try $ do
418 name <- anyControlSeq
425 name <- anyControlSeq
419 guard $ name /= "begin" && name /= "end"
426 guard $ name /= "begin" && name /= "end"
@@ -435,14 +442,14 @@ inlineCommand = try $ do
435 optional (try (string "{}")))
442 optional (try (string "{}")))
436 <|> raw
443 <|> raw
437
444
438−unlessParseRaw :: LP ()
445+unlessParseRaw :: PandocMonad m => LP m ()
439unlessParseRaw = getOption readerParseRaw >>= guard . not
446unlessParseRaw = getOption readerParseRaw >>= guard . not
440
447
441isBlockCommand :: String -> Bool
448isBlockCommand :: String -> Bool
442−isBlockCommand s = s `M.member` blockCommands
449+isBlockCommand s = s `M.member` (blockCommands :: M.Map String (LP PandocPure Blocks))
443
450
444
451
445−inlineEnvironments :: M.Map String (LP Inlines)
452+inlineEnvironments :: PandocMonad m => M.Map String (LP m Inlines)
446inlineEnvironments = M.fromList
453inlineEnvironments = M.fromList
447 [ ("displaymath", mathEnv id Nothing "displaymath")
454 [ ("displaymath", mathEnv id Nothing "displaymath")
448 , ("math", math <$> verbEnv "math")
455 , ("math", math <$> verbEnv "math")
@@ -460,7 +467,7 @@ inlineEnvironments = M.fromList
460 , ("alignat*", mathEnv id (Just "aligned") "alignat*")
467 , ("alignat*", mathEnv id (Just "aligned") "alignat*")
461 ]
468 ]
462
469
463−inlineCommands :: M.Map String (LP Inlines)
470+inlineCommands :: PandocMonad m => M.Map String (LP m Inlines)
464inlineCommands = M.fromList $
471inlineCommands = M.fromList $
465 [ ("emph", extractSpaces emph <$> tok)
472 [ ("emph", extractSpaces emph <$> tok)
466 , ("textit", extractSpaces emph <$> tok)
473 , ("textit", extractSpaces emph <$> tok)
@@ -621,7 +628,7 @@ inlineCommands = M.fromList $
621 -- in which case they will appear as raw latex blocks:
628 -- in which case they will appear as raw latex blocks:
622 [ "index" ]
629 [ "index" ]
623
630
624−mkImage :: [(String, String)] -> String -> LP Inlines
631+mkImage :: PandocMonad m => [(String, String)] -> String -> LP m Inlines
625mkImage options src = do
632mkImage options src = do
626 let replaceTextwidth (k,v) = case numUnit v of
633 let replaceTextwidth (k,v) = case numUnit v of
627 Just (num, "\\textwidth") -> (k, showFl (num * 100) ++ "%")
634 Just (num, "\\textwidth") -> (k, showFl (num * 100) ++ "%")
@@ -645,7 +652,7 @@ unescapeURL ('\\':x:xs) | isEscapable x = x:unescapeURL xs
645unescapeURL (x:xs) = x:unescapeURL xs
652unescapeURL (x:xs) = x:unescapeURL xs
646unescapeURL [] = ""
653unescapeURL [] = ""
647
654
648−enquote :: LP Inlines
655+enquote :: PandocMonad m => LP m Inlines
649enquote = do
656enquote = do
650 skipopts
657 skipopts
651 context <- stateQuoteContext <$> getState
658 context <- stateQuoteContext <$> getState
@@ -653,18 +660,18 @@ enquote = do
653 then singleQuoted <$> withQuoteContext InSingleQuote tok
660 then singleQuoted <$> withQuoteContext InSingleQuote tok
654 else doubleQuoted <$> withQuoteContext InDoubleQuote tok
661 else doubleQuoted <$> withQuoteContext InDoubleQuote tok
655
662
656−doverb :: LP Inlines
663+doverb :: PandocMonad m => LP m Inlines
657doverb = do
664doverb = do
658 marker <- anyChar
665 marker <- anyChar
659 code <$> manyTill (satisfy (/='\n')) (char marker)
666 code <$> manyTill (satisfy (/='\n')) (char marker)
660
667
661−doLHSverb :: LP Inlines
668+doLHSverb :: PandocMonad m => LP m Inlines
662doLHSverb = codeWith ("",["haskell"],[]) <$> manyTill (satisfy (/='\n')) (char '|')
669doLHSverb = codeWith ("",["haskell"],[]) <$> manyTill (satisfy (/='\n')) (char '|')
663
670
664−lit :: String -> LP Inlines
671+lit :: String -> LP m Inlines
665lit = pure . str
672lit = pure . str
666
673
667−accent :: (Char -> String) -> Inlines -> LP Inlines
674+accent :: (Char -> String) -> Inlines -> LP m Inlines
668accent f ils =
675accent f ils =
669 case toList ils of
676 case toList ils of
670 (Str (x:xs) : ys) -> return $ fromList (Str (f x ++ xs) : ys)
677 (Str (x:xs) : ys) -> return $ fromList (Str (f x ++ xs) : ys)
@@ -870,53 +877,53 @@ breve 'U' = "Ŭ"
870breve 'u' = "ŭ"
877breve 'u' = "ŭ"
871breve c = [c]
878breve c = [c]
872
879
873−tok :: LP Inlines
880+tok :: PandocMonad m => LP m Inlines
874tok = try $ grouped inline <|> inlineCommand <|> str <$> count 1 inlineChar
881tok = try $ grouped inline <|> inlineCommand <|> str <$> count 1 inlineChar
875
882
876−opt :: LP Inlines
883+opt :: PandocMonad m => LP m Inlines
877opt = bracketed inline
884opt = bracketed inline
878
885
879−rawopt :: LP String
886+rawopt :: PandocMonad m => LP m String
880rawopt = do
887rawopt = do
881 contents <- bracketed (many1 (noneOf "[]") <|> try (string "\\]") <|>
888 contents <- bracketed (many1 (noneOf "[]") <|> try (string "\\]") <|>
882 try (string "\\[") <|> rawopt)
889 try (string "\\[") <|> rawopt)
883 optional sp
890 optional sp
884 return $ "[" ++ contents ++ "]"
891 return $ "[" ++ contents ++ "]"
885
892
886−skipopts :: LP ()
893+skipopts :: PandocMonad m => LP m ()
887skipopts = skipMany rawopt
894skipopts = skipMany rawopt
888
895
889-- opts in angle brackets are used in beamer
896-- opts in angle brackets are used in beamer
890−rawangle :: LP ()
897+rawangle :: PandocMonad m => LP m ()
891rawangle = try $ do
898rawangle = try $ do
892 char '<'
899 char '<'
893 skipMany (noneOf ">")
900 skipMany (noneOf ">")
894 char '>'
901 char '>'
895 return ()
902 return ()
896
903
897−skipangles :: LP ()
904+skipangles :: PandocMonad m => LP m ()
898skipangles = skipMany rawangle
905skipangles = skipMany rawangle
899
906
900−inlineText :: LP Inlines
907+inlineText :: PandocMonad m => LP m Inlines
901inlineText = str <$> many1 inlineChar
908inlineText = str <$> many1 inlineChar
902
909
903−inlineChar :: LP Char
910+inlineChar :: PandocMonad m => LP m Char
904inlineChar = noneOf "\\$%&~#{}^'`\"‘’“”-[] \t\n"
911inlineChar = noneOf "\\$%&~#{}^'`\"‘’“”-[] \t\n"
905
912
906−environment :: LP Blocks
913+environment :: PandocMonad m => LP m Blocks
907environment = do
914environment = do
908 controlSeq "begin"
915 controlSeq "begin"
909 name <- braced
916 name <- braced
910 M.findWithDefault mzero name environments
917 M.findWithDefault mzero name environments
911 <|> rawEnv name
918 <|> rawEnv name
912
919
913−inlineEnvironment :: LP Inlines
920+inlineEnvironment :: PandocMonad m => LP m Inlines
914inlineEnvironment = try $ do
921inlineEnvironment = try $ do
915 controlSeq "begin"
922 controlSeq "begin"
916 name <- braced
923 name <- braced
917 M.findWithDefault mzero name inlineEnvironments
924 M.findWithDefault mzero name inlineEnvironments
918
925
919−rawEnv :: String -> LP Blocks
926+rawEnv :: PandocMonad m => String -> LP m Blocks
920rawEnv name = do
927rawEnv name = do
921 parseRaw <- getOption readerParseRaw
928 parseRaw <- getOption readerParseRaw
922 rawOptions <- mconcat <$> many rawopt
929 rawOptions <- mconcat <$> many rawopt
@@ -1045,7 +1052,7 @@ readFileFromDirs (d:ds) f =
1045
1052
1046----
1053----
1047
1054
1048−keyval :: LP (String, String)
1055+keyval :: PandocMonad m => LP m (String, String)
1049keyval = try $ do
1056keyval = try $ do
1050 key <- many1 alphaNum
1057 key <- many1 alphaNum
1051 val <- option "" $ char '=' >> many1 (alphaNum <|> char '.' <|> char '\\')
1058 val <- option "" $ char '=' >> many1 (alphaNum <|> char '.' <|> char '\\')
@@ -1055,25 +1062,25 @@ keyval = try $ do
1055 return (key, val)
1062 return (key, val)
1056
1063
1057
1064
1058−keyvals :: LP [(String, String)]
1065+keyvals :: PandocMonad m => LP m [(String, String)]
1059keyvals = try $ char '[' *> manyTill keyval (char ']')
1066keyvals = try $ char '[' *> manyTill keyval (char ']')
1060
1067
1061−alltt :: String -> LP Blocks
1068+alltt :: PandocMonad m => String -> LP m Blocks
1062alltt t = walk strToCode <$> parseFromString blocks
1069alltt t = walk strToCode <$> parseFromString blocks
1063 (substitute " " "\\ " $ substitute "%" "\\%" $
1070 (substitute " " "\\ " $ substitute "%" "\\%" $
1064 intercalate "\\\\\n" $ lines t)
1071 intercalate "\\\\\n" $ lines t)
1065 where strToCode (Str s) = Code nullAttr s
1072 where strToCode (Str s) = Code nullAttr s
1066 strToCode x = x
1073 strToCode x = x
1067
1074
1068−rawLaTeXBlock :: LP String
1075+rawLaTeXBlock :: PandocMonad m => LP m String
1069rawLaTeXBlock = snd <$> try (withRaw (environment <|> blockCommand))
1076rawLaTeXBlock = snd <$> try (withRaw (environment <|> blockCommand))
1070
1077
1071−rawLaTeXInline :: LP Inline
1078+rawLaTeXInline :: PandocMonad m => LP m Inline
1072rawLaTeXInline = do
1079rawLaTeXInline = do
1073 raw <- (snd <$> withRaw inlineCommand) <|> (snd <$> withRaw blockCommand)
1080 raw <- (snd <$> withRaw inlineCommand) <|> (snd <$> withRaw blockCommand)
1074 RawInline "latex" <$> applyMacros' raw
1081 RawInline "latex" <$> applyMacros' raw
1075
1082
1076−addImageCaption :: Blocks -> LP Blocks
1083+addImageCaption :: PandocMonad m => Blocks -> LP m Blocks
1077addImageCaption = walkM go
1084addImageCaption = walkM go
1078 where go (Image attr alt (src,tit)) = do
1085 where go (Image attr alt (src,tit)) = do
1079 mbcapt <- stateCaption <$> getState
1086 mbcapt <- stateCaption <$> getState
@@ -1082,7 +1089,7 @@ addImageCaption = walkM go
1082 Nothing -> Image attr alt (src,tit)
1089 Nothing -> Image attr alt (src,tit)
1083 go x = return x
1090 go x = return x
1084
1091
1085−addTableCaption :: Blocks -> LP Blocks
1092+addTableCaption :: PandocMonad m => Blocks -> LP m Blocks
1086addTableCaption = walkM go
1093addTableCaption = walkM go
1087 where go (Table c als ws hs rs) = do
1094 where go (Table c als ws hs rs) = do
1088 mbcapt <- stateCaption <$> getState
1095 mbcapt <- stateCaption <$> getState
@@ -1091,7 +1098,7 @@ addTableCaption = walkM go
1091 Nothing -> Table c als ws hs rs
1098 Nothing -> Table c als ws hs rs
1092 go x = return x
1099 go x = return x
1093
1100
1094−environments :: M.Map String (LP Blocks)
1101+environments :: PandocMonad m => M.Map String (LP m Blocks)
1095environments = M.fromList
1102environments = M.fromList
1096 [ ("document", env "document" blocks <* skipMany anyChar)
1103 [ ("document", env "document" blocks <* skipMany anyChar)
1097 , ("abstract", mempty <$ (env "abstract" blocks >>= addMeta "abstract"))
1104 , ("abstract", mempty <$ (env "abstract" blocks >>= addMeta "abstract"))
@@ -1159,7 +1166,7 @@ environments = M.fromList
1159 , ("alignat*", mathEnv para (Just "aligned") "alignat*")
1166 , ("alignat*", mathEnv para (Just "aligned") "alignat*")
1160 ]
1167 ]
1161
1168
1162−letterContents :: LP Blocks
1169+letterContents :: PandocMonad m => LP m Blocks
1163letterContents = do
1170letterContents = do
1164 bs <- blocks
1171 bs <- blocks
1165 st <- getState
1172 st <- getState
@@ -1170,7 +1177,7 @@ letterContents = do
1170 _ -> mempty
1177 _ -> mempty
1171 return $ addr <> bs -- sig added by \closing
1178 return $ addr <> bs -- sig added by \closing
1172
1179
1173−closing :: LP Blocks
1180+closing :: PandocMonad m => LP m Blocks
1174closing = do
1181closing = do
1175 contents <- tok
1182 contents <- tok
1176 st <- getState
1183 st <- getState
@@ -1184,17 +1191,17 @@ closing = do
1184 _ -> mempty
1191 _ -> mempty
1185 return $ para (trimInlines contents) <> sigs
1192 return $ para (trimInlines contents) <> sigs
1186
1193
1187−item :: LP Blocks
1194+item :: PandocMonad m => LP m Blocks
1188item = blocks *> controlSeq "item" *> skipopts *> blocks
1195item = blocks *> controlSeq "item" *> skipopts *> blocks
1189
1196
1190−looseItem :: LP Blocks
1197+looseItem :: PandocMonad m => LP m Blocks
1191looseItem = do
1198looseItem = do
1192 ctx <- stateParserContext `fmap` getState
1199 ctx <- stateParserContext `fmap` getState
1193 if ctx == ListItemState
1200 if ctx == ListItemState
1194 then mzero
1201 then mzero
1195 else return mempty
1202 else return mempty
1196
1203
1197−descItem :: LP (Inlines, [Blocks])
1204+descItem :: PandocMonad m => LP m (Inlines, [Blocks])
1198descItem = do
1205descItem = do
1199 blocks -- skip blocks before item
1206 blocks -- skip blocks before item
1200 controlSeq "item"
1207 controlSeq "item"
@@ -1203,12 +1210,12 @@ descItem = do
1203 bs <- blocks
1210 bs <- blocks
1204 return (ils, [bs])
1211 return (ils, [bs])
1205
1212
1206−env :: String -> LP a -> LP a
1213+env :: PandocMonad m => String -> LP m a -> LP m a
1207env name p = p <*
1214env name p = p <*
1208 (try (controlSeq "end" *> braced >>= guard . (== name))
1215 (try (controlSeq "end" *> braced >>= guard . (== name))
1209 <?> ("\\end{" ++ name ++ "}"))
1216 <?> ("\\end{" ++ name ++ "}"))
1210
1217
1211−listenv :: String -> LP a -> LP a
1218+listenv :: PandocMonad m => String -> LP m a -> LP m a
1212listenv name p = try $ do
1219listenv name p = try $ do
1213 oldCtx <- stateParserContext `fmap` getState
1220 oldCtx <- stateParserContext `fmap` getState
1214 updateState $ \st -> st{ stateParserContext = ListItemState }
1221 updateState $ \st -> st{ stateParserContext = ListItemState }
@@ -1216,14 +1223,14 @@ listenv name p = try $ do
1216 updateState $ \st -> st{ stateParserContext = oldCtx }
1223 updateState $ \st -> st{ stateParserContext = oldCtx }
1217 return res
1224 return res
1218
1225
1219−mathEnv :: (Inlines -> a) -> Maybe String -> String -> LP a
1226+mathEnv :: PandocMonad m => (Inlines -> a) -> Maybe String -> String -> LP m a
1220mathEnv f innerEnv name = f <$> mathDisplay (inner <$> verbEnv name)
1227mathEnv f innerEnv name = f <$> mathDisplay (inner <$> verbEnv name)
1221 where inner x = case innerEnv of
1228 where inner x = case innerEnv of
1222 Nothing -> x
1229 Nothing -> x
1223 Just y -> "\\begin{" ++ y ++ "}\n" ++ x ++
1230 Just y -> "\\begin{" ++ y ++ "}\n" ++ x ++
1224 "\\end{" ++ y ++ "}"
1231 "\\end{" ++ y ++ "}"
1225
1232
1226−verbEnv :: String -> LP String
1233+verbEnv :: PandocMonad m => String -> LP m String
1227verbEnv name = do
1234verbEnv name = do
1228 skipopts
1235 skipopts
1229 optional blankline
1236 optional blankline
@@ -1231,7 +1238,7 @@ verbEnv name = do
1231 res <- manyTill anyChar endEnv
1238 res <- manyTill anyChar endEnv
1232 return $ stripTrailingNewlines res
1239 return $ stripTrailingNewlines res
1233
1240
1234−fancyverbEnv :: String -> LP Blocks
1241+fancyverbEnv :: PandocMonad m => String -> LP m Blocks
1235fancyverbEnv name = do
1242fancyverbEnv name = do
1236 options <- option [] keyvals
1243 options <- option [] keyvals
1237 let kvs = [ (if k == "firstnumber"
1244 let kvs = [ (if k == "firstnumber"
@@ -1242,7 +1249,7 @@ fancyverbEnv name = do
1242 let attr = ("",classes,kvs)
1249 let attr = ("",classes,kvs)
1243 codeBlockWith attr <$> verbEnv name
1250 codeBlockWith attr <$> verbEnv name
1244
1251
1245−orderedList' :: LP Blocks
1252+orderedList' :: PandocMonad m => LP m Blocks
1246orderedList' = do
1253orderedList' = do
1247 optional sp
1254 optional sp
1248 (_, style, delim) <- option (1, DefaultStyle, DefaultDelim) $
1255 (_, style, delim) <- option (1, DefaultStyle, DefaultDelim) $
@@ -1259,14 +1266,14 @@ orderedList' = do
1259 bs <- listenv "enumerate" (many item)
1266 bs <- listenv "enumerate" (many item)
1260 return $ orderedListWith (start, style, delim) bs
1267 return $ orderedListWith (start, style, delim) bs
1261
1268
1262−paragraph :: LP Blocks
1269+paragraph :: PandocMonad m => LP m Blocks
1263paragraph = do
1270paragraph = do
1264 x <- trimInlines . mconcat <$> many1 inline
1271 x <- trimInlines . mconcat <$> many1 inline
1265 if x == mempty
1272 if x == mempty
1266 then return mempty
1273 then return mempty
1267 else return $ para x
1274 else return $ para x
1268
1275
1269−preamble :: LP Blocks
1276+preamble :: PandocMonad m => LP m Blocks
1270preamble = mempty <$> manyTill preambleBlock beginDoc
1277preamble = mempty <$> manyTill preambleBlock beginDoc
1271 where beginDoc = lookAhead $ try $ controlSeq "begin" *> string "{document}"
1278 where beginDoc = lookAhead $ try $ controlSeq "begin" *> string "{document}"
1272 preambleBlock = void comment
1279 preambleBlock = void comment
@@ -1292,7 +1299,7 @@ addSuffix s ks@(_:_) =
1292 in init ks ++ [k {citationSuffix = citationSuffix k ++ s}]
1299 in init ks ++ [k {citationSuffix = citationSuffix k ++ s}]
1293addSuffix _ _ = []
1300addSuffix _ _ = []
1294
1301
1295−simpleCiteArgs :: LP [Citation]
1302+simpleCiteArgs :: PandocMonad m => LP m [Citation]
1296simpleCiteArgs = try $ do
1303simpleCiteArgs = try $ do
1297 first <- optionMaybe $ toList <$> opt
1304 first <- optionMaybe $ toList <$> opt
1298 second <- optionMaybe $ toList <$> opt
1305 second <- optionMaybe $ toList <$> opt
@@ -1312,7 +1319,7 @@ simpleCiteArgs = try $ do
1312 }
1319 }
1313 return $ addPrefix pre $ addSuffix suf $ map conv keys
1320 return $ addPrefix pre $ addSuffix suf $ map conv keys
1314
1321
1315−citationLabel :: LP String
1322+citationLabel :: PandocMonad m => LP m String
1316citationLabel = optional sp *>
1323citationLabel = optional sp *>
1317 (many1 (satisfy isBibtexKeyChar)
1324 (many1 (satisfy isBibtexKeyChar)
1318 <* optional sp
1325 <* optional sp
@@ -1320,7 +1327,7 @@ citationLabel = optional sp *>
1320 <* optional sp)
1327 <* optional sp)
1321 where isBibtexKeyChar c = isAlphaNum c || c `elem` (".:;?!`'()/*@_+=-[]" :: String)
1328 where isBibtexKeyChar c = isAlphaNum c || c `elem` (".:;?!`'()/*@_+=-[]" :: String)
1322
1329
1323−cites :: CitationMode -> Bool -> LP [Citation]
1330+cites :: PandocMonad m => CitationMode -> Bool -> LP m [Citation]
1324cites mode multi = try $ do
1331cites mode multi = try $ do
1325 cits <- if multi
1332 cits <- if multi
1326 then many1 simpleCiteArgs
1333 then many1 simpleCiteArgs
@@ -1332,12 +1339,12 @@ cites mode multi = try $ do
1332 [] -> []
1339 [] -> []
1333 _ -> map (\a -> a {citationMode = mode}) cs
1340 _ -> map (\a -> a {citationMode = mode}) cs
1334
1341
1335−citation :: String -> CitationMode -> Bool -> LP Inlines
1342+citation :: PandocMonad m => String -> CitationMode -> Bool -> LP m Inlines
1336citation name mode multi = do
1343citation name mode multi = do
1337 (c,raw) <- withRaw $ cites mode multi
1344 (c,raw) <- withRaw $ cites mode multi
1338 return $ cite c (rawInline "latex" $ "\\" ++ name ++ raw)
1345 return $ cite c (rawInline "latex" $ "\\" ++ name ++ raw)
1339
1346
1340−complexNatbibCitation :: CitationMode -> LP Inlines
1347+complexNatbibCitation :: PandocMonad m => CitationMode -> LP m Inlines
1341complexNatbibCitation mode = try $ do
1348complexNatbibCitation mode = try $ do
1342 let ils = (toList . trimInlines . mconcat) <$>
1349 let ils = (toList . trimInlines . mconcat) <$>
1343 many (notFollowedBy (oneOf "\\};") >> inline)
1350 many (notFollowedBy (oneOf "\\};") >> inline)
@@ -1359,7 +1366,7 @@ complexNatbibCitation mode = try $ do
1359
1366
1360-- tables
1367-- tables
1361
1368
1362−parseAligns :: LP [Alignment]
1369+parseAligns :: PandocMonad m => LP m [Alignment]
1363parseAligns = try $ do
1370parseAligns = try $ do
1364 char '{'
1371 char '{'
1365 let maybeBar = skipMany $ sp <|> () <$ char '|' <|> () <$ (char '@' >> braced)
1372 let maybeBar = skipMany $ sp <|> () <$ char '|' <|> () <$ (char '@' >> braced)
@@ -1375,7 +1382,7 @@ parseAligns = try $ do
1375 spaces
1382 spaces
1376 return aligns'
1383 return aligns'
1377
1384
1378−hline :: LP ()
1385+hline :: PandocMonad m => LP m ()
1379hline = try $ do
1386hline = try $ do
1380 spaces'
1387 spaces'
1381 controlSeq "hline" <|>
1388 controlSeq "hline" <|>
@@ -1389,16 +1396,16 @@ hline = try $ do
1389 optional $ bracketed (many1 (satisfy (/=']')))
1396 optional $ bracketed (many1 (satisfy (/=']')))
1390 return ()
1397 return ()
1391
1398
1392−lbreak :: LP ()
1399+lbreak :: PandocMonad m => LP m ()
1393lbreak = () <$ try (spaces' *>
1400lbreak = () <$ try (spaces' *>
1394 (controlSeq "\\" <|> controlSeq "tabularnewline") <*
1401 (controlSeq "\\" <|> controlSeq "tabularnewline") <*
1395 spaces')
1402 spaces')
1396
1403
1397−amp :: LP ()
1404+amp :: PandocMonad m => LP m ()
1398amp = () <$ try (spaces' *> char '&' <* spaces')
1405amp = () <$ try (spaces' *> char '&' <* spaces')
1399
1406
1400−parseTableRow :: Int -- ^ number of columns
1407+parseTableRow :: PandocMonad m => Int -- ^ number of columns
1401− -> LP [Blocks]
1408+ -> LP m [Blocks]
1402parseTableRow cols = try $ do
1409parseTableRow cols = try $ do
1403 let tableCellInline = notFollowedBy (amp <|> lbreak) >> inline
1410 let tableCellInline = notFollowedBy (amp <|> lbreak) >> inline
1404 let minipage = try $ controlSeq "begin" *> string "{minipage}" *>
1411 let minipage = try $ controlSeq "begin" *> string "{minipage}" *>
@@ -1415,10 +1422,10 @@ parseTableRow cols = try $ do
1415 spaces'
1422 spaces'
1416 return cells''
1423 return cells''
1417
1424
1418−spaces' :: LP ()
1425+spaces' :: PandocMonad m => LP m ()
1419spaces' = spaces *> skipMany (comment *> spaces)
1426spaces' = spaces *> skipMany (comment *> spaces)
1420
1427
1421−simpTable :: Bool -> LP Blocks
1428+simpTable :: PandocMonad m => Bool -> LP m Blocks
1422simpTable hasWidthParameter = try $ do
1429simpTable hasWidthParameter = try $ do
1423 when hasWidthParameter $ () <$ (spaces' >> tok)
1430 when hasWidthParameter $ () <$ (spaces' >> tok)
1424 skipopts
1431 skipopts
@@ -1442,13 +1449,13 @@ simpTable hasWidthParameter = try $ do
1442 lookAhead $ controlSeq "end" -- make sure we're at end
1449 lookAhead $ controlSeq "end" -- make sure we're at end
1443 return $ table mempty (zip aligns (repeat 0)) header'' rows
1450 return $ table mempty (zip aligns (repeat 0)) header'' rows
1444
1451
1445−startInclude :: LP Blocks
1452+startInclude :: PandocMonad m => LP m Blocks
1446startInclude = do
1453startInclude = do
1447 fn <- braced
1454 fn <- braced
1448 setPosition $ newPos fn 1 1
1455 setPosition $ newPos fn 1 1
1449 return mempty
1456 return mempty
1450
1457
1451−endInclude :: LP Blocks
1458+endInclude :: PandocMonad m => LP m Blocks
1452endInclude = do
1459endInclude = do
1453 fn <- braced
1460 fn <- braced
1454 ln <- braced
1461 ln <- braced
src/Text/Pandoc/Readers/Markdown.hs+257−221
@@ -1,5 +1,6 @@
1{-# LANGUAGE RelaxedPolyRec #-} -- needed for inlinesBetween on GHC < 7
1{-# LANGUAGE RelaxedPolyRec #-} -- needed for inlinesBetween on GHC < 7
2{-# LANGUAGE ScopedTypeVariables #-}
2{-# LANGUAGE ScopedTypeVariables #-}
3+
3{-
4{-
4Copyright (C) 2006-2015 John MacFarlane <jgm@berkeley.edu>
5Copyright (C) 2006-2015 John MacFarlane <jgm@berkeley.edu>
5
6
@@ -65,24 +66,31 @@ import qualified Data.Set as Set
65import Text.Printf (printf)
66import Text.Printf (printf)
66import Debug.Trace (trace)
67import Debug.Trace (trace)
67import Data.Monoid ((<>))
68import Data.Monoid ((<>))
68−import Text.Pandoc.Error
69+import Control.Monad.Trans (lift)
70+import Control.Monad.Except (throwError, catchError)
71+import Text.Pandoc.Class (PandocMonad, PandocExecutionError(..))
72+import qualified Text.Pandoc.Class as P
69
73
70−type MarkdownParser = Parser [Char] ParserState
74+type MarkdownParser m = ParserT [Char] ParserState m
71
75
72-- | Read markdown from an input string and return a Pandoc document.
76-- | Read markdown from an input string and return a Pandoc document.
77+readMarkdown :: PandocMonad m
73−readMarkdown :: ReaderOptions -- ^ Reader options
78+ => ReaderOptions -- ^ Reader options
74 -> String -- ^ String to parse (assuming @'\n'@ line endings)
79 -> String -- ^ String to parse (assuming @'\n'@ line endings)
75− -> Either PandocError Pandoc
80+ -> m Pandoc
76−readMarkdown opts s =
81+readMarkdown opts s = do
77− (readWith parseMarkdown) def{ stateOptions = opts } (s ++ "\n\n")
82+ parsed <- (readWithM parseMarkdown) def{ stateOptions = opts } (s ++ "\n\n")
83+ case parsed of
84+ Right result -> return result
85+ Left _ -> throwError $ PandocParseError "markdown parse error"
78
86
79-- | Read markdown from an input string and return a pair of a Pandoc document
87-- | Read markdown from an input string and return a pair of a Pandoc document
80-- and a list of warnings.
88-- and a list of warnings.
89+readMarkdownWithWarnings :: PandocMonad m
81−readMarkdownWithWarnings :: ReaderOptions -- ^ Reader options
90+ => ReaderOptions -- ^ Reader options
82 -> String -- ^ String to parse (assuming @'\n'@ line endings)
91 -> String -- ^ String to parse (assuming @'\n'@ line endings)
83− -> Either PandocError (Pandoc, [String])
92+ -> m Pandoc
84−readMarkdownWithWarnings opts s =
93+readMarkdownWithWarnings = readMarkdown
85− (readWithWarnings parseMarkdown) def{ stateOptions = opts } (s ++ "\n\n")
86
94
87trimInlinesF :: F Inlines -> F Inlines
95trimInlinesF :: F Inlines -> F Inlines
88trimInlinesF = liftM trimInlines
96trimInlinesF = liftM trimInlines
@@ -117,25 +125,25 @@ isBlank _ = False
117--
125--
118
126
119-- | Succeeds when we're in list context.
127-- | Succeeds when we're in list context.
120−inList :: MarkdownParser ()
128+inList :: PandocMonad m => MarkdownParser m ()
121inList = do
129inList = do
122 ctx <- stateParserContext <$> getState
130 ctx <- stateParserContext <$> getState
123 guard (ctx == ListItemState)
131 guard (ctx == ListItemState)
124
132
125−spnl :: Parser [Char] st ()
133+spnl :: PandocMonad m => ParserT [Char] st m ()
126spnl = try $ do
134spnl = try $ do
127 skipSpaces
135 skipSpaces
128 optional newline
136 optional newline
129 skipSpaces
137 skipSpaces
130 notFollowedBy (char '\n')
138 notFollowedBy (char '\n')
131
139
132−indentSpaces :: MarkdownParser String
140+indentSpaces :: PandocMonad m => MarkdownParser m String
133indentSpaces = try $ do
141indentSpaces = try $ do
134 tabStop <- getOption readerTabStop
142 tabStop <- getOption readerTabStop
135 count tabStop (char ' ') <|>
143 count tabStop (char ' ') <|>
136 string "\t" <?> "indentation"
144 string "\t" <?> "indentation"
137
145
138−nonindentSpaces :: MarkdownParser String
146+nonindentSpaces :: PandocMonad m => MarkdownParser m String
139nonindentSpaces = do
147nonindentSpaces = do
140 tabStop <- getOption readerTabStop
148 tabStop <- getOption readerTabStop
141 sps <- many (char ' ')
149 sps <- many (char ' ')
@@ -144,17 +152,17 @@ nonindentSpaces = do
144 else unexpected "indented line"
152 else unexpected "indented line"
145
153
146-- returns number of spaces parsed
154-- returns number of spaces parsed
147−skipNonindentSpaces :: MarkdownParser Int
155+skipNonindentSpaces :: PandocMonad m => MarkdownParser m Int
148skipNonindentSpaces = do
156skipNonindentSpaces = do
149 tabStop <- getOption readerTabStop
157 tabStop <- getOption readerTabStop
150 atMostSpaces (tabStop - 1) <* notFollowedBy (char ' ')
158 atMostSpaces (tabStop - 1) <* notFollowedBy (char ' ')
151
159
152−atMostSpaces :: Int -> MarkdownParser Int
160+atMostSpaces :: PandocMonad m => Int -> MarkdownParser m Int
153atMostSpaces n
161atMostSpaces n
154 | n > 0 = (char ' ' >> (+1) <$> atMostSpaces (n-1)) <|> return 0
162 | n > 0 = (char ' ' >> (+1) <$> atMostSpaces (n-1)) <|> return 0
155 | otherwise = return 0
163 | otherwise = return 0
156
164
157−litChar :: MarkdownParser Char
165+litChar :: PandocMonad m => MarkdownParser m Char
158litChar = escapedChar'
166litChar = escapedChar'
159 <|> characterReference
167 <|> characterReference
160 <|> noneOf "\n"
168 <|> noneOf "\n"
@@ -162,14 +170,14 @@ litChar = escapedChar'
162
170
163-- | Parse a sequence of inline elements between square brackets,
171-- | Parse a sequence of inline elements between square brackets,
164-- including inlines between balanced pairs of square brackets.
172-- including inlines between balanced pairs of square brackets.
165−inlinesInBalancedBrackets :: MarkdownParser (F Inlines)
173+inlinesInBalancedBrackets :: PandocMonad m => MarkdownParser m (F Inlines)
166inlinesInBalancedBrackets = do
174inlinesInBalancedBrackets = do
167 char '['
175 char '['
168 (_, raw) <- withRaw $ charsInBalancedBrackets 1
176 (_, raw) <- withRaw $ charsInBalancedBrackets 1
169 guard $ not $ null raw
177 guard $ not $ null raw
170 parseFromString (trimInlinesF . mconcat <$> many inline) (init raw)
178 parseFromString (trimInlinesF . mconcat <$> many inline) (init raw)
171
179
172−charsInBalancedBrackets :: Int -> MarkdownParser ()
180+charsInBalancedBrackets :: PandocMonad m => Int -> MarkdownParser m ()
173charsInBalancedBrackets 0 = return ()
181charsInBalancedBrackets 0 = return ()
174charsInBalancedBrackets openBrackets =
182charsInBalancedBrackets openBrackets =
175 (char '[' >> charsInBalancedBrackets (openBrackets + 1))
183 (char '[' >> charsInBalancedBrackets (openBrackets + 1))
@@ -185,7 +193,7 @@ charsInBalancedBrackets openBrackets =
185-- document structure
193-- document structure
186--
194--
187
195
188−rawTitleBlockLine :: MarkdownParser String
196+rawTitleBlockLine :: PandocMonad m => MarkdownParser m String
189rawTitleBlockLine = do
197rawTitleBlockLine = do
190 char '%'
198 char '%'
191 skipSpaces
199 skipSpaces
@@ -196,13 +204,13 @@ rawTitleBlockLine = do
196 anyLine
204 anyLine
197 return $ trim $ unlines (first:rest)
205 return $ trim $ unlines (first:rest)
198
206
199−titleLine :: MarkdownParser (F Inlines)
207+titleLine :: PandocMonad m => MarkdownParser m (F Inlines)
200titleLine = try $ do
208titleLine = try $ do
201 raw <- rawTitleBlockLine
209 raw <- rawTitleBlockLine
202 res <- parseFromString (many inline) raw
210 res <- parseFromString (many inline) raw
203 return $ trimInlinesF $ mconcat res
211 return $ trimInlinesF $ mconcat res
204
212
205−authorsLine :: MarkdownParser (F [Inlines])
213+authorsLine :: PandocMonad m => MarkdownParser m (F [Inlines])
206authorsLine = try $ do
214authorsLine = try $ do
207 raw <- rawTitleBlockLine
215 raw <- rawTitleBlockLine
208 let sep = (char ';' <* spaces) <|> newline
216 let sep = (char ';' <* spaces) <|> newline
@@ -212,16 +220,16 @@ authorsLine = try $ do
212 sep
220 sep
213 sequence <$> parseFromString pAuthors raw
221 sequence <$> parseFromString pAuthors raw
214
222
215−dateLine :: MarkdownParser (F Inlines)
223+dateLine :: PandocMonad m => MarkdownParser m (F Inlines)
216dateLine = try $ do
224dateLine = try $ do
217 raw <- rawTitleBlockLine
225 raw <- rawTitleBlockLine
218 res <- parseFromString (many inline) raw
226 res <- parseFromString (many inline) raw
219 return $ trimInlinesF $ mconcat res
227 return $ trimInlinesF $ mconcat res
220
228
221−titleBlock :: MarkdownParser ()
229+titleBlock :: PandocMonad m => MarkdownParser m ()
222titleBlock = pandocTitleBlock <|> mmdTitleBlock
230titleBlock = pandocTitleBlock <|> mmdTitleBlock
223
231
224−pandocTitleBlock :: MarkdownParser ()
232+pandocTitleBlock :: PandocMonad m => MarkdownParser m ()
225pandocTitleBlock = try $ do
233pandocTitleBlock = try $ do
226 guardEnabled Ext_pandoc_title_block
234 guardEnabled Ext_pandoc_title_block
227 lookAhead (char '%')
235 lookAhead (char '%')
@@ -239,7 +247,15 @@ pandocTitleBlock = try $ do
239 $ nullMeta
247 $ nullMeta
240 updateState $ \st -> st{ stateMeta' = stateMeta' st <> meta' }
248 updateState $ \st -> st{ stateMeta' = stateMeta' st <> meta' }
241
249
250+
251+-- Adapted from solution at
252+-- http://stackoverflow.com/a/29448764/1901888
253+foldrWithKeyM :: Monad m => (k -> b -> a -> m a) -> a -> H.HashMap k b -> m a
254+foldrWithKeyM f acc = H.foldrWithKey f' (return acc)
255+ where
256+ f' k b ma = ma >>= \a -> f k b a
257+
242−yamlMetaBlock :: MarkdownParser (F Blocks)
258+yamlMetaBlock :: PandocMonad m => MarkdownParser m (F Blocks)
243yamlMetaBlock = try $ do
259yamlMetaBlock = try $ do
244 guardEnabled Ext_yaml_metadata_block
260 guardEnabled Ext_yaml_metadata_block
245 pos <- getPosition
261 pos <- getPosition
@@ -252,18 +268,20 @@ yamlMetaBlock = try $ do
252 optional blanklines
268 optional blanklines
253 opts <- stateOptions <$> getState
269 opts <- stateOptions <$> getState
254 meta' <- case Yaml.decodeEither' $ UTF8.fromString rawYaml of
270 meta' <- case Yaml.decodeEither' $ UTF8.fromString rawYaml of
255− Right (Yaml.Object hashmap) -> return $ return $
271+ Right (Yaml.Object hashmap) ->
256− H.foldrWithKey (\k v m ->
272+ foldrWithKeyM
273+ (\k v m -> do
257− if ignorable k
274+ if ignorable k
258− then m
275+ then return m
259− else case yamlToMeta opts v of
276+ else (do v' <- lift $ yamlToMeta opts v
260− Left _ -> m
261− Right v' -> B.setMeta (T.unpack k) v' m)
277+ return $ B.setMeta (T.unpack k) v' m)
278+ `catchError`
279+ (\_ -> return m)
262− nullMeta hashmap
280+ ) nullMeta hashmap
263− Right Yaml.Null -> return $ return nullMeta
281+ Right Yaml.Null -> return nullMeta
264 Right _ -> do
282 Right _ -> do
265− addWarning (Just pos) "YAML header is not an object"
283+ P.addWarningWithPos (Just pos) "YAML header is not an object"
266− return $ return nullMeta
284+ return nullMeta
267 Left err' -> do
285 Left err' -> do
268 case err' of
286 case err' of
269 InvalidYaml (Just YamlParseException{
287 InvalidYaml (Just YamlParseException{
@@ -273,24 +291,24 @@ yamlMetaBlock = try $ do
273 yamlLine = yline
291 yamlLine = yline
274 , yamlColumn = ycol
292 , yamlColumn = ycol
275 }}) ->
293 }}) ->
276− addWarning (Just $ setSourceLine
294+ P.addWarningWithPos (Just $ setSourceLine
277 (setSourceColumn pos
295 (setSourceColumn pos
278 (sourceColumn pos + ycol))
296 (sourceColumn pos + ycol))
279 (sourceLine pos + 1 + yline))
297 (sourceLine pos + 1 + yline))
280 $ "Could not parse YAML header: " ++
298 $ "Could not parse YAML header: " ++
281 problem
299 problem
282− _ -> addWarning (Just pos)
300+ _ -> P.addWarningWithPos (Just pos)
283 $ "Could not parse YAML header: " ++
301 $ "Could not parse YAML header: " ++
284 show err'
302 show err'
285− return $ return nullMeta
303+ return nullMeta
286− updateState $ \st -> st{ stateMeta' = stateMeta' st <> meta' }
304+ updateState $ \st -> st{ stateMeta' = stateMeta' st <> (return meta') }
287 return mempty
305 return mempty
288
306
289-- ignore fields ending with _
307-- ignore fields ending with _
290ignorable :: Text -> Bool
308ignorable :: Text -> Bool
291ignorable t = (T.pack "_") `T.isSuffixOf` t
309ignorable t = (T.pack "_") `T.isSuffixOf` t
292
310
293−toMetaValue :: ReaderOptions -> Text -> Either PandocError MetaValue
311+toMetaValue :: PandocMonad m => ReaderOptions -> Text -> m MetaValue
294toMetaValue opts x = toMeta <$> readMarkdown opts' (T.unpack x)
312toMetaValue opts x = toMeta <$> readMarkdown opts' (T.unpack x)
295 where
313 where
296 toMeta p =
314 toMeta p =
@@ -307,7 +325,7 @@ toMetaValue opts x = toMeta <$> readMarkdown opts' (T.unpack x)
307 , Ext_yaml_metadata_block
325 , Ext_yaml_metadata_block
308 ]
326 ]
309
327
310−yamlToMeta :: ReaderOptions -> Yaml.Value -> Either PandocError MetaValue
328+yamlToMeta :: PandocMonad m => ReaderOptions -> Yaml.Value -> m MetaValue
311yamlToMeta opts (Yaml.String t) = toMetaValue opts t
329yamlToMeta opts (Yaml.String t) = toMetaValue opts t
312yamlToMeta _ (Yaml.Number n)
330yamlToMeta _ (Yaml.Number n)
313 -- avoid decimal points for numbers that don't need them:
331 -- avoid decimal points for numbers that don't need them:
@@ -327,10 +345,10 @@ yamlToMeta opts (Yaml.Object o) = MetaMap <$> H.foldrWithKey (\k v m ->
327 (return M.empty) o
345 (return M.empty) o
328yamlToMeta _ _ = return $ MetaString ""
346yamlToMeta _ _ = return $ MetaString ""
329
347
330−stopLine :: MarkdownParser ()
348+stopLine :: PandocMonad m => MarkdownParser m ()
331stopLine = try $ (string "---" <|> string "...") >> blankline >> return ()
349stopLine = try $ (string "---" <|> string "...") >> blankline >> return ()
332
350
333−mmdTitleBlock :: MarkdownParser ()
351+mmdTitleBlock :: PandocMonad m => MarkdownParser m ()
334mmdTitleBlock = try $ do
352mmdTitleBlock = try $ do
335 guardEnabled Ext_mmd_title_block
353 guardEnabled Ext_mmd_title_block
336 firstPair <- kvPair False
354 firstPair <- kvPair False
@@ -340,7 +358,7 @@ mmdTitleBlock = try $ do
340 updateState $ \st -> st{ stateMeta' = stateMeta' st <>
358 updateState $ \st -> st{ stateMeta' = stateMeta' st <>
341 return (Meta $ M.fromList kvPairs) }
359 return (Meta $ M.fromList kvPairs) }
342
360
343−kvPair :: Bool -> MarkdownParser (String, MetaValue)
361+kvPair :: PandocMonad m => Bool -> MarkdownParser m (String, MetaValue)
344kvPair allowEmpty = try $ do
362kvPair allowEmpty = try $ do
345 key <- many1Till (alphaNum <|> oneOf "_- ") (char ':')
363 key <- many1Till (alphaNum <|> oneOf "_- ") (char ':')
346 val <- trim <$> manyTill anyChar
364 val <- trim <$> manyTill anyChar
@@ -350,7 +368,7 @@ kvPair allowEmpty = try $ do
350 let val' = MetaBlocks $ B.toList $ B.plain $ B.text $ val
368 let val' = MetaBlocks $ B.toList $ B.plain $ B.text $ val
351 return (key',val')
369 return (key',val')
352
370
353−parseMarkdown :: MarkdownParser Pandoc
371+parseMarkdown :: PandocMonad m => MarkdownParser m Pandoc
354parseMarkdown = do
372parseMarkdown = do
355 -- markdown allows raw HTML
373 -- markdown allows raw HTML
356 updateState $ \state -> state { stateOptions =
374 updateState $ \state -> state { stateOptions =
@@ -375,7 +393,7 @@ softBreakFilter (x:SoftBreak:y:zs) =
375 _ -> x:SoftBreak:y:zs
393 _ -> x:SoftBreak:y:zs
376softBreakFilter xs = xs
394softBreakFilter xs = xs
377
395
378−referenceKey :: MarkdownParser (F Blocks)
396+referenceKey :: PandocMonad m => MarkdownParser m (F Blocks)
379referenceKey = try $ do
397referenceKey = try $ do
380 pos <- getPosition
398 pos <- getPosition
381 skipNonindentSpaces
399 skipNonindentSpaces
@@ -402,18 +420,18 @@ referenceKey = try $ do
402 let oldkeys = stateKeys st
420 let oldkeys = stateKeys st
403 let key = toKey raw
421 let key = toKey raw
404 case M.lookup key oldkeys of
422 case M.lookup key oldkeys of
405− Just _ -> addWarning (Just pos) $ "Duplicate link reference `" ++ raw ++ "'"
423+ Just _ -> P.addWarningWithPos (Just pos) $ "Duplicate link reference `" ++ raw ++ "'"
406 Nothing -> return ()
424 Nothing -> return ()
407 updateState $ \s -> s { stateKeys = M.insert key (target, attr') oldkeys }
425 updateState $ \s -> s { stateKeys = M.insert key (target, attr') oldkeys }
408 return $ return mempty
426 return $ return mempty
409
427
410−referenceTitle :: MarkdownParser String
428+referenceTitle :: PandocMonad m => MarkdownParser m String
411referenceTitle = try $ do
429referenceTitle = try $ do
412 skipSpaces >> optional newline >> skipSpaces
430 skipSpaces >> optional newline >> skipSpaces
413 quotedTitle '"' <|> quotedTitle '\'' <|> charsInBalanced '(' ')' litChar
431 quotedTitle '"' <|> quotedTitle '\'' <|> charsInBalanced '(' ')' litChar
414
432
415-- A link title in quotes
433-- A link title in quotes
416−quotedTitle :: Char -> MarkdownParser String
434+quotedTitle :: PandocMonad m => Char -> MarkdownParser m String
417quotedTitle c = try $ do
435quotedTitle c = try $ do
418 char c
436 char c
419 notFollowedBy spaces
437 notFollowedBy spaces
@@ -425,7 +443,7 @@ quotedTitle c = try $ do
425-- | PHP Markdown Extra style abbreviation key. Currently
443-- | PHP Markdown Extra style abbreviation key. Currently
426-- we just skip them, since Pandoc doesn't have an element for
444-- we just skip them, since Pandoc doesn't have an element for
427-- an abbreviation.
445-- an abbreviation.
428−abbrevKey :: MarkdownParser (F Blocks)
446+abbrevKey :: PandocMonad m => MarkdownParser m (F Blocks)
429abbrevKey = do
447abbrevKey = do
430 guardEnabled Ext_abbreviations
448 guardEnabled Ext_abbreviations
431 try $ do
449 try $ do
@@ -436,23 +454,23 @@ abbrevKey = do
436 blanklines
454 blanklines
437 return $ return mempty
455 return $ return mempty
438
456
439−noteMarker :: MarkdownParser String
457+noteMarker :: PandocMonad m => MarkdownParser m String
440noteMarker = string "[^" >> many1Till (satisfy $ not . isBlank) (char ']')
458noteMarker = string "[^" >> many1Till (satisfy $ not . isBlank) (char ']')
441
459
442−rawLine :: MarkdownParser String
460+rawLine :: PandocMonad m => MarkdownParser m String
443rawLine = try $ do
461rawLine = try $ do
444 notFollowedBy blankline
462 notFollowedBy blankline
445 notFollowedBy' $ try $ skipNonindentSpaces >> noteMarker
463 notFollowedBy' $ try $ skipNonindentSpaces >> noteMarker
446 optional indentSpaces
464 optional indentSpaces
447 anyLine
465 anyLine
448
466
449−rawLines :: MarkdownParser String
467+rawLines :: PandocMonad m => MarkdownParser m String
450rawLines = do
468rawLines = do
451 first <- anyLine
469 first <- anyLine
452 rest <- many rawLine
470 rest <- many rawLine
453 return $ unlines (first:rest)
471 return $ unlines (first:rest)
454
472
455−noteBlock :: MarkdownParser (F Blocks)
473+noteBlock :: PandocMonad m => MarkdownParser m (F Blocks)
456noteBlock = try $ do
474noteBlock = try $ do
457 pos <- getPosition
475 pos <- getPosition
458 skipNonindentSpaces
476 skipNonindentSpaces
@@ -468,7 +486,7 @@ noteBlock = try $ do
468 let newnote = (ref, parsed)
486 let newnote = (ref, parsed)
469 oldnotes <- stateNotes' <$> getState
487 oldnotes <- stateNotes' <$> getState
470 case lookup ref oldnotes of
488 case lookup ref oldnotes of
471− Just _ -> addWarning (Just pos) $ "Duplicate note reference `" ++ ref ++ "'"
489+ Just _ -> P.addWarningWithPos (Just pos) $ "Duplicate note reference `" ++ ref ++ "'"
472 Nothing -> return ()
490 Nothing -> return ()
473 updateState $ \s -> s { stateNotes' = newnote : oldnotes }
491 updateState $ \s -> s { stateNotes' = newnote : oldnotes }
474 return mempty
492 return mempty
@@ -477,10 +495,10 @@ noteBlock = try $ do
477-- parsing blocks
495-- parsing blocks
478--
496--
479
497
480−parseBlocks :: MarkdownParser (F Blocks)
498+parseBlocks :: PandocMonad m => MarkdownParser m (F Blocks)
481parseBlocks = mconcat <$> manyTill block eof
499parseBlocks = mconcat <$> manyTill block eof
482
500
483−block :: MarkdownParser (F Blocks)
501+block :: PandocMonad m => MarkdownParser m (F Blocks)
484block = do
502block = do
485 tr <- getOption readerTrace
503 tr <- getOption readerTrace
486 pos <- getPosition
504 pos <- getPosition
@@ -519,16 +537,16 @@ block = do
519-- header blocks
537-- header blocks
520--
538--
521
539
522−header :: MarkdownParser (F Blocks)
540+header :: PandocMonad m => MarkdownParser m (F Blocks)
523header = setextHeader <|> atxHeader <?> "header"
541header = setextHeader <|> atxHeader <?> "header"
524
542
525−atxChar :: MarkdownParser Char
543+atxChar :: PandocMonad m => MarkdownParser m Char
526atxChar = do
544atxChar = do
527 exts <- getOption readerExtensions
545 exts <- getOption readerExtensions
528 return $ if Set.member Ext_literate_haskell exts
546 return $ if Set.member Ext_literate_haskell exts
529 then '=' else '#'
547 then '=' else '#'
530
548
531−atxHeader :: MarkdownParser (F Blocks)
549+atxHeader :: PandocMonad m => MarkdownParser m (F Blocks)
532atxHeader = try $ do
550atxHeader = try $ do
533 level <- atxChar >>= many1 . char >>= return . length
551 level <- atxChar >>= many1 . char >>= return . length
534 notFollowedBy $ guardEnabled Ext_fancy_lists >>
552 notFollowedBy $ guardEnabled Ext_fancy_lists >>
@@ -542,7 +560,7 @@ atxHeader = try $ do
542 <|> registerImplicitHeader raw attr'
560 <|> registerImplicitHeader raw attr'
543 return $ B.headerWith attr' level <$> text
561 return $ B.headerWith attr' level <$> text
544
562
545−atxClosing :: MarkdownParser Attr
563+atxClosing :: PandocMonad m => MarkdownParser m Attr
546atxClosing = try $ do
564atxClosing = try $ do
547 attr' <- option nullAttr
565 attr' <- option nullAttr
548 (guardEnabled Ext_mmd_header_identifiers >> mmdHeaderIdentifier)
566 (guardEnabled Ext_mmd_header_identifiers >> mmdHeaderIdentifier)
@@ -553,7 +571,7 @@ atxClosing = try $ do
553 blanklines
571 blanklines
554 return attr
572 return attr
555
573
556−setextHeaderEnd :: MarkdownParser Attr
574+setextHeaderEnd :: PandocMonad m => MarkdownParser m Attr
557setextHeaderEnd = try $ do
575setextHeaderEnd = try $ do
558 attr <- option nullAttr
576 attr <- option nullAttr
559 $ (guardEnabled Ext_mmd_header_identifiers >> mmdHeaderIdentifier)
577 $ (guardEnabled Ext_mmd_header_identifiers >> mmdHeaderIdentifier)
@@ -561,13 +579,13 @@ setextHeaderEnd = try $ do
561 blanklines
579 blanklines
562 return attr
580 return attr
563
581
564−mmdHeaderIdentifier :: MarkdownParser Attr
582+mmdHeaderIdentifier :: PandocMonad m => MarkdownParser m Attr
565mmdHeaderIdentifier = do
583mmdHeaderIdentifier = do
566 ident <- stripFirstAndLast . snd <$> reference
584 ident <- stripFirstAndLast . snd <$> reference
567 skipSpaces
585 skipSpaces
568 return (ident,[],[])
586 return (ident,[],[])
569
587
570−setextHeader :: MarkdownParser (F Blocks)
588+setextHeader :: PandocMonad m => MarkdownParser m (F Blocks)
571setextHeader = try $ do
589setextHeader = try $ do
572 -- This lookahead prevents us from wasting time parsing Inlines
590 -- This lookahead prevents us from wasting time parsing Inlines
573 -- unless necessary -- it gives a significant performance boost.
591 -- unless necessary -- it gives a significant performance boost.
@@ -585,7 +603,7 @@ setextHeader = try $ do
585 <|> registerImplicitHeader raw attr'
603 <|> registerImplicitHeader raw attr'
586 return $ B.headerWith attr' level <$> text
604 return $ B.headerWith attr' level <$> text
587
605
588−registerImplicitHeader :: String -> Attr -> MarkdownParser ()
606+registerImplicitHeader :: PandocMonad m => String -> Attr -> MarkdownParser m ()
589registerImplicitHeader raw attr@(ident, _, _) = do
607registerImplicitHeader raw attr@(ident, _, _) = do
590 let key = toKey $ "[" ++ raw ++ "]"
608 let key = toKey $ "[" ++ raw ++ "]"
591 updateState (\s -> s { stateHeaderKeys =
609 updateState (\s -> s { stateHeaderKeys =
@@ -595,7 +613,7 @@ registerImplicitHeader raw attr@(ident, _, _) = do
595-- hrule block
613-- hrule block
596--
614--
597
615
598−hrule :: Parser [Char] st (F Blocks)
616+hrule :: PandocMonad m => ParserT [Char] st m (F Blocks)
599hrule = try $ do
617hrule = try $ do
600 skipSpaces
618 skipSpaces
601 start <- satisfy isHruleChar
619 start <- satisfy isHruleChar
@@ -609,12 +627,13 @@ hrule = try $ do
609-- code blocks
627-- code blocks
610--
628--
611
629
612−indentedLine :: MarkdownParser String
630+indentedLine :: PandocMonad m => MarkdownParser m String
613indentedLine = indentSpaces >> anyLine >>= return . (++ "\n")
631indentedLine = indentSpaces >> anyLine >>= return . (++ "\n")
614
632
615−blockDelimiter :: (Char -> Bool)
633+blockDelimiter :: PandocMonad m
634+ => (Char -> Bool)
616 -> Maybe Int
635 -> Maybe Int
617− -> Parser [Char] st Int
636+ -> ParserT [Char] st m Int
618blockDelimiter f len = try $ do
637blockDelimiter f len = try $ do
619 c <- lookAhead (satisfy f)
638 c <- lookAhead (satisfy f)
620 case len of
639 case len of
@@ -622,7 +641,7 @@ blockDelimiter f len = try $ do
622 Nothing -> count 3 (char c) >> many (char c) >>=
641 Nothing -> count 3 (char c) >> many (char c) >>=
623 return . (+ 3) . length
642 return . (+ 3) . length
624
643
625−attributes :: MarkdownParser Attr
644+attributes :: PandocMonad m => MarkdownParser m Attr
626attributes = try $ do
645attributes = try $ do
627 char '{'
646 char '{'
628 spnl
647 spnl
@@ -630,28 +649,28 @@ attributes = try $ do
630 char '}'
649 char '}'
631 return $ foldl (\x f -> f x) nullAttr attrs
650 return $ foldl (\x f -> f x) nullAttr attrs
632
651
633−attribute :: MarkdownParser (Attr -> Attr)
652+attribute :: PandocMonad m => MarkdownParser m (Attr -> Attr)
634attribute = identifierAttr <|> classAttr <|> keyValAttr <|> specialAttr
653attribute = identifierAttr <|> classAttr <|> keyValAttr <|> specialAttr
635
654
636−identifier :: MarkdownParser String
655+identifier :: PandocMonad m => MarkdownParser m String
637identifier = do
656identifier = do
638 first <- letter
657 first <- letter
639 rest <- many $ alphaNum <|> oneOf "-_:."
658 rest <- many $ alphaNum <|> oneOf "-_:."
640 return (first:rest)
659 return (first:rest)
641
660
642−identifierAttr :: MarkdownParser (Attr -> Attr)
661+identifierAttr :: PandocMonad m => MarkdownParser m (Attr -> Attr)
643identifierAttr = try $ do
662identifierAttr = try $ do
644 char '#'
663 char '#'
645 result <- identifier
664 result <- identifier
646 return $ \(_,cs,kvs) -> (result,cs,kvs)
665 return $ \(_,cs,kvs) -> (result,cs,kvs)
647
666
648−classAttr :: MarkdownParser (Attr -> Attr)
667+classAttr :: PandocMonad m => MarkdownParser m (Attr -> Attr)
649classAttr = try $ do
668classAttr = try $ do
650 char '.'
669 char '.'
651 result <- identifier
670 result <- identifier
652 return $ \(id',cs,kvs) -> (id',cs ++ [result],kvs)
671 return $ \(id',cs,kvs) -> (id',cs ++ [result],kvs)
653
672
654−keyValAttr :: MarkdownParser (Attr -> Attr)
673+keyValAttr :: PandocMonad m => MarkdownParser m (Attr -> Attr)
655keyValAttr = try $ do
674keyValAttr = try $ do
656 key <- identifier
675 key <- identifier
657 char '='
676 char '='
@@ -664,12 +683,12 @@ keyValAttr = try $ do
664 "class" -> (id',cs ++ words val,kvs)
683 "class" -> (id',cs ++ words val,kvs)
665 _ -> (id',cs,kvs ++ [(key,val)])
684 _ -> (id',cs,kvs ++ [(key,val)])
666
685
667−specialAttr :: MarkdownParser (Attr -> Attr)
686+specialAttr :: PandocMonad m => MarkdownParser m (Attr -> Attr)
668specialAttr = do
687specialAttr = do
669 char '-'
688 char '-'
670 return $ \(id',cs,kvs) -> (id',cs ++ ["unnumbered"],kvs)
689 return $ \(id',cs,kvs) -> (id',cs ++ ["unnumbered"],kvs)
671
690
672−codeBlockFenced :: MarkdownParser (F Blocks)
691+codeBlockFenced :: PandocMonad m => MarkdownParser m (F Blocks)
673codeBlockFenced = try $ do
692codeBlockFenced = try $ do
674 c <- try (guardEnabled Ext_fenced_code_blocks >> lookAhead (char '~'))
693 c <- try (guardEnabled Ext_fenced_code_blocks >> lookAhead (char '~'))
675 <|> (guardEnabled Ext_backtick_code_blocks >> lookAhead (char '`'))
694 <|> (guardEnabled Ext_backtick_code_blocks >> lookAhead (char '`'))
@@ -690,7 +709,7 @@ toLanguageId = map toLower . go
690 go "objective-c" = "objectivec"
709 go "objective-c" = "objectivec"
691 go x = x
710 go x = x
692
711
693−codeBlockIndented :: MarkdownParser (F Blocks)
712+codeBlockIndented :: PandocMonad m => MarkdownParser m (F Blocks)
694codeBlockIndented = do
713codeBlockIndented = do
695 contents <- many1 (indentedLine <|>
714 contents <- many1 (indentedLine <|>
696 try (do b <- blanklines
715 try (do b <- blanklines
@@ -701,7 +720,7 @@ codeBlockIndented = do
701 return $ return $ B.codeBlockWith ("", classes, []) $
720 return $ return $ B.codeBlockWith ("", classes, []) $
702 stripTrailingNewlines $ concat contents
721 stripTrailingNewlines $ concat contents
703
722
704−lhsCodeBlock :: MarkdownParser (F Blocks)
723+lhsCodeBlock :: PandocMonad m => MarkdownParser m (F Blocks)
705lhsCodeBlock = do
724lhsCodeBlock = do
706 guardEnabled Ext_literate_haskell
725 guardEnabled Ext_literate_haskell
707 (return . B.codeBlockWith ("",["sourceCode","literate","haskell"],[]) <$>
726 (return . B.codeBlockWith ("",["sourceCode","literate","haskell"],[]) <$>
@@ -709,7 +728,7 @@ lhsCodeBlock = do
709 <|> (return . B.codeBlockWith ("",["sourceCode","haskell"],[]) <$>
728 <|> (return . B.codeBlockWith ("",["sourceCode","haskell"],[]) <$>
710 lhsCodeBlockInverseBird)
729 lhsCodeBlockInverseBird)
711
730
712−lhsCodeBlockLaTeX :: MarkdownParser String
731+lhsCodeBlockLaTeX :: PandocMonad m => MarkdownParser m String
713lhsCodeBlockLaTeX = try $ do
732lhsCodeBlockLaTeX = try $ do
714 string "\\begin{code}"
733 string "\\begin{code}"
715 manyTill spaceChar newline
734 manyTill spaceChar newline
@@ -717,13 +736,13 @@ lhsCodeBlockLaTeX = try $ do
717 blanklines
736 blanklines
718 return $ stripTrailingNewlines contents
737 return $ stripTrailingNewlines contents
719
738
720−lhsCodeBlockBird :: MarkdownParser String
739+lhsCodeBlockBird :: PandocMonad m => MarkdownParser m String
721lhsCodeBlockBird = lhsCodeBlockBirdWith '>'
740lhsCodeBlockBird = lhsCodeBlockBirdWith '>'
722
741
723−lhsCodeBlockInverseBird :: MarkdownParser String
742+lhsCodeBlockInverseBird :: PandocMonad m => MarkdownParser m String
724lhsCodeBlockInverseBird = lhsCodeBlockBirdWith '<'
743lhsCodeBlockInverseBird = lhsCodeBlockBirdWith '<'
725
744
726−lhsCodeBlockBirdWith :: Char -> MarkdownParser String
745+lhsCodeBlockBirdWith :: PandocMonad m => Char -> MarkdownParser m String
727lhsCodeBlockBirdWith c = try $ do
746lhsCodeBlockBirdWith c = try $ do
728 pos <- getPosition
747 pos <- getPosition
729 when (sourceColumn pos /= 1) $ fail "Not in first column"
748 when (sourceColumn pos /= 1) $ fail "Not in first column"
@@ -735,7 +754,7 @@ lhsCodeBlockBirdWith c = try $ do
735 blanklines
754 blanklines
736 return $ intercalate "\n" lns'
755 return $ intercalate "\n" lns'
737
756
738−birdTrackLine :: Char -> Parser [Char] st String
757+birdTrackLine :: PandocMonad m => Char -> ParserT [Char] st m String
739birdTrackLine c = try $ do
758birdTrackLine c = try $ do
740 char c
759 char c
741 -- allow html tags on left margin:
760 -- allow html tags on left margin:
@@ -746,10 +765,10 @@ birdTrackLine c = try $ do
746-- block quotes
765-- block quotes
747--
766--
748
767
749−emailBlockQuoteStart :: MarkdownParser Char
768+emailBlockQuoteStart :: PandocMonad m => MarkdownParser m Char
750emailBlockQuoteStart = try $ skipNonindentSpaces >> char '>' <* optional (char ' ')
769emailBlockQuoteStart = try $ skipNonindentSpaces >> char '>' <* optional (char ' ')
751
770
752−emailBlockQuote :: MarkdownParser [String]
771+emailBlockQuote :: PandocMonad m => MarkdownParser m [String]
753emailBlockQuote = try $ do
772emailBlockQuote = try $ do
754 emailBlockQuoteStart
773 emailBlockQuoteStart
755 let emailLine = many $ nonEndline <|> try
774 let emailLine = many $ nonEndline <|> try
@@ -763,7 +782,7 @@ emailBlockQuote = try $ do
763 optional blanklines
782 optional blanklines
764 return raw
783 return raw
765
784
766−blockQuote :: MarkdownParser (F Blocks)
785+blockQuote :: PandocMonad m => MarkdownParser m (F Blocks)
767blockQuote = do
786blockQuote = do
768 raw <- emailBlockQuote
787 raw <- emailBlockQuote
769 -- parse the extracted block, which may contain various block elements:
788 -- parse the extracted block, which may contain various block elements:
@@ -774,7 +793,7 @@ blockQuote = do
774-- list blocks
793-- list blocks
775--
794--
776
795
777−bulletListStart :: MarkdownParser ()
796+bulletListStart :: PandocMonad m => MarkdownParser m ()
778bulletListStart = try $ do
797bulletListStart = try $ do
779 optional newline -- if preceded by a Plain block in a list context
798 optional newline -- if preceded by a Plain block in a list context
780 startpos <- sourceColumn <$> getPosition
799 startpos <- sourceColumn <$> getPosition
@@ -786,7 +805,7 @@ bulletListStart = try $ do
786 lookAhead (newline <|> spaceChar)
805 lookAhead (newline <|> spaceChar)
787 () <$ atMostSpaces (tabStop - (endpos - startpos))
806 () <$ atMostSpaces (tabStop - (endpos - startpos))
788
807
789−anyOrderedListStart :: MarkdownParser (Int, ListNumberStyle, ListNumberDelim)
808+anyOrderedListStart :: PandocMonad m => MarkdownParser m (Int, ListNumberStyle, ListNumberDelim)
790anyOrderedListStart = try $ do
809anyOrderedListStart = try $ do
791 optional newline -- if preceded by a Plain block in a list context
810 optional newline -- if preceded by a Plain block in a list context
792 startpos <- sourceColumn <$> getPosition
811 startpos <- sourceColumn <$> getPosition
@@ -810,10 +829,10 @@ anyOrderedListStart = try $ do
810 atMostSpaces (tabStop - (endpos - startpos))
829 atMostSpaces (tabStop - (endpos - startpos))
811 return res
830 return res
812
831
813−listStart :: MarkdownParser ()
832+listStart :: PandocMonad m => MarkdownParser m ()
814listStart = bulletListStart <|> (anyOrderedListStart >> return ())
833listStart = bulletListStart <|> (anyOrderedListStart >> return ())
815
834
816−listLine :: MarkdownParser String
835+listLine :: PandocMonad m => MarkdownParser m String
817listLine = try $ do
836listLine = try $ do
818 notFollowedBy' (do indentSpaces
837 notFollowedBy' (do indentSpaces
819 many spaceChar
838 many spaceChar
@@ -822,7 +841,7 @@ listLine = try $ do
822 optional (() <$ indentSpaces)
841 optional (() <$ indentSpaces)
823 listLineCommon
842 listLineCommon
824
843
825−listLineCommon :: MarkdownParser String
844+listLineCommon :: PandocMonad m => MarkdownParser m String
826listLineCommon = concat <$> manyTill
845listLineCommon = concat <$> manyTill
827 ( many1 (satisfy $ \c -> c /= '\n' && c /= '<')
846 ( many1 (satisfy $ \c -> c /= '\n' && c /= '<')
828 <|> liftM snd (htmlTag isCommentTag)
847 <|> liftM snd (htmlTag isCommentTag)
@@ -830,8 +849,9 @@ listLineCommon = concat <$> manyTill
830 ) newline
849 ) newline
831
850
832-- parse raw text for one list item, excluding start marker and continuations
851-- parse raw text for one list item, excluding start marker and continuations
852+rawListItem :: PandocMonad m
833−rawListItem :: MarkdownParser a
853+ => MarkdownParser m a
834− -> MarkdownParser String
854+ -> MarkdownParser m String
835rawListItem start = try $ do
855rawListItem start = try $ do
836 start
856 start
837 first <- listLineCommon
857 first <- listLineCommon
@@ -842,21 +862,21 @@ rawListItem start = try $ do
842-- continuation of a list item - indented and separated by blankline
862-- continuation of a list item - indented and separated by blankline
843-- or (in compact lists) endline.
863-- or (in compact lists) endline.
844-- note: nested lists are parsed as continuations
864-- note: nested lists are parsed as continuations
845−listContinuation :: MarkdownParser String
865+listContinuation :: PandocMonad m => MarkdownParser m String
846listContinuation = try $ do
866listContinuation = try $ do
847 lookAhead indentSpaces
867 lookAhead indentSpaces
848 result <- many1 listContinuationLine
868 result <- many1 listContinuationLine
849 blanks <- many blankline
869 blanks <- many blankline
850 return $ concat result ++ blanks
870 return $ concat result ++ blanks
851
871
852−notFollowedByHtmlCloser :: MarkdownParser ()
872+notFollowedByHtmlCloser :: PandocMonad m => MarkdownParser m ()
853notFollowedByHtmlCloser = do
873notFollowedByHtmlCloser = do
854 inHtmlBlock <- stateInHtmlBlock <$> getState
874 inHtmlBlock <- stateInHtmlBlock <$> getState
855 case inHtmlBlock of
875 case inHtmlBlock of
856 Just t -> notFollowedBy' $ htmlTag (~== TagClose t)
876 Just t -> notFollowedBy' $ htmlTag (~== TagClose t)
857 Nothing -> return ()
877 Nothing -> return ()
858
878
859−listContinuationLine :: MarkdownParser String
879+listContinuationLine :: PandocMonad m => MarkdownParser m String
860listContinuationLine = try $ do
880listContinuationLine = try $ do
861 notFollowedBy blankline
881 notFollowedBy blankline
862 notFollowedBy' listStart
882 notFollowedBy' listStart
@@ -865,8 +885,9 @@ listContinuationLine = try $ do
865 result <- anyLine
885 result <- anyLine
866 return $ result ++ "\n"
886 return $ result ++ "\n"
867
887
888+listItem :: PandocMonad m
868−listItem :: MarkdownParser a
889+ => MarkdownParser m a
869− -> MarkdownParser (F Blocks)
890+ -> MarkdownParser m (F Blocks)
870listItem start = try $ do
891listItem start = try $ do
871 first <- rawListItem start
892 first <- rawListItem start
872 continuations <- many listContinuation
893 continuations <- many listContinuation
@@ -882,7 +903,7 @@ listItem start = try $ do
882 updateState (\st -> st {stateParserContext = oldContext})
903 updateState (\st -> st {stateParserContext = oldContext})
883 return contents
904 return contents
884
905
885−orderedList :: MarkdownParser (F Blocks)
906+orderedList :: PandocMonad m => MarkdownParser m (F Blocks)
886orderedList = try $ do
907orderedList = try $ do
887 (start, style, delim) <- lookAhead anyOrderedListStart
908 (start, style, delim) <- lookAhead anyOrderedListStart
888 unless (style `elem` [DefaultStyle, Decimal, Example] &&
909 unless (style `elem` [DefaultStyle, Decimal, Example] &&
@@ -903,14 +924,14 @@ orderedList = try $ do
903 start' <- option 1 $ guardEnabled Ext_startnum >> return start
924 start' <- option 1 $ guardEnabled Ext_startnum >> return start
904 return $ B.orderedListWith (start', style, delim) <$> fmap compactify' items
925 return $ B.orderedListWith (start', style, delim) <$> fmap compactify' items
905
926
906−bulletList :: MarkdownParser (F Blocks)
927+bulletList :: PandocMonad m => MarkdownParser m (F Blocks)
907bulletList = do
928bulletList = do
908 items <- fmap sequence $ many1 $ listItem bulletListStart
929 items <- fmap sequence $ many1 $ listItem bulletListStart
909 return $ B.bulletList <$> fmap compactify' items
930 return $ B.bulletList <$> fmap compactify' items
910
931
911-- definition lists
932-- definition lists
912
933
913−defListMarker :: MarkdownParser ()
934+defListMarker :: PandocMonad m => MarkdownParser m ()
914defListMarker = do
935defListMarker = do
915 sps <- nonindentSpaces
936 sps <- nonindentSpaces
916 char ':' <|> char '~'
937 char ':' <|> char '~'
@@ -921,7 +942,7 @@ defListMarker = do
921 else mzero
942 else mzero
922 return ()
943 return ()
923
944
924−definitionListItem :: Bool -> MarkdownParser (F (Inlines, [Blocks]))
945+definitionListItem :: PandocMonad m => Bool -> MarkdownParser m (F (Inlines, [Blocks]))
925definitionListItem compact = try $ do
946definitionListItem compact = try $ do
926 rawLine' <- anyLine
947 rawLine' <- anyLine
927 raw <- many1 $ defRawBlock compact
948 raw <- many1 $ defRawBlock compact
@@ -930,7 +951,7 @@ definitionListItem compact = try $ do
930 optional blanklines
951 optional blanklines
931 return $ liftM2 (,) term (sequence contents)
952 return $ liftM2 (,) term (sequence contents)
932
953
933−defRawBlock :: Bool -> MarkdownParser String
954+defRawBlock :: PandocMonad m => Bool -> MarkdownParser m String
934defRawBlock compact = try $ do
955defRawBlock compact = try $ do
935 hasBlank <- option False $ blankline >> return True
956 hasBlank <- option False $ blankline >> return True
936 defListMarker
957 defListMarker
@@ -952,7 +973,7 @@ defRawBlock compact = try $ do
952 return $ trimr (firstline ++ "\n" ++ unlines rawlines ++ cont) ++
973 return $ trimr (firstline ++ "\n" ++ unlines rawlines ++ cont) ++
953 if hasBlank || not (null cont) then "\n\n" else ""
974 if hasBlank || not (null cont) then "\n\n" else ""
954
975
955−definitionList :: MarkdownParser (F Blocks)
976+definitionList :: PandocMonad m => MarkdownParser m (F Blocks)
956definitionList = try $ do
977definitionList = try $ do
957 lookAhead (anyLine >>
978 lookAhead (anyLine >>
958 optional (blankline >> notFollowedBy (table >> return ())) >>
979 optional (blankline >> notFollowedBy (table >> return ())) >>
@@ -960,13 +981,13 @@ definitionList = try $ do
960 defListMarker)
981 defListMarker)
961 compactDefinitionList <|> normalDefinitionList
982 compactDefinitionList <|> normalDefinitionList
962
983
963−compactDefinitionList :: MarkdownParser (F Blocks)
984+compactDefinitionList :: PandocMonad m => MarkdownParser m (F Blocks)
964compactDefinitionList = do
985compactDefinitionList = do
965 guardEnabled Ext_compact_definition_lists
986 guardEnabled Ext_compact_definition_lists
966 items <- fmap sequence $ many1 $ definitionListItem True
987 items <- fmap sequence $ many1 $ definitionListItem True
967 return $ B.definitionList <$> fmap compactify'DL items
988 return $ B.definitionList <$> fmap compactify'DL items
968
989
969−normalDefinitionList :: MarkdownParser (F Blocks)
990+normalDefinitionList :: PandocMonad m => MarkdownParser m (F Blocks)
970normalDefinitionList = do
991normalDefinitionList = do
971 guardEnabled Ext_definition_lists
992 guardEnabled Ext_definition_lists
972 items <- fmap sequence $ many1 $ definitionListItem False
993 items <- fmap sequence $ many1 $ definitionListItem False
@@ -976,7 +997,7 @@ normalDefinitionList = do
976-- paragraph block
997-- paragraph block
977--
998--
978
999
979−para :: MarkdownParser (F Blocks)
1000+para :: PandocMonad m => MarkdownParser m (F Blocks)
980para = try $ do
1001para = try $ do
981 exts <- getOption readerExtensions
1002 exts <- getOption readerExtensions
982 result <- trimInlinesF . mconcat <$> many1 inline
1003 result <- trimInlinesF . mconcat <$> many1 inline
@@ -1007,19 +1028,19 @@ para = try $ do
1007 $ Image attr alt (src,'f':'i':'g':':':tit)
1028 $ Image attr alt (src,'f':'i':'g':':':tit)
1008 _ -> return $ B.para result'
1029 _ -> return $ B.para result'
1009
1030
1010−plain :: MarkdownParser (F Blocks)
1031+plain :: PandocMonad m => MarkdownParser m (F Blocks)
1011plain = fmap B.plain . trimInlinesF . mconcat <$> many1 inline
1032plain = fmap B.plain . trimInlinesF . mconcat <$> many1 inline
1012
1033
1013--
1034--
1014-- raw html
1035-- raw html
1015--
1036--
1016
1037
1017−htmlElement :: MarkdownParser String
1038+htmlElement :: PandocMonad m => MarkdownParser m String
1018htmlElement = rawVerbatimBlock
1039htmlElement = rawVerbatimBlock
1019 <|> strictHtmlBlock
1040 <|> strictHtmlBlock
1020 <|> liftM snd (htmlTag isBlockTag)
1041 <|> liftM snd (htmlTag isBlockTag)
1021
1042
1022−htmlBlock :: MarkdownParser (F Blocks)
1043+htmlBlock :: PandocMonad m => MarkdownParser m (F Blocks)
1023htmlBlock = do
1044htmlBlock = do
1024 guardEnabled Ext_raw_html
1045 guardEnabled Ext_raw_html
1025 try (do
1046 try (do
@@ -1044,24 +1065,24 @@ htmlBlock = do
1044 <|> (guardEnabled Ext_markdown_in_html_blocks >> rawHtmlBlocks))
1065 <|> (guardEnabled Ext_markdown_in_html_blocks >> rawHtmlBlocks))
1045 <|> htmlBlock'
1066 <|> htmlBlock'
1046
1067
1047−htmlBlock' :: MarkdownParser (F Blocks)
1068+htmlBlock' :: PandocMonad m => MarkdownParser m (F Blocks)
1048htmlBlock' = try $ do
1069htmlBlock' = try $ do
1049 first <- htmlElement
1070 first <- htmlElement
1050 skipMany spaceChar
1071 skipMany spaceChar
1051 optional blanklines
1072 optional blanklines
1052 return $ return $ B.rawBlock "html" first
1073 return $ return $ B.rawBlock "html" first
1053
1074
1054−strictHtmlBlock :: MarkdownParser String
1075+strictHtmlBlock :: PandocMonad m => MarkdownParser m String
1055strictHtmlBlock = htmlInBalanced (not . isInlineTag)
1076strictHtmlBlock = htmlInBalanced (not . isInlineTag)
1056
1077
1057−rawVerbatimBlock :: MarkdownParser String
1078+rawVerbatimBlock :: PandocMonad m => MarkdownParser m String
1058rawVerbatimBlock = htmlInBalanced isVerbTag
1079rawVerbatimBlock = htmlInBalanced isVerbTag
1059 where isVerbTag (TagOpen "pre" _) = True
1080 where isVerbTag (TagOpen "pre" _) = True
1060 isVerbTag (TagOpen "style" _) = True
1081 isVerbTag (TagOpen "style" _) = True
1061 isVerbTag (TagOpen "script" _) = True
1082 isVerbTag (TagOpen "script" _) = True
1062 isVerbTag _ = False
1083 isVerbTag _ = False
1063
1084
1064−rawTeXBlock :: MarkdownParser (F Blocks)
1085+rawTeXBlock :: PandocMonad m => MarkdownParser m (F Blocks)
1065rawTeXBlock = do
1086rawTeXBlock = do
1066 guardEnabled Ext_raw_tex
1087 guardEnabled Ext_raw_tex
1067 result <- (B.rawBlock "latex" . concat <$>
1088 result <- (B.rawBlock "latex" . concat <$>
@@ -1071,7 +1092,7 @@ rawTeXBlock = do
1071 spaces
1092 spaces
1072 return $ return result
1093 return $ return result
1073
1094
1074−rawHtmlBlocks :: MarkdownParser (F Blocks)
1095+rawHtmlBlocks :: PandocMonad m => MarkdownParser m (F Blocks)
1075rawHtmlBlocks = do
1096rawHtmlBlocks = do
1076 (TagOpen tagtype _, raw) <- htmlTag isBlockTag
1097 (TagOpen tagtype _, raw) <- htmlTag isBlockTag
1077 -- try to find closing tag
1098 -- try to find closing tag
@@ -1101,7 +1122,7 @@ stripMarkdownAttribute s = renderTags' $ map filterAttrib $ parseTags s
1101-- line block
1122-- line block
1102--
1123--
1103
1124
1104−lineBlock :: MarkdownParser (F Blocks)
1125+lineBlock :: PandocMonad m => MarkdownParser m (F Blocks)
1105lineBlock = try $ do
1126lineBlock = try $ do
1106 guardEnabled Ext_line_blocks
1127 guardEnabled Ext_line_blocks
1107 lines' <- lineBlockLines >>=
1128 lines' <- lineBlockLines >>=
@@ -1114,8 +1135,9 @@ lineBlock = try $ do
1114
1135
1115-- Parse a dashed line with optional trailing spaces; return its length
1136-- Parse a dashed line with optional trailing spaces; return its length
1116-- and the length including trailing space.
1137-- and the length including trailing space.
1117−dashedLine :: Char
1138+dashedLine :: PandocMonad m
1139+ => Char
1118− -> Parser [Char] st (Int, Int)
1140+ -> ParserT [Char] st m (Int, Int)
1119dashedLine ch = do
1141dashedLine ch = do
1120 dashes <- many1 (char ch)
1142 dashes <- many1 (char ch)
1121 sp <- many spaceChar
1143 sp <- many spaceChar
@@ -1125,8 +1147,9 @@ dashedLine ch = do
1125
1147
1126-- Parse a table header with dashed lines of '-' preceded by
1148-- Parse a table header with dashed lines of '-' preceded by
1127-- one (or zero) line of text.
1149-- one (or zero) line of text.
1150+simpleTableHeader :: PandocMonad m
1128−simpleTableHeader :: Bool -- ^ Headerless table
1151+ => Bool -- ^ Headerless table
1129− -> MarkdownParser (F [Blocks], [Alignment], [Int])
1152+ -> MarkdownParser m (F [Blocks], [Alignment], [Int])
1130simpleTableHeader headless = try $ do
1153simpleTableHeader headless = try $ do
1131 rawContent <- if headless
1154 rawContent <- if headless
1132 then return ""
1155 then return ""
@@ -1170,16 +1193,17 @@ alignType strLst len =
1170 (False, False) -> AlignDefault
1193 (False, False) -> AlignDefault
1171
1194
1172-- Parse a table footer - dashed lines followed by blank line.
1195-- Parse a table footer - dashed lines followed by blank line.
1173−tableFooter :: MarkdownParser String
1196+tableFooter :: PandocMonad m => MarkdownParser m String
1174tableFooter = try $ skipNonindentSpaces >> many1 (dashedLine '-') >> blanklines
1197tableFooter = try $ skipNonindentSpaces >> many1 (dashedLine '-') >> blanklines
1175
1198
1176-- Parse a table separator - dashed line.
1199-- Parse a table separator - dashed line.
1177−tableSep :: MarkdownParser Char
1200+tableSep :: PandocMonad m => MarkdownParser m Char
1178tableSep = try $ skipNonindentSpaces >> many1 (dashedLine '-') >> char '\n'
1201tableSep = try $ skipNonindentSpaces >> many1 (dashedLine '-') >> char '\n'
1179
1202
1180-- Parse a raw line and split it into chunks by indices.
1203-- Parse a raw line and split it into chunks by indices.
1181−rawTableLine :: [Int]
1204+rawTableLine :: PandocMonad m
1205+ => [Int]
1182− -> MarkdownParser [String]
1206+ -> MarkdownParser m [String]
1183rawTableLine indices = do
1207rawTableLine indices = do
1184 notFollowedBy' (blanklines <|> tableFooter)
1208 notFollowedBy' (blanklines <|> tableFooter)
1185 line <- many1Till anyChar newline
1209 line <- many1Till anyChar newline
@@ -1187,14 +1211,16 @@ rawTableLine indices = do
1187 splitStringByIndices (init indices) line
1211 splitStringByIndices (init indices) line
1188
1212
1189-- Parse a table line and return a list of lists of blocks (columns).
1213-- Parse a table line and return a list of lists of blocks (columns).
1190−tableLine :: [Int]
1214+tableLine :: PandocMonad m
1215+ => [Int]
1191− -> MarkdownParser (F [Blocks])
1216+ -> MarkdownParser m (F [Blocks])
1192tableLine indices = rawTableLine indices >>=
1217tableLine indices = rawTableLine indices >>=
1193 fmap sequence . mapM (parseFromString (mconcat <$> many plain))
1218 fmap sequence . mapM (parseFromString (mconcat <$> many plain))
1194
1219
1195-- Parse a multiline table row and return a list of blocks (columns).
1220-- Parse a multiline table row and return a list of blocks (columns).
1196−multilineRow :: [Int]
1221+multilineRow :: PandocMonad m
1222+ => [Int]
1197− -> MarkdownParser (F [Blocks])
1223+ -> MarkdownParser m (F [Blocks])
1198multilineRow indices = do
1224multilineRow indices = do
1199 colLines <- many1 (rawTableLine indices)
1225 colLines <- many1 (rawTableLine indices)
1200 let cols = map unlines $ transpose colLines
1226 let cols = map unlines $ transpose colLines
@@ -1202,7 +1228,7 @@ multilineRow indices = do
1202
1228
1203-- Parses a table caption: inlines beginning with 'Table:'
1229-- Parses a table caption: inlines beginning with 'Table:'
1204-- and followed by blank lines.
1230-- and followed by blank lines.
1205−tableCaption :: MarkdownParser (F Inlines)
1231+tableCaption :: PandocMonad m => MarkdownParser m (F Inlines)
1206tableCaption = try $ do
1232tableCaption = try $ do
1207 guardEnabled Ext_table_captions
1233 guardEnabled Ext_table_captions
1208 skipNonindentSpaces
1234 skipNonindentSpaces
@@ -1210,8 +1236,9 @@ tableCaption = try $ do
1210 trimInlinesF . mconcat <$> many1 inline <* blanklines
1236 trimInlinesF . mconcat <$> many1 inline <* blanklines
1211
1237
1212-- Parse a simple table with '---' header and one line per row.
1238-- Parse a simple table with '---' header and one line per row.
1239+simpleTable :: PandocMonad m
1213−simpleTable :: Bool -- ^ Headerless table
1240+ => Bool -- ^ Headerless table
1214− -> MarkdownParser ([Alignment], [Double], F [Blocks], F [[Blocks]])
1241+ -> MarkdownParser m ([Alignment], [Double], F [Blocks], F [[Blocks]])
1215simpleTable headless = do
1242simpleTable headless = do
1216 (aligns, _widths, heads', lines') <-
1243 (aligns, _widths, heads', lines') <-
1217 tableWith (simpleTableHeader headless) tableLine
1244 tableWith (simpleTableHeader headless) tableLine
@@ -1224,13 +1251,15 @@ simpleTable headless = do
1224-- (which may be multiline), then the rows,
1251-- (which may be multiline), then the rows,
1225-- which may be multiline, separated by blank lines, and
1252-- which may be multiline, separated by blank lines, and
1226-- ending with a footer (dashed line followed by blank line).
1253-- ending with a footer (dashed line followed by blank line).
1254+multilineTable :: PandocMonad m
1227−multilineTable :: Bool -- ^ Headerless table
1255+ => Bool -- ^ Headerless table
1228− -> MarkdownParser ([Alignment], [Double], F [Blocks], F [[Blocks]])
1256+ -> MarkdownParser m ([Alignment], [Double], F [Blocks], F [[Blocks]])
1229multilineTable headless =
1257multilineTable headless =
1230 tableWith (multilineTableHeader headless) multilineRow blanklines tableFooter
1258 tableWith (multilineTableHeader headless) multilineRow blanklines tableFooter
1231
1259
1260+multilineTableHeader :: PandocMonad m
1232−multilineTableHeader :: Bool -- ^ Headerless table
1261+ => Bool -- ^ Headerless table
1233− -> MarkdownParser (F [Blocks], [Alignment], [Int])
1262+ -> MarkdownParser m (F [Blocks], [Alignment], [Int])
1234multilineTableHeader headless = try $ do
1263multilineTableHeader headless = try $ do
1235 unless headless $
1264 unless headless $
1236 tableSep >> notFollowedBy blankline
1265 tableSep >> notFollowedBy blankline
@@ -1261,8 +1290,8 @@ multilineTableHeader headless = try $ do
1261-- (which may be grid), then the rows,
1290-- (which may be grid), then the rows,
1262-- which may be grid, separated by blank lines, and
1291-- which may be grid, separated by blank lines, and
1263-- ending with a footer (dashed line followed by blank line).
1292-- ending with a footer (dashed line followed by blank line).
1264−gridTable :: Bool -- ^ Headerless table
1293+gridTable :: PandocMonad m => Bool -- ^ Headerless table
1265− -> MarkdownParser ([Alignment], [Double], F [Blocks], F [[Blocks]])
1294+ -> MarkdownParser m ([Alignment], [Double], F [Blocks], F [[Blocks]])
1266gridTable headless =
1295gridTable headless =
1267 tableWith (gridTableHeader headless) gridTableRow
1296 tableWith (gridTableHeader headless) gridTableRow
1268 (gridTableSep '-') gridTableFooter
1297 (gridTableSep '-') gridTableFooter
@@ -1271,7 +1300,7 @@ gridTableSplitLine :: [Int] -> String -> [String]
1271gridTableSplitLine indices line = map removeFinalBar $ tail $
1300gridTableSplitLine indices line = map removeFinalBar $ tail $
1272 splitStringByIndices (init indices) $ trimr line
1301 splitStringByIndices (init indices) $ trimr line
1273
1302
1274−gridPart :: Char -> Parser [Char] st ((Int, Int), Alignment)
1303+gridPart :: PandocMonad m => Char -> ParserT [Char] st m ((Int, Int), Alignment)
1275gridPart ch = do
1304gridPart ch = do
1276 leftColon <- option False (True <$ char ':')
1305 leftColon <- option False (True <$ char ':')
1277 dashes <- many1 (char ch)
1306 dashes <- many1 (char ch)
@@ -1286,7 +1315,7 @@ gridPart ch = do
1286 (False, False) -> AlignDefault
1315 (False, False) -> AlignDefault
1287 return ((lengthDashes, lengthDashes + 1), alignment)
1316 return ((lengthDashes, lengthDashes + 1), alignment)
1288
1317
1289−gridDashedLines :: Char -> Parser [Char] st [((Int, Int), Alignment)]
1318+gridDashedLines :: PandocMonad m => Char -> ParserT [Char] st m [((Int, Int), Alignment)]
1290gridDashedLines ch = try $ char '+' >> many1 (gridPart ch) <* blankline
1319gridDashedLines ch = try $ char '+' >> many1 (gridPart ch) <* blankline
1291
1320
1292removeFinalBar :: String -> String
1321removeFinalBar :: String -> String
@@ -1294,12 +1323,12 @@ removeFinalBar =
1294 reverse . dropWhile (`elem` " \t") . dropWhile (=='|') . reverse
1323 reverse . dropWhile (`elem` " \t") . dropWhile (=='|') . reverse
1295
1324
1296-- | Separator between rows of grid table.
1325-- | Separator between rows of grid table.
1297−gridTableSep :: Char -> MarkdownParser Char
1326+gridTableSep :: PandocMonad m => Char -> MarkdownParser m Char
1298gridTableSep ch = try $ gridDashedLines ch >> return '\n'
1327gridTableSep ch = try $ gridDashedLines ch >> return '\n'
1299
1328
1300-- | Parse header for a grid table.
1329-- | Parse header for a grid table.
1301−gridTableHeader :: Bool -- ^ Headerless table
1330+gridTableHeader :: PandocMonad m => Bool -- ^ Headerless table
1302− -> MarkdownParser (F [Blocks], [Alignment], [Int])
1331+ -> MarkdownParser m (F [Blocks], [Alignment], [Int])
1303gridTableHeader headless = try $ do
1332gridTableHeader headless = try $ do
1304 optional blanklines
1333 optional blanklines
1305 dashes <- gridDashedLines '-'
1334 dashes <- gridDashedLines '-'
@@ -1320,15 +1349,15 @@ gridTableHeader headless = try $ do
1320 heads <- fmap sequence $ mapM (parseFromString parseBlocks . trim) rawHeads
1349 heads <- fmap sequence $ mapM (parseFromString parseBlocks . trim) rawHeads
1321 return (heads, aligns, indices)
1350 return (heads, aligns, indices)
1322
1351
1323−gridTableRawLine :: [Int] -> MarkdownParser [String]
1352+gridTableRawLine :: PandocMonad m => [Int] -> MarkdownParser m [String]
1324gridTableRawLine indices = do
1353gridTableRawLine indices = do
1325 char '|'
1354 char '|'
1326 line <- anyLine
1355 line <- anyLine
1327 return (gridTableSplitLine indices line)
1356 return (gridTableSplitLine indices line)
1328
1357
1329-- | Parse row of grid table.
1358-- | Parse row of grid table.
1330−gridTableRow :: [Int]
1359+gridTableRow :: PandocMonad m => [Int]
1331− -> MarkdownParser (F [Blocks])
1360+ -> MarkdownParser m (F [Blocks])
1332gridTableRow indices = do
1361gridTableRow indices = do
1333 colLines <- many1 (gridTableRawLine indices)
1362 colLines <- many1 (gridTableRawLine indices)
1334 let cols = map ((++ "\n") . unlines . removeOneLeadingSpace) $
1363 let cols = map ((++ "\n") . unlines . removeOneLeadingSpace) $
@@ -1344,10 +1373,10 @@ removeOneLeadingSpace xs =
1344 startsWithSpace (y:_) = y == ' '
1373 startsWithSpace (y:_) = y == ' '
1345
1374
1346-- | Parse footer for a grid table.
1375-- | Parse footer for a grid table.
1347−gridTableFooter :: MarkdownParser [Char]
1376+gridTableFooter :: PandocMonad m => MarkdownParser m [Char]
1348gridTableFooter = blanklines
1377gridTableFooter = blanklines
1349
1378
1350−pipeBreak :: MarkdownParser ([Alignment], [Int])
1379+pipeBreak :: PandocMonad m => MarkdownParser m ([Alignment], [Int])
1351pipeBreak = try $ do
1380pipeBreak = try $ do
1352 nonindentSpaces
1381 nonindentSpaces
1353 openPipe <- (True <$ char '|') <|> return False
1382 openPipe <- (True <$ char '|') <|> return False
@@ -1359,7 +1388,7 @@ pipeBreak = try $ do
1359 blankline
1388 blankline
1360 return $ unzip (first:rest)
1389 return $ unzip (first:rest)
1361
1390
1362−pipeTable :: MarkdownParser ([Alignment], [Double], F [Blocks], F [[Blocks]])
1391+pipeTable :: PandocMonad m => MarkdownParser m ([Alignment], [Double], F [Blocks], F [[Blocks]])
1363pipeTable = try $ do
1392pipeTable = try $ do
1364 nonindentSpaces
1393 nonindentSpaces
1365 lookAhead nonspaceChar
1394 lookAhead nonspaceChar
@@ -1377,13 +1406,13 @@ pipeTable = try $ do
1377 else replicate (length aligns) 0.0
1406 else replicate (length aligns) 0.0
1378 return $ (aligns, widths, heads', sequence lines'')
1407 return $ (aligns, widths, heads', sequence lines'')
1379
1408
1380−sepPipe :: MarkdownParser ()
1409+sepPipe :: PandocMonad m => MarkdownParser m ()
1381sepPipe = try $ do
1410sepPipe = try $ do
1382 char '|' <|> char '+'
1411 char '|' <|> char '+'
1383 notFollowedBy blankline
1412 notFollowedBy blankline
1384
1413
1385-- parse a row, also returning probable alignments for org-table cells
1414-- parse a row, also returning probable alignments for org-table cells
1386−pipeTableRow :: MarkdownParser (F [Blocks])
1415+pipeTableRow :: PandocMonad m => MarkdownParser m (F [Blocks])
1387pipeTableRow = try $ do
1416pipeTableRow = try $ do
1388 scanForPipe
1417 scanForPipe
1389 skipMany spaceChar
1418 skipMany spaceChar
@@ -1399,14 +1428,14 @@ pipeTableRow = try $ do
1399 blankline
1428 blankline
1400 return $ sequence cells
1429 return $ sequence cells
1401
1430
1402−pipeTableCell :: MarkdownParser (F Blocks)
1431+pipeTableCell :: PandocMonad m => MarkdownParser m (F Blocks)
1403pipeTableCell = do
1432pipeTableCell = do
1404 result <- many inline
1433 result <- many inline
1405 if null result
1434 if null result
1406 then return mempty
1435 then return mempty
1407 else return $ B.plain . mconcat <$> sequence result
1436 else return $ B.plain . mconcat <$> sequence result
1408
1437
1409−pipeTableHeaderPart :: Parser [Char] st (Alignment, Int)
1438+pipeTableHeaderPart :: PandocMonad m => ParserT [Char] st m (Alignment, Int)
1410pipeTableHeaderPart = try $ do
1439pipeTableHeaderPart = try $ do
1411 skipMany spaceChar
1440 skipMany spaceChar
1412 left <- optionMaybe (char ':')
1441 left <- optionMaybe (char ':')
@@ -1422,7 +1451,7 @@ pipeTableHeaderPart = try $ do
1422 (Just _,Just _) -> AlignCenter), len)
1451 (Just _,Just _) -> AlignCenter), len)
1423
1452
1424-- Succeed only if current line contains a pipe.
1453-- Succeed only if current line contains a pipe.
1425−scanForPipe :: Parser [Char] st ()
1454+scanForPipe :: PandocMonad m => ParserT [Char] st m ()
1426scanForPipe = do
1455scanForPipe = do
1427 inp <- getInput
1456 inp <- getInput
1428 case break (\c -> c == '\n' || c == '|') inp of
1457 case break (\c -> c == '\n' || c == '|') inp of
@@ -1432,11 +1461,12 @@ scanForPipe = do
1432-- | Parse a table using 'headerParser', 'rowParser',
1461-- | Parse a table using 'headerParser', 'rowParser',
1433-- 'lineParser', and 'footerParser'. Variant of the version in
1462-- 'lineParser', and 'footerParser'. Variant of the version in
1434-- Text.Pandoc.Parsing.
1463-- Text.Pandoc.Parsing.
1464+tableWith :: PandocMonad m
1435−tableWith :: MarkdownParser (F [Blocks], [Alignment], [Int])
1465+ => MarkdownParser m (F [Blocks], [Alignment], [Int])
1436− -> ([Int] -> MarkdownParser (F [Blocks]))
1466+ -> ([Int] -> MarkdownParser m (F [Blocks]))
1437− -> MarkdownParser sep
1467+ -> MarkdownParser m sep
1438− -> MarkdownParser end
1468+ -> MarkdownParser m end
1439− -> MarkdownParser ([Alignment], [Double], F [Blocks], F [[Blocks]])
1469+ -> MarkdownParser m ([Alignment], [Double], F [Blocks], F [[Blocks]])
1440tableWith headerParser rowParser lineParser footerParser = try $ do
1470tableWith headerParser rowParser lineParser footerParser = try $ do
1441 (heads, aligns, indices) <- headerParser
1471 (heads, aligns, indices) <- headerParser
1442 lines' <- fmap sequence $ rowParser indices `sepEndBy1` lineParser
1472 lines' <- fmap sequence $ rowParser indices `sepEndBy1` lineParser
@@ -1447,7 +1477,7 @@ tableWith headerParser rowParser lineParser footerParser = try $ do
1447 else widthsFromIndices numColumns indices
1477 else widthsFromIndices numColumns indices
1448 return $ (aligns, widths, heads, lines')
1478 return $ (aligns, widths, heads, lines')
1449
1479
1450−table :: MarkdownParser (F Blocks)
1480+table :: PandocMonad m => MarkdownParser m (F Blocks)
1451table = try $ do
1481table = try $ do
1452 frontCaption <- option Nothing (Just <$> tableCaption)
1482 frontCaption <- option Nothing (Just <$> tableCaption)
1453 (aligns, widths, heads, lns) <-
1483 (aligns, widths, heads, lns) <-
@@ -1479,7 +1509,7 @@ table = try $ do
1479-- inline
1509-- inline
1480--
1510--
1481
1511
1482−inline :: MarkdownParser (F Inlines)
1512+inline :: PandocMonad m => MarkdownParser m (F Inlines)
1483inline = choice [ whitespace
1513inline = choice [ whitespace
1484 , bareURL
1514 , bareURL
1485 , str
1515 , str
@@ -1509,7 +1539,7 @@ inline = choice [ whitespace
1509 , ltSign
1539 , ltSign
1510 ] <?> "inline"
1540 ] <?> "inline"
1511
1541
1512−escapedChar' :: MarkdownParser Char
1542+escapedChar' :: PandocMonad m => MarkdownParser m Char
1513escapedChar' = try $ do
1543escapedChar' = try $ do
1514 char '\\'
1544 char '\\'
1515 (guardEnabled Ext_all_symbols_escapable >> satisfy (not . isAlphaNum))
1545 (guardEnabled Ext_all_symbols_escapable >> satisfy (not . isAlphaNum))
@@ -1518,7 +1548,7 @@ escapedChar' = try $ do
1518 <|> (guardEnabled Ext_escaped_line_breaks >> char '\n')
1548 <|> (guardEnabled Ext_escaped_line_breaks >> char '\n')
1519 <|> oneOf "\\`*_{}[]()>#+-.!~\""
1549 <|> oneOf "\\`*_{}[]()>#+-.!~\""
1520
1550
1521−escapedChar :: MarkdownParser (F Inlines)
1551+escapedChar :: PandocMonad m => MarkdownParser m (F Inlines)
1522escapedChar = do
1552escapedChar = do
1523 result <- escapedChar'
1553 result <- escapedChar'
1524 case result of
1554 case result of
@@ -1527,14 +1557,14 @@ escapedChar = do
1527 return (return B.linebreak) -- "\[newline]" is a linebreak
1557 return (return B.linebreak) -- "\[newline]" is a linebreak
1528 _ -> return $ return $ B.str [result]
1558 _ -> return $ return $ B.str [result]
1529
1559
1530−ltSign :: MarkdownParser (F Inlines)
1560+ltSign :: PandocMonad m => MarkdownParser m (F Inlines)
1531ltSign = do
1561ltSign = do
1532 guardDisabled Ext_raw_html
1562 guardDisabled Ext_raw_html
1533 <|> (notFollowedByHtmlCloser >> notFollowedBy' (htmlTag isBlockTag))
1563 <|> (notFollowedByHtmlCloser >> notFollowedBy' (htmlTag isBlockTag))
1534 char '<'
1564 char '<'
1535 return $ return $ B.str "<"
1565 return $ return $ B.str "<"
1536
1566
1537−exampleRef :: MarkdownParser (F Inlines)
1567+exampleRef :: PandocMonad m => MarkdownParser m (F Inlines)
1538exampleRef = try $ do
1568exampleRef = try $ do
1539 guardEnabled Ext_example_lists
1569 guardEnabled Ext_example_lists
1540 char '@'
1570 char '@'
@@ -1545,7 +1575,7 @@ exampleRef = try $ do
1545 Just n -> B.str (show n)
1575 Just n -> B.str (show n)
1546 Nothing -> B.str ('@':lab)
1576 Nothing -> B.str ('@':lab)
1547
1577
1548−symbol :: MarkdownParser (F Inlines)
1578+symbol :: PandocMonad m => MarkdownParser m (F Inlines)
1549symbol = do
1579symbol = do
1550 result <- noneOf "<\\\n\t "
1580 result <- noneOf "<\\\n\t "
1551 <|> try (do lookAhead $ char '\\'
1581 <|> try (do lookAhead $ char '\\'
@@ -1554,7 +1584,7 @@ symbol = do
1554 return $ return $ B.str [result]
1584 return $ return $ B.str [result]
1555
1585
1556-- parses inline code, between n `s and n `s
1586-- parses inline code, between n `s and n `s
1557−code :: MarkdownParser (F Inlines)
1587+code :: PandocMonad m => MarkdownParser m (F Inlines)
1558code = try $ do
1588code = try $ do
1559 starts <- many1 (char '`')
1589 starts <- many1 (char '`')
1560 skipSpaces
1590 skipSpaces
@@ -1566,7 +1596,7 @@ code = try $ do
1566 >> attributes)
1596 >> attributes)
1567 return $ return $ B.codeWith attr $ trim $ concat result
1597 return $ return $ B.codeWith attr $ trim $ concat result
1568
1598
1569−math :: MarkdownParser (F Inlines)
1599+math :: PandocMonad m => MarkdownParser m (F Inlines)
1570math = (return . B.displayMath <$> (mathDisplay >>= applyMacros'))
1600math = (return . B.displayMath <$> (mathDisplay >>= applyMacros'))
1571 <|> (return . B.math <$> (mathInline >>= applyMacros')) <+?>
1601 <|> (return . B.math <$> (mathInline >>= applyMacros')) <+?>
1572 ((getOption readerSmart >>= guard) *> (return <$> apostrophe)
1602 ((getOption readerSmart >>= guard) *> (return <$> apostrophe)
@@ -1574,8 +1604,9 @@ math = (return . B.displayMath <$> (mathDisplay >>= applyMacros'))
1574
1604
1575-- Parses material enclosed in *s, **s, _s, or __s.
1605-- Parses material enclosed in *s, **s, _s, or __s.
1576-- Designed to avoid backtracking.
1606-- Designed to avoid backtracking.
1577−enclosure :: Char
1607+enclosure :: PandocMonad m
1608+ => Char
1578− -> MarkdownParser (F Inlines)
1609+ -> MarkdownParser m (F Inlines)
1579enclosure c = do
1610enclosure c = do
1580 -- we can't start an enclosure with _ if after a string and
1611 -- we can't start an enclosure with _ if after a string and
1581 -- the intraword_underscores extension is enabled:
1612 -- the intraword_underscores extension is enabled:
@@ -1591,7 +1622,7 @@ enclosure c = do
1591 1 -> one c mempty
1622 1 -> one c mempty
1592 _ -> return (return $ B.str cs)
1623 _ -> return (return $ B.str cs)
1593
1624
1594−ender :: Char -> Int -> MarkdownParser ()
1625+ender :: PandocMonad m => Char -> Int -> MarkdownParser m ()
1595ender c n = try $ do
1626ender c n = try $ do
1596 count n (char c)
1627 count n (char c)
1597 guard (c == '*')
1628 guard (c == '*')
@@ -1602,7 +1633,7 @@ ender c n = try $ do
1602-- If one c, emit emph and then parse two.
1633-- If one c, emit emph and then parse two.
1603-- If two cs, emit strong and then parse one.
1634-- If two cs, emit strong and then parse one.
1604-- Otherwise, emit ccc then the results.
1635-- Otherwise, emit ccc then the results.
1605−three :: Char -> MarkdownParser (F Inlines)
1636+three :: PandocMonad m => Char -> MarkdownParser m (F Inlines)
1606three c = do
1637three c = do
1607 contents <- mconcat <$> many (notFollowedBy (ender c 1) >> inline)
1638 contents <- mconcat <$> many (notFollowedBy (ender c 1) >> inline)
1608 (ender c 3 >> return ((B.strong . B.emph) <$> contents))
1639 (ender c 3 >> return ((B.strong . B.emph) <$> contents))
@@ -1612,7 +1643,7 @@ three c = do
1612
1643
1613-- Parse inlines til you hit two c's, and emit strong.
1644-- Parse inlines til you hit two c's, and emit strong.
1614-- If you never do hit two cs, emit ** plus inlines parsed.
1645-- If you never do hit two cs, emit ** plus inlines parsed.
1615−two :: Char -> F Inlines -> MarkdownParser (F Inlines)
1646+two :: PandocMonad m => Char -> F Inlines -> MarkdownParser m (F Inlines)
1616two c prefix' = do
1647two c prefix' = do
1617 contents <- mconcat <$> many (try $ notFollowedBy (ender c 2) >> inline)
1648 contents <- mconcat <$> many (try $ notFollowedBy (ender c 2) >> inline)
1618 (ender c 2 >> return (B.strong <$> (prefix' <> contents)))
1649 (ender c 2 >> return (B.strong <$> (prefix' <> contents)))
@@ -1620,7 +1651,7 @@ two c prefix' = do
1620
1651
1621-- Parse inlines til you hit a c, and emit emph.
1652-- Parse inlines til you hit a c, and emit emph.
1622-- If you never hit a c, emit * plus inlines parsed.
1653-- If you never hit a c, emit * plus inlines parsed.
1623−one :: Char -> F Inlines -> MarkdownParser (F Inlines)
1654+one :: PandocMonad m => Char -> F Inlines -> MarkdownParser m (F Inlines)
1624one c prefix' = do
1655one c prefix' = do
1625 contents <- mconcat <$> many ( (notFollowedBy (ender c 1) >> inline)
1656 contents <- mconcat <$> many ( (notFollowedBy (ender c 1) >> inline)
1626 <|> try (string [c,c] >>
1657 <|> try (string [c,c] >>
@@ -1629,47 +1660,48 @@ one c prefix' = do
1629 (ender c 1 >> return (B.emph <$> (prefix' <> contents)))
1660 (ender c 1 >> return (B.emph <$> (prefix' <> contents)))
1630 <|> return (return (B.str [c]) <> (prefix' <> contents))
1661 <|> return (return (B.str [c]) <> (prefix' <> contents))
1631
1662
1632−strongOrEmph :: MarkdownParser (F Inlines)
1663+strongOrEmph :: PandocMonad m => MarkdownParser m (F Inlines)
1633strongOrEmph = enclosure '*' <|> enclosure '_'
1664strongOrEmph = enclosure '*' <|> enclosure '_'
1634
1665
1635-- | Parses a list of inlines between start and end delimiters.
1666-- | Parses a list of inlines between start and end delimiters.
1636−inlinesBetween :: (Show b)
1667+inlinesBetween :: PandocMonad m
1668+ => (Show b)
1637− => MarkdownParser a
1669+ => MarkdownParser m a
1638− -> MarkdownParser b
1670+ -> MarkdownParser m b
1639− -> MarkdownParser (F Inlines)
1671+ -> MarkdownParser m (F Inlines)
1640inlinesBetween start end =
1672inlinesBetween start end =
1641 (trimInlinesF . mconcat) <$> try (start >> many1Till inner end)
1673 (trimInlinesF . mconcat) <$> try (start >> many1Till inner end)
1642 where inner = innerSpace <|> (notFollowedBy' (() <$ whitespace) >> inline)
1674 where inner = innerSpace <|> (notFollowedBy' (() <$ whitespace) >> inline)
1643 innerSpace = try $ whitespace <* notFollowedBy' end
1675 innerSpace = try $ whitespace <* notFollowedBy' end
1644
1676
1645−strikeout :: MarkdownParser (F Inlines)
1677+strikeout :: PandocMonad m => MarkdownParser m (F Inlines)
1646strikeout = fmap B.strikeout <$>
1678strikeout = fmap B.strikeout <$>
1647 (guardEnabled Ext_strikeout >> inlinesBetween strikeStart strikeEnd)
1679 (guardEnabled Ext_strikeout >> inlinesBetween strikeStart strikeEnd)
1648 where strikeStart = string "~~" >> lookAhead nonspaceChar
1680 where strikeStart = string "~~" >> lookAhead nonspaceChar
1649 >> notFollowedBy (char '~')
1681 >> notFollowedBy (char '~')
1650 strikeEnd = try $ string "~~"
1682 strikeEnd = try $ string "~~"
1651
1683
1652−superscript :: MarkdownParser (F Inlines)
1684+superscript :: PandocMonad m => MarkdownParser m (F Inlines)
1653superscript = fmap B.superscript <$> try (do
1685superscript = fmap B.superscript <$> try (do
1654 guardEnabled Ext_superscript
1686 guardEnabled Ext_superscript
1655 char '^'
1687 char '^'
1656 mconcat <$> many1Till (notFollowedBy spaceChar >> inline) (char '^'))
1688 mconcat <$> many1Till (notFollowedBy spaceChar >> inline) (char '^'))
1657
1689
1658−subscript :: MarkdownParser (F Inlines)
1690+subscript :: PandocMonad m => MarkdownParser m (F Inlines)
1659subscript = fmap B.subscript <$> try (do
1691subscript = fmap B.subscript <$> try (do
1660 guardEnabled Ext_subscript
1692 guardEnabled Ext_subscript
1661 char '~'
1693 char '~'
1662 mconcat <$> many1Till (notFollowedBy spaceChar >> inline) (char '~'))
1694 mconcat <$> many1Till (notFollowedBy spaceChar >> inline) (char '~'))
1663
1695
1664−whitespace :: MarkdownParser (F Inlines)
1696+whitespace :: PandocMonad m => MarkdownParser m (F Inlines)
1665whitespace = spaceChar >> return <$> (lb <|> regsp) <?> "whitespace"
1697whitespace = spaceChar >> return <$> (lb <|> regsp) <?> "whitespace"
1666 where lb = spaceChar >> skipMany spaceChar >> option B.space (endline >> return B.linebreak)
1698 where lb = spaceChar >> skipMany spaceChar >> option B.space (endline >> return B.linebreak)
1667 regsp = skipMany spaceChar >> return B.space
1699 regsp = skipMany spaceChar >> return B.space
1668
1700
1669−nonEndline :: Parser [Char] st Char
1701+nonEndline :: PandocMonad m => ParserT [Char] st m Char
1670nonEndline = satisfy (/='\n')
1702nonEndline = satisfy (/='\n')
1671
1703
1672−str :: MarkdownParser (F Inlines)
1704+str :: PandocMonad m => MarkdownParser m (F Inlines)
1673str = do
1705str = do
1674 result <- many1 alphaNum
1706 result <- many1 alphaNum
1675 updateLastStrPos
1707 updateLastStrPos
@@ -1699,7 +1731,7 @@ likelyAbbrev x =
1699 in map snd $ filter (\(y,_) -> y == x) abbrPairs
1731 in map snd $ filter (\(y,_) -> y == x) abbrPairs
1700
1732
1701-- an endline character that can be treated as a space, not a structural break
1733-- an endline character that can be treated as a space, not a structural break
1702−endline :: MarkdownParser (F Inlines)
1734+endline :: PandocMonad m => MarkdownParser m (F Inlines)
1703endline = try $ do
1735endline = try $ do
1704 newline
1736 newline
1705 notFollowedBy blankline
1737 notFollowedBy blankline
@@ -1721,17 +1753,17 @@ endline = try $ do
1721--
1753--
1722
1754
1723-- a reference label for a link
1755-- a reference label for a link
1724−reference :: MarkdownParser (F Inlines, String)
1756+reference :: PandocMonad m => MarkdownParser m (F Inlines, String)
1725reference = do notFollowedBy' (string "[^") -- footnote reference
1757reference = do notFollowedBy' (string "[^") -- footnote reference
1726 withRaw $ trimInlinesF <$> inlinesInBalancedBrackets
1758 withRaw $ trimInlinesF <$> inlinesInBalancedBrackets
1727
1759
1728−parenthesizedChars :: MarkdownParser [Char]
1760+parenthesizedChars :: PandocMonad m => MarkdownParser m [Char]
1729parenthesizedChars = do
1761parenthesizedChars = do
1730 result <- charsInBalanced '(' ')' litChar
1762 result <- charsInBalanced '(' ')' litChar
1731 return $ '(' : result ++ ")"
1763 return $ '(' : result ++ ")"
1732
1764
1733-- source for a link, with optional title
1765-- source for a link, with optional title
1734−source :: MarkdownParser (String, String)
1766+source :: PandocMonad m => MarkdownParser m (String, String)
1735source = do
1767source = do
1736 char '('
1768 char '('
1737 skipSpaces
1769 skipSpaces
@@ -1748,10 +1780,10 @@ source = do
1748 char ')'
1780 char ')'
1749 return (escapeURI $ trimr src, tit)
1781 return (escapeURI $ trimr src, tit)
1750
1782
1751−linkTitle :: MarkdownParser String
1783+linkTitle :: PandocMonad m => MarkdownParser m String
1752linkTitle = quotedTitle '"' <|> quotedTitle '\''
1784linkTitle = quotedTitle '"' <|> quotedTitle '\''
1753
1785
1754−link :: MarkdownParser (F Inlines)
1786+link :: PandocMonad m => MarkdownParser m (F Inlines)
1755link = try $ do
1787link = try $ do
1756 st <- getState
1788 st <- getState
1757 guard $ stateAllowLinks st
1789 guard $ stateAllowLinks st
@@ -1760,7 +1792,7 @@ link = try $ do
1760 setState $ st{ stateAllowLinks = True }
1792 setState $ st{ stateAllowLinks = True }
1761 regLink B.linkWith lab <|> referenceLink B.linkWith (lab,raw)
1793 regLink B.linkWith lab <|> referenceLink B.linkWith (lab,raw)
1762
1794
1763−bracketedSpan :: MarkdownParser (F Inlines)
1795+bracketedSpan :: PandocMonad m => MarkdownParser m (F Inlines)
1764bracketedSpan = try $ do
1796bracketedSpan = try $ do
1765 guardEnabled Ext_bracketed_spans
1797 guardEnabled Ext_bracketed_spans
1766 (lab,_) <- reference
1798 (lab,_) <- reference
@@ -1773,8 +1805,10 @@ bracketedSpan = try $ do
1773 -> return $ B.smallcaps <$> lab
1805 -> return $ B.smallcaps <$> lab
1774 _ -> return $ B.spanWith attr <$> lab
1806 _ -> return $ B.spanWith attr <$> lab
1775
1807
1808+regLink :: PandocMonad m
1776−regLink :: (Attr -> String -> String -> Inlines -> Inlines)
1809+ => (Attr -> String -> String -> Inlines -> Inlines)
1810+ -> F Inlines
1777− -> F Inlines -> MarkdownParser (F Inlines)
1811+ -> MarkdownParser m (F Inlines)
1778regLink constructor lab = try $ do
1812regLink constructor lab = try $ do
1779 (src, tit) <- source
1813 (src, tit) <- source
1780 attr <- option nullAttr $
1814 attr <- option nullAttr $
@@ -1782,8 +1816,10 @@ regLink constructor lab = try $ do
1782 return $ constructor attr src tit <$> lab
1816 return $ constructor attr src tit <$> lab
1783
1817
1784-- a link like [this][ref] or [this][] or [this]
1818-- a link like [this][ref] or [this][] or [this]
1819+referenceLink :: PandocMonad m
1785−referenceLink :: (Attr -> String -> String -> Inlines -> Inlines)
1820+ => (Attr -> String -> String -> Inlines -> Inlines)
1821+ -> (F Inlines, String)
1786− -> (F Inlines, String) -> MarkdownParser (F Inlines)
1822+ -> MarkdownParser m (F Inlines)
1787referenceLink constructor (lab, raw) = do
1823referenceLink constructor (lab, raw) = do
1788 sp <- (True <$ lookAhead (char ' ')) <|> return False
1824 sp <- (True <$ lookAhead (char ' ')) <|> return False
1789 (_,raw') <- option (mempty, "") $
1825 (_,raw') <- option (mempty, "") $
@@ -1824,7 +1860,7 @@ dropBrackets = reverse . dropRB . reverse . dropLB
1824 dropLB ('[':xs) = xs
1860 dropLB ('[':xs) = xs
1825 dropLB xs = xs
1861 dropLB xs = xs
1826
1862
1827−bareURL :: MarkdownParser (F Inlines)
1863+bareURL :: PandocMonad m => MarkdownParser m (F Inlines)
1828bareURL = try $ do
1864bareURL = try $ do
1829 guardEnabled Ext_autolink_bare_uris
1865 guardEnabled Ext_autolink_bare_uris
1830 getState >>= guard . stateAllowLinks
1866 getState >>= guard . stateAllowLinks
@@ -1832,7 +1868,7 @@ bareURL = try $ do
1832 notFollowedBy $ try $ spaces >> htmlTag (~== TagClose "a")
1868 notFollowedBy $ try $ spaces >> htmlTag (~== TagClose "a")
1833 return $ return $ B.link src "" (B.str orig)
1869 return $ return $ B.link src "" (B.str orig)
1834
1870
1835−autoLink :: MarkdownParser (F Inlines)
1871+autoLink :: PandocMonad m => MarkdownParser m (F Inlines)
1836autoLink = try $ do
1872autoLink = try $ do
1837 getState >>= guard . stateAllowLinks
1873 getState >>= guard . stateAllowLinks
1838 char '<'
1874 char '<'
@@ -1846,7 +1882,7 @@ autoLink = try $ do
1846 guardEnabled Ext_link_attributes >> attributes
1882 guardEnabled Ext_link_attributes >> attributes
1847 return $ return $ B.linkWith attr (src ++ escapeURI extra) "" (B.str $ orig ++ extra)
1883 return $ return $ B.linkWith attr (src ++ escapeURI extra) "" (B.str $ orig ++ extra)
1848
1884
1849−image :: MarkdownParser (F Inlines)
1885+image :: PandocMonad m => MarkdownParser m (F Inlines)
1850image = try $ do
1886image = try $ do
1851 char '!'
1887 char '!'
1852 (lab,raw) <- reference
1888 (lab,raw) <- reference
@@ -1856,7 +1892,7 @@ image = try $ do
1856 _ -> B.imageWith attr' src
1892 _ -> B.imageWith attr' src
1857 regLink constructor lab <|> referenceLink constructor (lab,raw)
1893 regLink constructor lab <|> referenceLink constructor (lab,raw)
1858
1894
1859−note :: MarkdownParser (F Inlines)
1895+note :: PandocMonad m => MarkdownParser m (F Inlines)
1860note = try $ do
1896note = try $ do
1861 guardEnabled Ext_footnotes
1897 guardEnabled Ext_footnotes
1862 ref <- noteMarker
1898 ref <- noteMarker
@@ -1872,14 +1908,14 @@ note = try $ do
1872 let contents' = runF contents st{ stateNotes' = [] }
1908 let contents' = runF contents st{ stateNotes' = [] }
1873 return $ B.note contents'
1909 return $ B.note contents'
1874
1910
1875−inlineNote :: MarkdownParser (F Inlines)
1911+inlineNote :: PandocMonad m => MarkdownParser m (F Inlines)
1876inlineNote = try $ do
1912inlineNote = try $ do
1877 guardEnabled Ext_inline_notes
1913 guardEnabled Ext_inline_notes
1878 char '^'
1914 char '^'
1879 contents <- inlinesInBalancedBrackets
1915 contents <- inlinesInBalancedBrackets
1880 return $ B.note . B.para <$> contents
1916 return $ B.note . B.para <$> contents
1881
1917
1882−rawLaTeXInline' :: MarkdownParser (F Inlines)
1918+rawLaTeXInline' :: PandocMonad m => MarkdownParser m (F Inlines)
1883rawLaTeXInline' = try $ do
1919rawLaTeXInline' = try $ do
1884 guardEnabled Ext_raw_tex
1920 guardEnabled Ext_raw_tex
1885 lookAhead $ char '\\' >> notFollowedBy' (string "start") -- context env
1921 lookAhead $ char '\\' >> notFollowedBy' (string "start") -- context env
@@ -1887,7 +1923,7 @@ rawLaTeXInline' = try $ do
1887 return $ return $ B.rawInline "tex" s
1923 return $ return $ B.rawInline "tex" s
1888 -- "tex" because it might be context or latex
1924 -- "tex" because it might be context or latex
1889
1925
1890−rawConTeXtEnvironment :: Parser [Char] st String
1926+rawConTeXtEnvironment :: PandocMonad m => ParserT [Char] st m String
1891rawConTeXtEnvironment = try $ do
1927rawConTeXtEnvironment = try $ do
1892 string "\\start"
1928 string "\\start"
1893 completion <- inBrackets (letter <|> digit <|> spaceChar)
1929 completion <- inBrackets (letter <|> digit <|> spaceChar)
@@ -1896,14 +1932,14 @@ rawConTeXtEnvironment = try $ do
1896 (try $ string "\\stop" >> string completion)
1932 (try $ string "\\stop" >> string completion)
1897 return $ "\\start" ++ completion ++ concat contents ++ "\\stop" ++ completion
1933 return $ "\\start" ++ completion ++ concat contents ++ "\\stop" ++ completion
1898
1934
1899−inBrackets :: (Parser [Char] st Char) -> Parser [Char] st String
1935+inBrackets :: PandocMonad m => (ParserT [Char] st m Char) -> ParserT [Char] st m String
1900inBrackets parser = do
1936inBrackets parser = do
1901 char '['
1937 char '['
1902 contents <- many parser
1938 contents <- many parser
1903 char ']'
1939 char ']'
1904 return $ "[" ++ contents ++ "]"
1940 return $ "[" ++ contents ++ "]"
1905
1941
1906−spanHtml :: MarkdownParser (F Inlines)
1942+spanHtml :: PandocMonad m => MarkdownParser m (F Inlines)
1907spanHtml = try $ do
1943spanHtml = try $ do
1908 guardEnabled Ext_native_spans
1944 guardEnabled Ext_native_spans
1909 (TagOpen _ attrs, _) <- htmlTag (~== TagOpen "span" [])
1945 (TagOpen _ attrs, _) <- htmlTag (~== TagOpen "span" [])
@@ -1918,7 +1954,7 @@ spanHtml = try $ do
1918 -> return $ B.smallcaps <$> contents
1954 -> return $ B.smallcaps <$> contents
1919 _ -> return $ B.spanWith (ident, classes, keyvals) <$> contents
1955 _ -> return $ B.spanWith (ident, classes, keyvals) <$> contents
1920
1956
1921−divHtml :: MarkdownParser (F Blocks)
1957+divHtml :: PandocMonad m => MarkdownParser m (F Blocks)
1922divHtml = try $ do
1958divHtml = try $ do
1923 guardEnabled Ext_native_divs
1959 guardEnabled Ext_native_divs
1924 (TagOpen _ attrs, rawtag) <- htmlTag (~== TagOpen "div" [])
1960 (TagOpen _ attrs, rawtag) <- htmlTag (~== TagOpen "div" [])
@@ -1940,7 +1976,7 @@ divHtml = try $ do
1940 else -- avoid backtracing
1976 else -- avoid backtracing
1941 return $ return (B.rawBlock "html" (rawtag <> bls)) <> contents
1977 return $ return (B.rawBlock "html" (rawtag <> bls)) <> contents
1942
1978
1943−rawHtmlInline :: MarkdownParser (F Inlines)
1979+rawHtmlInline :: PandocMonad m => MarkdownParser m (F Inlines)
1944rawHtmlInline = do
1980rawHtmlInline = do
1945 guardEnabled Ext_raw_html
1981 guardEnabled Ext_raw_html
1946 inHtmlBlock <- stateInHtmlBlock <$> getState
1982 inHtmlBlock <- stateInHtmlBlock <$> getState
@@ -1962,7 +1998,7 @@ rawHtmlInline = do
1962emojiChars :: [Char]
1998emojiChars :: [Char]
1963emojiChars = ['a'..'z'] ++ ['0'..'9'] ++ ['_','+','-']
1999emojiChars = ['a'..'z'] ++ ['0'..'9'] ++ ['_','+','-']
1964
2000
1965−emoji :: MarkdownParser (F Inlines)
2001+emoji :: PandocMonad m => MarkdownParser m (F Inlines)
1966emoji = try $ do
2002emoji = try $ do
1967 guardEnabled Ext_emoji
2003 guardEnabled Ext_emoji
1968 char ':'
2004 char ':'
@@ -1974,7 +2010,7 @@ emoji = try $ do
1974
2010
1975-- Citations
2011-- Citations
1976
2012
1977−cite :: MarkdownParser (F Inlines)
2013+cite :: PandocMonad m => MarkdownParser m (F Inlines)
1978cite = do
2014cite = do
1979 guardEnabled Ext_citations
2015 guardEnabled Ext_citations
1980 citations <- textualCite
2016 citations <- textualCite
@@ -1982,7 +2018,7 @@ cite = do
1982 return $ (flip B.cite (B.text raw)) <$> cs
2018 return $ (flip B.cite (B.text raw)) <$> cs
1983 return citations
2019 return citations
1984
2020
1985−textualCite :: MarkdownParser (F Inlines)
2021+textualCite :: PandocMonad m => MarkdownParser m (F Inlines)
1986textualCite = try $ do
2022textualCite = try $ do
1987 (_, key) <- citeKey
2023 (_, key) <- citeKey
1988 let first = Citation{ citationId = key
2024 let first = Citation{ citationId = key
@@ -2017,7 +2053,7 @@ textualCite = try $ do
2017 Just n -> B.str (show n)
2053 Just n -> B.str (show n)
2018 _ -> B.cite [first] $ B.str $ '@':key)
2054 _ -> B.cite [first] $ B.str $ '@':key)
2019
2055
2020−bareloc :: Citation -> MarkdownParser (F [Citation])
2056+bareloc :: PandocMonad m => Citation -> MarkdownParser m (F [Citation])
2021bareloc c = try $ do
2057bareloc c = try $ do
2022 spnl
2058 spnl
2023 char '['
2059 char '['
@@ -2032,7 +2068,7 @@ bareloc c = try $ do
2032 rest' <- rest
2068 rest' <- rest
2033 return $ c{ citationSuffix = B.toList suff' } : rest'
2069 return $ c{ citationSuffix = B.toList suff' } : rest'
2034
2070
2035−normalCite :: MarkdownParser (F [Citation])
2071+normalCite :: PandocMonad m => MarkdownParser m (F [Citation])
2036normalCite = try $ do
2072normalCite = try $ do
2037 char '['
2073 char '['
2038 spnl
2074 spnl
@@ -2041,7 +2077,7 @@ normalCite = try $ do
2041 char ']'
2077 char ']'
2042 return citations
2078 return citations
2043
2079
2044−suffix :: MarkdownParser (F Inlines)
2080+suffix :: PandocMonad m => MarkdownParser m (F Inlines)
2045suffix = try $ do
2081suffix = try $ do
2046 hasSpace <- option False (notFollowedBy nonspaceChar >> return True)
2082 hasSpace <- option False (notFollowedBy nonspaceChar >> return True)
2047 spnl
2083 spnl
@@ -2050,14 +2086,14 @@ suffix = try $ do
2050 then (B.space <>) <$> rest
2086 then (B.space <>) <$> rest
2051 else rest
2087 else rest
2052
2088
2053−prefix :: MarkdownParser (F Inlines)
2089+prefix :: PandocMonad m => MarkdownParser m (F Inlines)
2054prefix = trimInlinesF . mconcat <$>
2090prefix = trimInlinesF . mconcat <$>
2055 manyTill inline (char ']' <|> liftM (const ']') (lookAhead citeKey))
2091 manyTill inline (char ']' <|> liftM (const ']') (lookAhead citeKey))
2056
2092
2057−citeList :: MarkdownParser (F [Citation])
2093+citeList :: PandocMonad m => MarkdownParser m (F [Citation])
2058citeList = fmap sequence $ sepBy1 citation (try $ char ';' >> spnl)
2094citeList = fmap sequence $ sepBy1 citation (try $ char ';' >> spnl)
2059
2095
2060−citation :: MarkdownParser (F Citation)
2096+citation :: PandocMonad m => MarkdownParser m (F Citation)
2061citation = try $ do
2097citation = try $ do
2062 pref <- prefix
2098 pref <- prefix
2063 (suppress_author, key) <- citeKey
2099 (suppress_author, key) <- citeKey
@@ -2075,13 +2111,13 @@ citation = try $ do
2075 , citationHash = 0
2111 , citationHash = 0
2076 }
2112 }
2077
2113
2078−smart :: MarkdownParser (F Inlines)
2114+smart :: PandocMonad m => MarkdownParser m (F Inlines)
2079smart = do
2115smart = do
2080 getOption readerSmart >>= guard
2116 getOption readerSmart >>= guard
2081 doubleQuoted <|> singleQuoted <|>
2117 doubleQuoted <|> singleQuoted <|>
2082 choice (map (return <$>) [apostrophe, dash, ellipses])
2118 choice (map (return <$>) [apostrophe, dash, ellipses])
2083
2119
2084−singleQuoted :: MarkdownParser (F Inlines)
2120+singleQuoted :: PandocMonad m => MarkdownParser m (F Inlines)
2085singleQuoted = try $ do
2121singleQuoted = try $ do
2086 singleQuoteStart
2122 singleQuoteStart
2087 withQuoteContext InSingleQuote $
2123 withQuoteContext InSingleQuote $
@@ -2091,7 +2127,7 @@ singleQuoted = try $ do
2091-- doubleQuoted will handle regular double-quoted sections, as well
2127-- doubleQuoted will handle regular double-quoted sections, as well
2092-- as dialogues with an open double-quote without a close double-quote
2128-- as dialogues with an open double-quote without a close double-quote
2093-- in the same paragraph.
2129-- in the same paragraph.
2094−doubleQuoted :: MarkdownParser (F Inlines)
2130+doubleQuoted :: PandocMonad m => MarkdownParser m (F Inlines)
2095doubleQuoted = try $ do
2131doubleQuoted = try $ do
2096 doubleQuoteStart
2132 doubleQuoteStart
2097 contents <- mconcat <$> many (try $ notFollowedBy doubleQuoteEnd >> inline)
2133 contents <- mconcat <$> many (try $ notFollowedBy doubleQuoteEnd >> inline)
src/Text/Pandoc/Readers/MediaWiki.hs+75−71
@@ -57,22 +57,26 @@ import Data.Char (isDigit, isSpace)
57import Data.Maybe (fromMaybe)
57import Data.Maybe (fromMaybe)
58import Text.Printf (printf)
58import Text.Printf (printf)
59import Debug.Trace (trace)
59import Debug.Trace (trace)
60−
60+import Control.Monad.Except (throwError)
61−import Text.Pandoc.Error
61+import Text.Pandoc.Class (PandocMonad, PandocExecutionError(..))
62
62
63-- | Read mediawiki from an input string and return a Pandoc document.
63-- | Read mediawiki from an input string and return a Pandoc document.
64+readMediaWiki :: PandocMonad m
64−readMediaWiki :: ReaderOptions -- ^ Reader options
65+ => ReaderOptions -- ^ Reader options
65 -> String -- ^ String to parse (assuming @'\n'@ line endings)
66 -> String -- ^ String to parse (assuming @'\n'@ line endings)
66− -> Either PandocError Pandoc
67+ -> m Pandoc
67−readMediaWiki opts s =
68+readMediaWiki opts s = do
68− readWith parseMediaWiki MWState{ mwOptions = opts
69+ parsed <- readWithM parseMediaWiki MWState{ mwOptions = opts
69− , mwMaxNestingLevel = 4
70+ , mwMaxNestingLevel = 4
70− , mwNextLinkNumber = 1
71+ , mwNextLinkNumber = 1
71− , mwCategoryLinks = []
72+ , mwCategoryLinks = []
72− , mwHeaderMap = M.empty
73+ , mwHeaderMap = M.empty
73− , mwIdentifierList = Set.empty
74+ , mwIdentifierList = Set.empty
74− }
75+ }
75− (s ++ "\n")
76+ (s ++ "\n")
77+ case parsed of
78+ Right result -> return result
79+ Left _ -> throwError $ PandocParseError "problem parsing mediawiki"
76
80
77data MWState = MWState { mwOptions :: ReaderOptions
81data MWState = MWState { mwOptions :: ReaderOptions
78 , mwMaxNestingLevel :: Int
82 , mwMaxNestingLevel :: Int
@@ -82,7 +86,7 @@ data MWState = MWState { mwOptions :: ReaderOptions
82 , mwIdentifierList :: Set.Set String
86 , mwIdentifierList :: Set.Set String
83 }
87 }
84
88
85−type MWParser = Parser [Char] MWState
89+type MWParser m = ParserT [Char] MWState m
86
90
87instance HasReaderOptions MWState where
91instance HasReaderOptions MWState where
88 extractReaderOptions = mwOptions
92 extractReaderOptions = mwOptions
@@ -101,7 +105,7 @@ instance HasIdentifierList MWState where
101
105
102-- This is used to prevent exponential blowups for things like:
106-- This is used to prevent exponential blowups for things like:
103-- ''a'''a''a'''a''a'''a''a'''a
107-- ''a'''a''a'''a''a'''a''a'''a
104−nested :: MWParser a -> MWParser a
108+nested :: PandocMonad m => MWParser m a -> MWParser m a
105nested p = do
109nested p = do
106 nestlevel <- mwMaxNestingLevel `fmap` getState
110 nestlevel <- mwMaxNestingLevel `fmap` getState
107 guard $ nestlevel > 0
111 guard $ nestlevel > 0
@@ -116,7 +120,7 @@ specialChars = "'[]<=&*{}|\":\\"
116spaceChars :: [Char]
120spaceChars :: [Char]
117spaceChars = " \n\t"
121spaceChars = " \n\t"
118
122
119−sym :: String -> MWParser ()
123+sym :: PandocMonad m => String -> MWParser m ()
120sym s = () <$ try (string s)
124sym s = () <$ try (string s)
121
125
122newBlockTags :: [String]
126newBlockTags :: [String]
@@ -137,10 +141,10 @@ eitherBlockOrInline :: [String]
137eitherBlockOrInline = ["applet", "button", "del", "iframe", "ins",
141eitherBlockOrInline = ["applet", "button", "del", "iframe", "ins",
138 "map", "area", "object"]
142 "map", "area", "object"]
139
143
140−htmlComment :: MWParser ()
144+htmlComment :: PandocMonad m => MWParser m ()
141htmlComment = () <$ htmlTag isCommentTag
145htmlComment = () <$ htmlTag isCommentTag
142
146
143−inlinesInTags :: String -> MWParser Inlines
147+inlinesInTags :: PandocMonad m => String -> MWParser m Inlines
144inlinesInTags tag = try $ do
148inlinesInTags tag = try $ do
145 (_,raw) <- htmlTag (~== TagOpen tag [])
149 (_,raw) <- htmlTag (~== TagOpen tag [])
146 if '/' `elem` raw -- self-closing tag
150 if '/' `elem` raw -- self-closing tag
@@ -148,7 +152,7 @@ inlinesInTags tag = try $ do
148 else trimInlines . mconcat <$>
152 else trimInlines . mconcat <$>
149 manyTill inline (htmlTag (~== TagClose tag))
153 manyTill inline (htmlTag (~== TagClose tag))
150
154
151−blocksInTags :: String -> MWParser Blocks
155+blocksInTags :: PandocMonad m => String -> MWParser m Blocks
152blocksInTags tag = try $ do
156blocksInTags tag = try $ do
153 (_,raw) <- htmlTag (~== TagOpen tag [])
157 (_,raw) <- htmlTag (~== TagOpen tag [])
154 let closer = if tag == "li"
158 let closer = if tag == "li"
@@ -162,7 +166,7 @@ blocksInTags tag = try $ do
162 then return mempty
166 then return mempty
163 else mconcat <$> manyTill block closer
167 else mconcat <$> manyTill block closer
164
168
165−charsInTags :: String -> MWParser [Char]
169+charsInTags :: PandocMonad m => String -> MWParser m [Char]
166charsInTags tag = try $ do
170charsInTags tag = try $ do
167 (_,raw) <- htmlTag (~== TagOpen tag [])
171 (_,raw) <- htmlTag (~== TagOpen tag [])
168 if '/' `elem` raw -- self-closing tag
172 if '/' `elem` raw -- self-closing tag
@@ -173,7 +177,7 @@ charsInTags tag = try $ do
173-- main parser
177-- main parser
174--
178--
175
179
176−parseMediaWiki :: MWParser Pandoc
180+parseMediaWiki :: PandocMonad m => MWParser m Pandoc
177parseMediaWiki = do
181parseMediaWiki = do
178 bs <- mconcat <$> many block
182 bs <- mconcat <$> many block
179 spaces
183 spaces
@@ -188,7 +192,7 @@ parseMediaWiki = do
188-- block parsers
192-- block parsers
189--
193--
190
194
191−block :: MWParser Blocks
195+block :: PandocMonad m => MWParser m Blocks
192block = do
196block = do
193 tr <- getOption readerTrace
197 tr <- getOption readerTrace
194 pos <- getPosition
198 pos <- getPosition
@@ -209,14 +213,14 @@ block = do
209 (take 60 $ show $ B.toList res)) (return ())
213 (take 60 $ show $ B.toList res)) (return ())
210 return res
214 return res
211
215
212−para :: MWParser Blocks
216+para :: PandocMonad m => MWParser m Blocks
213para = do
217para = do
214 contents <- trimInlines . mconcat <$> many1 inline
218 contents <- trimInlines . mconcat <$> many1 inline
215 if F.all (==Space) contents
219 if F.all (==Space) contents
216 then return mempty
220 then return mempty
217 else return $ B.para contents
221 else return $ B.para contents
218
222
219−table :: MWParser Blocks
223+table :: PandocMonad m => MWParser m Blocks
220table = do
224table = do
221 tableStart
225 tableStart
222 styles <- option [] parseAttrs <* blankline
226 styles <- option [] parseAttrs <* blankline
@@ -244,10 +248,10 @@ table = do
244 else (replicate cols mempty, hdr:rows')
248 else (replicate cols mempty, hdr:rows')
245 return $ B.table caption cellspecs headers rows
249 return $ B.table caption cellspecs headers rows
246
250
247−parseAttrs :: MWParser [(String,String)]
251+parseAttrs :: PandocMonad m => MWParser m [(String,String)]
248parseAttrs = many1 parseAttr
252parseAttrs = many1 parseAttr
249
253
250−parseAttr :: MWParser (String, String)
254+parseAttr :: PandocMonad m => MWParser m (String, String)
251parseAttr = try $ do
255parseAttr = try $ do
252 skipMany spaceChar
256 skipMany spaceChar
253 k <- many1 letter
257 k <- many1 letter
@@ -256,17 +260,17 @@ parseAttr = try $ do
256 <|> many1 (satisfy $ \c -> not (isSpace c) && c /= '|')
260 <|> many1 (satisfy $ \c -> not (isSpace c) && c /= '|')
257 return (k,v)
261 return (k,v)
258
262
259−tableStart :: MWParser ()
263+tableStart :: PandocMonad m => MWParser m ()
260tableStart = try $ guardColumnOne *> skipSpaces *> sym "{|"
264tableStart = try $ guardColumnOne *> skipSpaces *> sym "{|"
261
265
262−tableEnd :: MWParser ()
266+tableEnd :: PandocMonad m => MWParser m ()
263tableEnd = try $ guardColumnOne *> skipSpaces *> sym "|}"
267tableEnd = try $ guardColumnOne *> skipSpaces *> sym "|}"
264
268
265−rowsep :: MWParser ()
269+rowsep :: PandocMonad m => MWParser m ()
266rowsep = try $ guardColumnOne *> skipSpaces *> sym "|-" <*
270rowsep = try $ guardColumnOne *> skipSpaces *> sym "|-" <*
267 optional parseAttr <* blanklines
271 optional parseAttr <* blanklines
268
272
269−cellsep :: MWParser ()
273+cellsep :: PandocMonad m => MWParser m ()
270cellsep = try $
274cellsep = try $
271 (guardColumnOne *> skipSpaces <*
275 (guardColumnOne *> skipSpaces <*
272 ( (char '|' <* notFollowedBy (oneOf "-}+"))
276 ( (char '|' <* notFollowedBy (oneOf "-}+"))
@@ -276,7 +280,7 @@ cellsep = try $
276 <|> (() <$ try (string "||"))
280 <|> (() <$ try (string "||"))
277 <|> (() <$ try (string "!!"))
281 <|> (() <$ try (string "!!"))
278
282
279−tableCaption :: MWParser Inlines
283+tableCaption :: PandocMonad m => MWParser m Inlines
280tableCaption = try $ do
284tableCaption = try $ do
281 guardColumnOne
285 guardColumnOne
282 skipSpaces
286 skipSpaces
@@ -284,10 +288,10 @@ tableCaption = try $ do
284 optional (try $ parseAttr *> skipSpaces *> char '|' *> skipSpaces)
288 optional (try $ parseAttr *> skipSpaces *> char '|' *> skipSpaces)
285 (trimInlines . mconcat) <$> many (notFollowedBy (cellsep <|> rowsep) *> inline)
289 (trimInlines . mconcat) <$> many (notFollowedBy (cellsep <|> rowsep) *> inline)
286
290
287−tableRow :: MWParser [((Alignment, Double), Blocks)]
291+tableRow :: PandocMonad m => MWParser m [((Alignment, Double), Blocks)]
288tableRow = try $ skipMany htmlComment *> many tableCell
292tableRow = try $ skipMany htmlComment *> many tableCell
289
293
290−tableCell :: MWParser ((Alignment, Double), Blocks)
294+tableCell :: PandocMonad m => MWParser m ((Alignment, Double), Blocks)
291tableCell = try $ do
295tableCell = try $ do
292 cellsep
296 cellsep
293 skipMany spaceChar
297 skipMany spaceChar
@@ -313,7 +317,7 @@ parseWidth s =
313 ('%':ds) | all isDigit ds -> safeRead ('0':'.':reverse ds)
317 ('%':ds) | all isDigit ds -> safeRead ('0':'.':reverse ds)
314 _ -> Nothing
318 _ -> Nothing
315
319
316−template :: MWParser String
320+template :: PandocMonad m => MWParser m String
317template = try $ do
321template = try $ do
318 string "{{"
322 string "{{"
319 notFollowedBy (char '{')
323 notFollowedBy (char '{')
@@ -322,7 +326,7 @@ template = try $ do
322 contents <- manyTill chunk (try $ string "}}")
326 contents <- manyTill chunk (try $ string "}}")
323 return $ "{{" ++ concat contents ++ "}}"
327 return $ "{{" ++ concat contents ++ "}}"
324
328
325−blockTag :: MWParser Blocks
329+blockTag :: PandocMonad m => MWParser m Blocks
326blockTag = do
330blockTag = do
327 (tag, _) <- lookAhead $ htmlTag isBlockTag'
331 (tag, _) <- lookAhead $ htmlTag isBlockTag'
328 case tag of
332 case tag of
@@ -341,7 +345,7 @@ trimCode :: String -> String
341trimCode ('\n':xs) = stripTrailingNewlines xs
345trimCode ('\n':xs) = stripTrailingNewlines xs
342trimCode xs = stripTrailingNewlines xs
346trimCode xs = stripTrailingNewlines xs
343
347
344−syntaxhighlight :: String -> [Attribute String] -> MWParser Blocks
348+syntaxhighlight :: PandocMonad m => String -> [Attribute String] -> MWParser m Blocks
345syntaxhighlight tag attrs = try $ do
349syntaxhighlight tag attrs = try $ do
346 let mblang = lookup "lang" attrs
350 let mblang = lookup "lang" attrs
347 let mbstart = lookup "start" attrs
351 let mbstart = lookup "start" attrs
@@ -351,13 +355,13 @@ syntaxhighlight tag attrs = try $ do
351 contents <- charsInTags tag
355 contents <- charsInTags tag
352 return $ B.codeBlockWith ("",classes,kvs) $ trimCode contents
356 return $ B.codeBlockWith ("",classes,kvs) $ trimCode contents
353
357
354−hrule :: MWParser Blocks
358+hrule :: PandocMonad m => MWParser m Blocks
355hrule = B.horizontalRule <$ try (string "----" *> many (char '-') *> newline)
359hrule = B.horizontalRule <$ try (string "----" *> many (char '-') *> newline)
356
360
357−guardColumnOne :: MWParser ()
361+guardColumnOne :: PandocMonad m => MWParser m ()
358guardColumnOne = getPosition >>= \pos -> guard (sourceColumn pos == 1)
362guardColumnOne = getPosition >>= \pos -> guard (sourceColumn pos == 1)
359
363
360−preformatted :: MWParser Blocks
364+preformatted :: PandocMonad m => MWParser m Blocks
361preformatted = try $ do
365preformatted = try $ do
362 guardColumnOne
366 guardColumnOne
363 char ' '
367 char ' '
@@ -388,7 +392,7 @@ encode = B.fromList . normalizeCode . B.toList . walk strToCode
388 normalizeCode $ (Code a1 (x ++ y)) : zs
392 normalizeCode $ (Code a1 (x ++ y)) : zs
389 normalizeCode (x:xs) = x : normalizeCode xs
393 normalizeCode (x:xs) = x : normalizeCode xs
390
394
391−header :: MWParser Blocks
395+header :: PandocMonad m => MWParser m Blocks
392header = try $ do
396header = try $ do
393 guardColumnOne
397 guardColumnOne
394 eqs <- many1 (char '=')
398 eqs <- many1 (char '=')
@@ -398,13 +402,13 @@ header = try $ do
398 attr <- registerHeader nullAttr contents
402 attr <- registerHeader nullAttr contents
399 return $ B.headerWith attr lev contents
403 return $ B.headerWith attr lev contents
400
404
401−bulletList :: MWParser Blocks
405+bulletList :: PandocMonad m => MWParser m Blocks
402bulletList = B.bulletList <$>
406bulletList = B.bulletList <$>
403 ( many1 (listItem '*')
407 ( many1 (listItem '*')
404 <|> (htmlTag (~== TagOpen "ul" []) *> spaces *> many (listItem '*' <|> li) <*
408 <|> (htmlTag (~== TagOpen "ul" []) *> spaces *> many (listItem '*' <|> li) <*
405 optional (htmlTag (~== TagClose "ul"))) )
409 optional (htmlTag (~== TagClose "ul"))) )
406
410
407−orderedList :: MWParser Blocks
411+orderedList :: PandocMonad m => MWParser m Blocks
408orderedList =
412orderedList =
409 (B.orderedList <$> many1 (listItem '#'))
413 (B.orderedList <$> many1 (listItem '#'))
410 <|> try
414 <|> try
@@ -415,10 +419,10 @@ orderedList =
415 let start = fromMaybe 1 $ safeRead $ fromAttrib "start" tag
419 let start = fromMaybe 1 $ safeRead $ fromAttrib "start" tag
416 return $ B.orderedListWith (start, DefaultStyle, DefaultDelim) items)
420 return $ B.orderedListWith (start, DefaultStyle, DefaultDelim) items)
417
421
418−definitionList :: MWParser Blocks
422+definitionList :: PandocMonad m => MWParser m Blocks
419definitionList = B.definitionList <$> many1 defListItem
423definitionList = B.definitionList <$> many1 defListItem
420
424
421−defListItem :: MWParser (Inlines, [Blocks])
425+defListItem :: PandocMonad m => MWParser m (Inlines, [Blocks])
422defListItem = try $ do
426defListItem = try $ do
423 terms <- mconcat . intersperse B.linebreak <$> many defListTerm
427 terms <- mconcat . intersperse B.linebreak <$> many defListTerm
424 -- we allow dd with no dt, or dt with no dd
428 -- we allow dd with no dt, or dt with no dd
@@ -429,27 +433,27 @@ defListItem = try $ do
429 else many (listItem ':')
433 else many (listItem ':')
430 return (terms, defs)
434 return (terms, defs)
431
435
432−defListTerm :: MWParser Inlines
436+defListTerm :: PandocMonad m => MWParser m Inlines
433defListTerm = char ';' >> skipMany spaceChar >> anyLine >>=
437defListTerm = char ';' >> skipMany spaceChar >> anyLine >>=
434 parseFromString (trimInlines . mconcat <$> many inline)
438 parseFromString (trimInlines . mconcat <$> many inline)
435
439
436−listStart :: Char -> MWParser ()
440+listStart :: PandocMonad m => Char -> MWParser m ()
437listStart c = char c *> notFollowedBy listStartChar
441listStart c = char c *> notFollowedBy listStartChar
438
442
439−listStartChar :: MWParser Char
443+listStartChar :: PandocMonad m => MWParser m Char
440listStartChar = oneOf "*#;:"
444listStartChar = oneOf "*#;:"
441
445
442−anyListStart :: MWParser Char
446+anyListStart :: PandocMonad m => MWParser m Char
443anyListStart = char '*'
447anyListStart = char '*'
444 <|> char '#'
448 <|> char '#'
445 <|> char ':'
449 <|> char ':'
446 <|> char ';'
450 <|> char ';'
447
451
448−li :: MWParser Blocks
452+li :: PandocMonad m => MWParser m Blocks
449li = lookAhead (htmlTag (~== TagOpen "li" [])) *>
453li = lookAhead (htmlTag (~== TagOpen "li" [])) *>
450 (firstParaToPlain <$> blocksInTags "li") <* spaces
454 (firstParaToPlain <$> blocksInTags "li") <* spaces
451
455
452−listItem :: Char -> MWParser Blocks
456+listItem :: PandocMonad m => Char -> MWParser m Blocks
453listItem c = try $ do
457listItem c = try $ do
454 extras <- many (try $ char c <* lookAhead listStartChar)
458 extras <- many (try $ char c <* lookAhead listStartChar)
455 if null extras
459 if null extras
@@ -475,10 +479,10 @@ listItem c = try $ do
475-- }}
479-- }}
476-- * next list item
480-- * next list item
477-- which seems to be valid mediawiki.
481-- which seems to be valid mediawiki.
478−listChunk :: MWParser String
482+listChunk :: PandocMonad m => MWParser m String
479listChunk = template <|> count 1 anyChar
483listChunk = template <|> count 1 anyChar
480
484
481−listItem' :: Char -> MWParser Blocks
485+listItem' :: PandocMonad m => Char -> MWParser m Blocks
482listItem' c = try $ do
486listItem' c = try $ do
483 listStart c
487 listStart c
484 skipMany spaceChar
488 skipMany spaceChar
@@ -498,7 +502,7 @@ firstParaToPlain contents =
498-- inline parsers
502-- inline parsers
499--
503--
500
504
501−inline :: MWParser Inlines
505+inline :: PandocMonad m => MWParser m Inlines
502inline = whitespace
506inline = whitespace
503 <|> url
507 <|> url
504 <|> str
508 <|> str
@@ -516,10 +520,10 @@ inline = whitespace
516 <|> (B.rawInline "mediawiki" <$> template)
520 <|> (B.rawInline "mediawiki" <$> template)
517 <|> special
521 <|> special
518
522
519−str :: MWParser Inlines
523+str :: PandocMonad m => MWParser m Inlines
520str = B.str <$> many1 (noneOf $ specialChars ++ spaceChars)
524str = B.str <$> many1 (noneOf $ specialChars ++ spaceChars)
521
525
522−math :: MWParser Inlines
526+math :: PandocMonad m => MWParser m Inlines
523math = (B.displayMath . trim <$> try (many1 (char ':') >> charsInTags "math"))
527math = (B.displayMath . trim <$> try (many1 (char ':') >> charsInTags "math"))
524 <|> (B.math . trim <$> charsInTags "math")
528 <|> (B.math . trim <$> charsInTags "math")
525 <|> (B.displayMath . trim <$> try (dmStart *> manyTill anyChar dmEnd))
529 <|> (B.displayMath . trim <$> try (dmStart *> manyTill anyChar dmEnd))
@@ -529,13 +533,13 @@ math = (B.displayMath . trim <$> try (many1 (char ':') >> charsInTags "math"))
529 mStart = string "\\("
533 mStart = string "\\("
530 mEnd = try (string "\\)")
534 mEnd = try (string "\\)")
531
535
532−variable :: MWParser String
536+variable :: PandocMonad m => MWParser m String
533variable = try $ do
537variable = try $ do
534 string "{{{"
538 string "{{{"
535 contents <- manyTill anyChar (try $ string "}}}")
539 contents <- manyTill anyChar (try $ string "}}}")
536 return $ "{{{" ++ contents ++ "}}}"
540 return $ "{{{" ++ contents ++ "}}}"
537
541
538−inlineTag :: MWParser Inlines
542+inlineTag :: PandocMonad m => MWParser m Inlines
539inlineTag = do
543inlineTag = do
540 (tag, _) <- lookAhead $ htmlTag isInlineTag'
544 (tag, _) <- lookAhead $ htmlTag isInlineTag'
541 case tag of
545 case tag of
@@ -557,18 +561,18 @@ inlineTag = do
557 TagOpen "hask" _ -> B.codeWith ("",["haskell"],[]) <$> charsInTags "hask"
561 TagOpen "hask" _ -> B.codeWith ("",["haskell"],[]) <$> charsInTags "hask"
558 _ -> B.rawInline "html" . snd <$> htmlTag (~== tag)
562 _ -> B.rawInline "html" . snd <$> htmlTag (~== tag)
559
563
560−special :: MWParser Inlines
564+special :: PandocMonad m => MWParser m Inlines
561special = B.str <$> count 1 (notFollowedBy' (htmlTag isBlockTag') *>
565special = B.str <$> count 1 (notFollowedBy' (htmlTag isBlockTag') *>
562 oneOf specialChars)
566 oneOf specialChars)
563
567
564−inlineHtml :: MWParser Inlines
568+inlineHtml :: PandocMonad m => MWParser m Inlines
565inlineHtml = B.rawInline "html" . snd <$> htmlTag isInlineTag'
569inlineHtml = B.rawInline "html" . snd <$> htmlTag isInlineTag'
566
570
567−whitespace :: MWParser Inlines
571+whitespace :: PandocMonad m => MWParser m Inlines
568whitespace = B.space <$ (skipMany1 spaceChar <|> htmlComment)
572whitespace = B.space <$ (skipMany1 spaceChar <|> htmlComment)
569 <|> B.softbreak <$ endline
573 <|> B.softbreak <$ endline
570
574
571−endline :: MWParser ()
575+endline :: PandocMonad m => MWParser m ()
572endline = () <$ try (newline <*
576endline = () <$ try (newline <*
573 notFollowedBy spaceChar <*
577 notFollowedBy spaceChar <*
574 notFollowedBy newline <*
578 notFollowedBy newline <*
@@ -577,12 +581,12 @@ endline = () <$ try (newline <*
577 notFollowedBy' header <*
581 notFollowedBy' header <*
578 notFollowedBy anyListStart)
582 notFollowedBy anyListStart)
579
583
580−imageIdentifiers :: [MWParser ()]
584+imageIdentifiers :: PandocMonad m => [MWParser m ()]
581imageIdentifiers = [sym (identifier ++ ":") | identifier <- identifiers]
585imageIdentifiers = [sym (identifier ++ ":") | identifier <- identifiers]
582 where identifiers = ["File", "Image", "Archivo", "Datei", "Fichier",
586 where identifiers = ["File", "Image", "Archivo", "Datei", "Fichier",
583 "Bild"]
587 "Bild"]
584
588
585−image :: MWParser Inlines
589+image :: PandocMonad m => MWParser m Inlines
586image = try $ do
590image = try $ do
587 sym "[["
591 sym "[["
588 choice imageIdentifiers
592 choice imageIdentifiers
@@ -600,7 +604,7 @@ image = try $ do
600 <|> try (char '|' *> (mconcat <$> manyTill inline (sym "]]")))
604 <|> try (char '|' *> (mconcat <$> manyTill inline (sym "]]")))
601 return $ B.imageWith attr fname ("fig:" ++ stringify caption) caption
605 return $ B.imageWith attr fname ("fig:" ++ stringify caption) caption
602
606
603−imageOption :: MWParser String
607+imageOption :: PandocMonad m => MWParser m String
604imageOption = try $ char '|' *> opt
608imageOption = try $ char '|' *> opt
605 where
609 where
606 opt = try (oneOfStrings [ "border", "thumbnail", "frameless"
610 opt = try (oneOfStrings [ "border", "thumbnail", "frameless"
@@ -619,7 +623,7 @@ collapseUnderscores (x:xs) = x : collapseUnderscores xs
619addUnderscores :: String -> String
623addUnderscores :: String -> String
620addUnderscores = collapseUnderscores . intercalate "_" . words
624addUnderscores = collapseUnderscores . intercalate "_" . words
621
625
622−internalLink :: MWParser Inlines
626+internalLink :: PandocMonad m => MWParser m Inlines
623internalLink = try $ do
627internalLink = try $ do
624 sym "[["
628 sym "[["
625 pagename <- unwords . words <$> many (noneOf "|]")
629 pagename <- unwords . words <$> many (noneOf "|]")
@@ -637,7 +641,7 @@ internalLink = try $ do
637 return mempty
641 return mempty
638 else return link
642 else return link
639
643
640−externalLink :: MWParser Inlines
644+externalLink :: PandocMonad m => MWParser m Inlines
641externalLink = try $ do
645externalLink = try $ do
642 char '['
646 char '['
643 (_, src) <- uri
647 (_, src) <- uri
@@ -649,29 +653,29 @@ externalLink = try $ do
649 return $ B.str $ show num
653 return $ B.str $ show num
650 return $ B.link src "" lab
654 return $ B.link src "" lab
651
655
652−url :: MWParser Inlines
656+url :: PandocMonad m => MWParser m Inlines
653url = do
657url = do
654 (orig, src) <- uri
658 (orig, src) <- uri
655 return $ B.link src "" (B.str orig)
659 return $ B.link src "" (B.str orig)
656
660
657-- | Parses a list of inlines between start and end delimiters.
661-- | Parses a list of inlines between start and end delimiters.
658−inlinesBetween :: (Show b) => MWParser a -> MWParser b -> MWParser Inlines
662+inlinesBetween :: (PandocMonad m, Show b) => MWParser m a -> MWParser m b -> MWParser m Inlines
659inlinesBetween start end =
663inlinesBetween start end =
660 (trimInlines . mconcat) <$> try (start >> many1Till inner end)
664 (trimInlines . mconcat) <$> try (start >> many1Till inner end)
661 where inner = innerSpace <|> (notFollowedBy' (() <$ whitespace) >> inline)
665 where inner = innerSpace <|> (notFollowedBy' (() <$ whitespace) >> inline)
662 innerSpace = try $ whitespace <* notFollowedBy' end
666 innerSpace = try $ whitespace <* notFollowedBy' end
663
667
664−emph :: MWParser Inlines
668+emph :: PandocMonad m => MWParser m Inlines
665emph = B.emph <$> nested (inlinesBetween start end)
669emph = B.emph <$> nested (inlinesBetween start end)
666 where start = sym "''" >> lookAhead nonspaceChar
670 where start = sym "''" >> lookAhead nonspaceChar
667 end = try $ notFollowedBy' (() <$ strong) >> sym "''"
671 end = try $ notFollowedBy' (() <$ strong) >> sym "''"
668
672
669−strong :: MWParser Inlines
673+strong :: PandocMonad m => MWParser m Inlines
670strong = B.strong <$> nested (inlinesBetween start end)
674strong = B.strong <$> nested (inlinesBetween start end)
671 where start = sym "'''" >> lookAhead nonspaceChar
675 where start = sym "'''" >> lookAhead nonspaceChar
672 end = try $ sym "'''"
676 end = try $ sym "'''"
673
677
674−doubleQuotes :: MWParser Inlines
678+doubleQuotes :: PandocMonad m => MWParser m Inlines
675doubleQuotes = B.doubleQuoted <$> nested (inlinesBetween openDoubleQuote closeDoubleQuote)
679doubleQuotes = B.doubleQuoted <$> nested (inlinesBetween openDoubleQuote closeDoubleQuote)
676 where openDoubleQuote = sym "\"" >> lookAhead nonspaceChar
680 where openDoubleQuote = sym "\"" >> lookAhead nonspaceChar
677 closeDoubleQuote = try $ sym "\""
681 closeDoubleQuote = try $ sym "\""
src/Text/Pandoc/Readers/Native.hs+5−2
@@ -33,6 +33,7 @@ module Text.Pandoc.Readers.Native ( readNative ) where
33import Text.Pandoc.Definition
33import Text.Pandoc.Definition
34import Text.Pandoc.Shared (safeRead)
34import Text.Pandoc.Shared (safeRead)
35
35
36+import Control.Monad.Except (throwError)
36import Text.Pandoc.Error
37import Text.Pandoc.Error
37import Text.Pandoc.Class
38import Text.Pandoc.Class
38
39
@@ -48,9 +49,11 @@ import Text.Pandoc.Class
48--
49--
49readNative :: PandocMonad m
50readNative :: PandocMonad m
50 => String -- ^ String to parse (assuming @'\n'@ line endings)
51 => String -- ^ String to parse (assuming @'\n'@ line endings)
51− -> m (Either PandocError Pandoc)
52+ -> m Pandoc
52readNative s =
53readNative s =
53− return $ maybe (Pandoc nullMeta <$> readBlocks s) Right (safeRead s)
54+ case maybe (Pandoc nullMeta <$> readBlocks s) Right (safeRead s) of
55+ Right doc -> return doc
56+ Left _ -> throwError $ PandocParseError "couldn't read native"
54
57
55readBlocks :: String -> Either PandocError [Block]
58readBlocks :: String -> Either PandocError [Block]
56readBlocks s = maybe ((:[]) <$> readBlock s) Right (safeRead s)
59readBlocks s = maybe ((:[]) <$> readBlock s) Right (safeRead s)
src/Text/Pandoc/Readers/OPML.hs+20−16
@@ -13,8 +13,9 @@ import Control.Monad.State
13import Data.Default
13import Data.Default
14import Control.Monad.Except
14import Control.Monad.Except
15import Text.Pandoc.Error
15import Text.Pandoc.Error
16+import Text.Pandoc.Class (PandocMonad, PandocExecutionError(..))
16
17
17−type OPML = ExceptT PandocError (State OPMLState)
18+type OPML m = StateT OPMLState m
18
19
19data OPMLState = OPMLState{
20data OPMLState = OPMLState{
20 opmlSectionLevel :: Int
21 opmlSectionLevel :: Int
@@ -30,12 +31,14 @@ instance Default OPMLState where
30 , opmlDocDate = mempty
31 , opmlDocDate = mempty
31 }
32 }
32
33
33−readOPML :: ReaderOptions -> String -> Either PandocError Pandoc
34+readOPML :: PandocMonad m => ReaderOptions -> String -> m Pandoc
35+readOPML _ inp = do
36+ (bs, st') <- flip runStateT def (mapM parseBlock $ normalizeTree $ parseXML inp)
37+ return $
34−readOPML _ inp = setTitle (opmlDocTitle st')
38+ setTitle (opmlDocTitle st') $
35− . setAuthors (opmlDocAuthors st')
39+ setAuthors (opmlDocAuthors st') $
36− . setDate (opmlDocDate st')
40+ setDate (opmlDocDate st') $
37− . doc . mconcat <$> bs
41+ doc $ mconcat bs
38− where (bs, st') = flip runState def . runExceptT $ (mapM parseBlock $ normalizeTree $ parseXML inp)
39
42
40-- normalize input, consolidating adjacent Text and CRef elements
43-- normalize input, consolidating adjacent Text and CRef elements
41normalizeTree :: [Content] -> [Content]
44normalizeTree :: [Content] -> [Content]
@@ -62,21 +65,22 @@ attrValue attr elt =
62 Just z -> z
65 Just z -> z
63 Nothing -> ""
66 Nothing -> ""
64
67
65−exceptT :: Either PandocError a -> OPML a
68+-- exceptT :: PandocMonad m => Either PandocExecutionError a -> OPML m a
66−exceptT = either throwError return
69+-- exceptT = either throwError return
67
70
68−asHtml :: String -> OPML Inlines
71+asHtml :: PandocMonad m => String -> OPML m Inlines
72+asHtml s =
69−asHtml s = (\(Pandoc _ bs) -> case bs of
73+ (\(Pandoc _ bs) -> case bs of
70 [Plain ils] -> fromList ils
74 [Plain ils] -> fromList ils
71− _ -> mempty) <$> exceptT (readHtml def s)
75+ _ -> mempty) <$> (lift $ readHtml def s)
72
76
73−asMarkdown :: String -> OPML Blocks
77+asMarkdown :: PandocMonad m => String -> OPML m Blocks
74−asMarkdown s = (\(Pandoc _ bs) -> fromList bs) <$> exceptT (readMarkdown def s)
78+asMarkdown s = (\(Pandoc _ bs) -> fromList bs) <$> (lift $ readMarkdown def s)
75
79
76−getBlocks :: Element -> OPML Blocks
80+getBlocks :: PandocMonad m => Element -> OPML m Blocks
77getBlocks e = mconcat <$> (mapM parseBlock $ elContent e)
81getBlocks e = mconcat <$> (mapM parseBlock $ elContent e)
78
82
79−parseBlock :: Content -> OPML Blocks
83+parseBlock :: PandocMonad m => Content -> OPML m Blocks
80parseBlock (Elem e) =
84parseBlock (Elem e) =
81 case qName (elName e) of
85 case qName (elName e) of
82 "ownerName" -> mempty <$ modify (\st ->
86 "ownerName" -> mempty <$ modify (\st ->
src/Text/Pandoc/Readers/Odt.hs+18−4
@@ -39,6 +39,10 @@ import qualified Data.ByteString.Lazy as B
39
39
40import System.FilePath
40import System.FilePath
41
41
42+import Control.Monad.Except (throwError)
43+
44+import Text.Pandoc.Class (PandocMonad, PandocExecutionError(..))
45+import qualified Text.Pandoc.Class as P
42import Text.Pandoc.Definition
46import Text.Pandoc.Definition
43import Text.Pandoc.Error
47import Text.Pandoc.Error
44import Text.Pandoc.Options
48import Text.Pandoc.Options
@@ -52,11 +56,21 @@ import Text.Pandoc.Readers.Odt.Generic.XMLConverter
52import Text.Pandoc.Readers.Odt.Generic.Fallible
56import Text.Pandoc.Readers.Odt.Generic.Fallible
53import Text.Pandoc.Shared (filteredFilesFromArchive)
57import Text.Pandoc.Shared (filteredFilesFromArchive)
54
58
55−--
59+readOdt :: PandocMonad m
56−readOdt :: ReaderOptions
60+ => ReaderOptions
57 -> B.ByteString
61 -> B.ByteString
62+ -> m Pandoc
63+readOdt opts bytes = case readOdt' opts bytes of
64+ Right (doc, mb) -> do
65+ P.setMediaBag mb
66+ return doc
67+ Left _ -> throwError $ PandocParseError "couldn't parse odt"
68+
69+--
70+readOdt' :: ReaderOptions
71+ -> B.ByteString
58− -> Either PandocError (Pandoc, MediaBag)
72+ -> Either PandocError (Pandoc, MediaBag)
59−readOdt _ bytes = bytesToOdt bytes-- of
73+readOdt' _ bytes = bytesToOdt bytes-- of
60-- Right (pandoc, mediaBag) -> Right (pandoc , mediaBag)
74-- Right (pandoc, mediaBag) -> Right (pandoc , mediaBag)
61-- Left err -> Left err
75-- Left err -> Left err
62
76
src/Text/Pandoc/Readers/Org.hs+13−7
@@ -31,24 +31,30 @@ import Text.Pandoc.Readers.Org.Blocks ( blockList, meta )
31import Text.Pandoc.Readers.Org.Parsing ( OrgParser, readWithM )
31import Text.Pandoc.Readers.Org.Parsing ( OrgParser, readWithM )
32import Text.Pandoc.Readers.Org.ParserState ( optionsToParserState )
32import Text.Pandoc.Readers.Org.ParserState ( optionsToParserState )
33
33
34+import Text.Pandoc.Class (PandocMonad, PandocExecutionError(..))
34import Text.Pandoc.Definition
35import Text.Pandoc.Definition
35−import Text.Pandoc.Error
36import Text.Pandoc.Options
36import Text.Pandoc.Options
37
37
38−import Control.Monad.Reader ( runReader )
38+import Control.Monad.Except ( throwError )
39+import Control.Monad.Reader ( runReaderT )
39
40
40
41
41-- | Parse org-mode string and return a Pandoc document.
42-- | Parse org-mode string and return a Pandoc document.
43+readOrg :: PandocMonad m
42−readOrg :: ReaderOptions -- ^ Reader options
44+ => ReaderOptions -- ^ Reader options
43 -> String -- ^ String to parse (assuming @'\n'@ line endings)
45 -> String -- ^ String to parse (assuming @'\n'@ line endings)
44− -> Either PandocError Pandoc
46+ -> m Pandoc
45−readOrg opts s = flip runReader def $
47+readOrg opts s = do
48+ parsed <- flip runReaderT def $
46− readWithM parseOrg (optionsToParserState opts) (s ++ "\n\n")
49+ readWithM parseOrg (optionsToParserState opts) (s ++ "\n\n")
50+ case parsed of
51+ Right result -> return result
52+ Left _ -> throwError $ PandocParseError "problem parsing org"
47
53
48--
54--
49-- Parser
55-- Parser
50--
56--
51−parseOrg :: OrgParser Pandoc
57+parseOrg :: PandocMonad m => OrgParser m Pandoc
52parseOrg = do
58parseOrg = do
53 blocks' <- blockList
59 blocks' <- blockList
54 meta' <- meta
60 meta' <- meta
src/Text/Pandoc/Readers/Org/BlockStarts.hs+17−16
@@ -44,7 +44,7 @@ import Control.Monad ( void )
44import Text.Pandoc.Readers.Org.Parsing
44import Text.Pandoc.Readers.Org.Parsing
45
45
46-- | Horizontal Line (five -- dashes or more)
46-- | Horizontal Line (five -- dashes or more)
47−hline :: OrgParser ()
47+hline :: Monad m => OrgParser m ()
48hline = try $ do
48hline = try $ do
49 skipSpaces
49 skipSpaces
50 string "-----"
50 string "-----"
@@ -54,58 +54,59 @@ hline = try $ do
54 return ()
54 return ()
55
55
56-- | Read the start of a header line, return the header level
56-- | Read the start of a header line, return the header level
57−headerStart :: OrgParser Int
57+headerStart :: Monad m => OrgParser m Int
58headerStart = try $
58headerStart = try $
59 (length <$> many1 (char '*')) <* many1 (char ' ') <* updateLastPreCharPos
59 (length <$> many1 (char '*')) <* many1 (char ' ') <* updateLastPreCharPos
60
60
61−tableStart :: OrgParser Char
61+tableStart :: Monad m => OrgParser m Char
62tableStart = try $ skipSpaces *> char '|'
62tableStart = try $ skipSpaces *> char '|'
63
63
64−latexEnvStart :: OrgParser String
64+latexEnvStart :: Monad m => OrgParser m String
65latexEnvStart = try $ do
65latexEnvStart = try $ do
66 skipSpaces *> string "\\begin{"
66 skipSpaces *> string "\\begin{"
67 *> latexEnvName
67 *> latexEnvName
68 <* string "}"
68 <* string "}"
69 <* blankline
69 <* blankline
70 where
70 where
71− latexEnvName :: OrgParser String
71+ latexEnvName :: Monad m => OrgParser m String
72 latexEnvName = try $ mappend <$> many1 alphaNum <*> option "" (string "*")
72 latexEnvName = try $ mappend <$> many1 alphaNum <*> option "" (string "*")
73
73
74
74
75-- | Parses bullet list marker.
75-- | Parses bullet list marker.
76−bulletListStart :: OrgParser ()
76+bulletListStart :: Monad m => OrgParser m ()
77bulletListStart = try $
77bulletListStart = try $
78 choice
78 choice
79 [ () <$ skipSpaces <* oneOf "+-" <* skipSpaces1
79 [ () <$ skipSpaces <* oneOf "+-" <* skipSpaces1
80 , () <$ skipSpaces1 <* char '*' <* skipSpaces1
80 , () <$ skipSpaces1 <* char '*' <* skipSpaces1
81 ]
81 ]
82
82
83+genericListStart :: Monad m
83−genericListStart :: OrgParser String
84+ => OrgParser m String
84− -> OrgParser Int
85+ -> OrgParser m Int
85genericListStart listMarker = try $
86genericListStart listMarker = try $
86 (+) <$> (length <$> many spaceChar)
87 (+) <$> (length <$> many spaceChar)
87 <*> (length <$> listMarker <* many1 spaceChar)
88 <*> (length <$> listMarker <* many1 spaceChar)
88
89
89−orderedListStart :: OrgParser Int
90+orderedListStart :: Monad m => OrgParser m Int
90orderedListStart = genericListStart orderedListMarker
91orderedListStart = genericListStart orderedListMarker
91 -- Ordered list markers allowed in org-mode
92 -- Ordered list markers allowed in org-mode
92 where orderedListMarker = mappend <$> many1 digit <*> (pure <$> oneOf ".)")
93 where orderedListMarker = mappend <$> many1 digit <*> (pure <$> oneOf ".)")
93
94
94−drawerStart :: OrgParser String
95+drawerStart :: Monad m => OrgParser m String
95drawerStart = try $
96drawerStart = try $
96 skipSpaces *> drawerName <* skipSpaces <* newline
97 skipSpaces *> drawerName <* skipSpaces <* newline
97 where drawerName = char ':' *> manyTill nonspaceChar (char ':')
98 where drawerName = char ':' *> manyTill nonspaceChar (char ':')
98
99
99−metaLineStart :: OrgParser ()
100+metaLineStart :: Monad m => OrgParser m ()
100metaLineStart = try $ skipSpaces <* string "#+"
101metaLineStart = try $ skipSpaces <* string "#+"
101
102
102−commentLineStart :: OrgParser ()
103+commentLineStart :: Monad m => OrgParser m ()
103commentLineStart = try $ skipSpaces <* string "# "
104commentLineStart = try $ skipSpaces <* string "# "
104
105
105−exampleLineStart :: OrgParser ()
106+exampleLineStart :: Monad m => OrgParser m ()
106exampleLineStart = () <$ try (skipSpaces *> string ": ")
107exampleLineStart = () <$ try (skipSpaces *> string ": ")
107
108
108−noteMarker :: OrgParser String
109+noteMarker :: Monad m => OrgParser m String
109noteMarker = try $ do
110noteMarker = try $ do
110 char '['
111 char '['
111 choice [ many1Till digit (char ']')
112 choice [ many1Till digit (char ']')
@@ -114,12 +115,12 @@ noteMarker = try $ do
114 ]
115 ]
115
116
116-- | Succeeds if the parser is at the end of a block.
117-- | Succeeds if the parser is at the end of a block.
117−endOfBlock :: OrgParser ()
118+endOfBlock :: Monad m => OrgParser m ()
118endOfBlock = lookAhead . try $ do
119endOfBlock = lookAhead . try $ do
119 void blankline <|> anyBlockStart
120 void blankline <|> anyBlockStart
120 where
121 where
121 -- Succeeds if there is a new block starting at this position.
122 -- Succeeds if there is a new block starting at this position.
122− anyBlockStart :: OrgParser ()
123+ anyBlockStart :: Monad m => OrgParser m ()
123 anyBlockStart = try . choice $
124 anyBlockStart = try . choice $
124 [ exampleLineStart
125 [ exampleLineStart
125 , hline
126 , hline
src/Text/Pandoc/Readers/Org/Blocks.hs+83−80
@@ -44,6 +44,7 @@ import Text.Pandoc.Readers.Org.Shared
44
44
45import qualified Text.Pandoc.Builder as B
45import qualified Text.Pandoc.Builder as B
46import Text.Pandoc.Builder ( Inlines, Blocks )
46import Text.Pandoc.Builder ( Inlines, Blocks )
47+import Text.Pandoc.Class (PandocMonad)
47import Text.Pandoc.Definition
48import Text.Pandoc.Definition
48import Text.Pandoc.Options
49import Text.Pandoc.Options
49import Text.Pandoc.Shared ( compactify', compactify'DL, safeRead )
50import Text.Pandoc.Shared ( compactify', compactify'DL, safeRead )
@@ -105,7 +106,7 @@ data Headline = Headline
105
106
106-- | Read an Org mode headline and its contents (i.e. a document subtree).
107-- | Read an Org mode headline and its contents (i.e. a document subtree).
107-- @lvl@ gives the minimum acceptable level of the tree.
108-- @lvl@ gives the minimum acceptable level of the tree.
108−headline :: Int -> OrgParser (F Headline)
109+headline :: PandocMonad m => Int -> OrgParser m (F Headline)
109headline lvl = try $ do
110headline lvl = try $ do
110 level <- headerStart
111 level <- headerStart
111 guard (lvl <= level)
112 guard (lvl <= level)
@@ -130,16 +131,16 @@ headline lvl = try $ do
130 , headlineChildren = children'
131 , headlineChildren = children'
131 }
132 }
132 where
133 where
133− endOfTitle :: OrgParser ()
134+ endOfTitle :: Monad m => OrgParser m ()
134 endOfTitle = void . lookAhead $ optional headerTags *> newline
135 endOfTitle = void . lookAhead $ optional headerTags *> newline
135
136
136− headerTags :: OrgParser [Tag]
137+ headerTags :: Monad m => OrgParser m [Tag]
137 headerTags = try $
138 headerTags = try $
138 let tag = many1 (alphaNum <|> oneOf "@%#_") <* char ':'
139 let tag = many1 (alphaNum <|> oneOf "@%#_") <* char ':'
139 in map toTag <$> (skipSpaces *> char ':' *> many1 tag <* skipSpaces)
140 in map toTag <$> (skipSpaces *> char ':' *> many1 tag <* skipSpaces)
140
141
141-- | Convert an Org mode headline (i.e. a document tree) into pandoc's Blocks
142-- | Convert an Org mode headline (i.e. a document tree) into pandoc's Blocks
142−headlineToBlocks :: Headline -> OrgParser Blocks
143+headlineToBlocks :: Monad m => Headline -> OrgParser m Blocks
143headlineToBlocks hdln@(Headline {..}) = do
144headlineToBlocks hdln@(Headline {..}) = do
144 maxHeadlineLevels <- getExportSetting exportHeadlineLevels
145 maxHeadlineLevels <- getExportSetting exportHeadlineLevels
145 case () of
146 case () of
@@ -162,7 +163,7 @@ isCommentTitle :: Inlines -> Bool
162isCommentTitle (B.toList -> (Str "COMMENT":_)) = True
163isCommentTitle (B.toList -> (Str "COMMENT":_)) = True
163isCommentTitle _ = False
164isCommentTitle _ = False
164
165
165−archivedHeadlineToBlocks :: Headline -> OrgParser Blocks
166+archivedHeadlineToBlocks :: Monad m => Headline -> OrgParser m Blocks
166archivedHeadlineToBlocks hdln = do
167archivedHeadlineToBlocks hdln = do
167 archivedTreesOption <- getExportSetting exportArchivedTrees
168 archivedTreesOption <- getExportSetting exportArchivedTrees
168 case archivedTreesOption of
169 case archivedTreesOption of
@@ -170,7 +171,7 @@ archivedHeadlineToBlocks hdln = do
170 ArchivedTreesExport -> headlineToHeaderWithContents hdln
171 ArchivedTreesExport -> headlineToHeaderWithContents hdln
171 ArchivedTreesHeadlineOnly -> headlineToHeader hdln
172 ArchivedTreesHeadlineOnly -> headlineToHeader hdln
172
173
173−headlineToHeaderWithList :: Headline -> OrgParser Blocks
174+headlineToHeaderWithList :: Monad m => Headline -> OrgParser m Blocks
174headlineToHeaderWithList hdln@(Headline {..}) = do
175headlineToHeaderWithList hdln@(Headline {..}) = do
175 maxHeadlineLevels <- getExportSetting exportHeadlineLevels
176 maxHeadlineLevels <- getExportSetting exportHeadlineLevels
176 header <- headlineToHeader hdln
177 header <- headlineToHeader hdln
@@ -189,13 +190,13 @@ headlineToHeaderWithList hdln@(Headline {..}) = do
189 (Header _ _ inlns:_) -> B.para (B.fromList inlns)
190 (Header _ _ inlns:_) -> B.para (B.fromList inlns)
190 _ -> mempty
191 _ -> mempty
191
192
192−headlineToHeaderWithContents :: Headline -> OrgParser Blocks
193+headlineToHeaderWithContents :: Monad m => Headline -> OrgParser m Blocks
193headlineToHeaderWithContents hdln@(Headline {..}) = do
194headlineToHeaderWithContents hdln@(Headline {..}) = do
194 header <- headlineToHeader hdln
195 header <- headlineToHeader hdln
195 childrenBlocks <- mconcat <$> sequence (map headlineToBlocks headlineChildren)
196 childrenBlocks <- mconcat <$> sequence (map headlineToBlocks headlineChildren)
196 return $ header <> headlineContents <> childrenBlocks
197 return $ header <> headlineContents <> childrenBlocks
197
198
198−headlineToHeader :: Headline -> OrgParser Blocks
199+headlineToHeader :: Monad m => Headline -> OrgParser m Blocks
199headlineToHeader (Headline {..}) = do
200headlineToHeader (Headline {..}) = do
200 exportTodoKeyword <- getExportSetting exportWithTodoKeywords
201 exportTodoKeyword <- getExportSetting exportWithTodoKeywords
201 let todoText = if exportTodoKeyword
202 let todoText = if exportTodoKeyword
@@ -208,7 +209,7 @@ headlineToHeader (Headline {..}) = do
208 attr <- registerHeader propAttr headlineText
209 attr <- registerHeader propAttr headlineText
209 return $ B.headerWith attr headlineLevel text
210 return $ B.headerWith attr headlineLevel text
210
211
211−todoKeyword :: OrgParser TodoMarker
212+todoKeyword :: Monad m => OrgParser m TodoMarker
212todoKeyword = try $ do
213todoKeyword = try $ do
213 taskStates <- activeTodoMarkers <$> getState
214 taskStates <- activeTodoMarkers <$> getState
214 let kwParser tdm = try $ (tdm <$ string (todoMarkerName tdm) <* spaceChar)
215 let kwParser tdm = try $ (tdm <$ string (todoMarkerName tdm) <* spaceChar)
@@ -250,7 +251,7 @@ tagToInline t = B.spanWith ("", ["tag"], [("data-tag-name", fromTag t)]) mempty
250--
251--
251
252
252-- | Get a list of blocks.
253-- | Get a list of blocks.
253−blockList :: OrgParser [Block]
254+blockList :: PandocMonad m => OrgParser m [Block]
254blockList = do
255blockList = do
255 initialBlocks <- blocks
256 initialBlocks <- blocks
256 headlines <- sequence <$> manyTill (headline 1) eof
257 headlines <- sequence <$> manyTill (headline 1) eof
@@ -259,15 +260,15 @@ blockList = do
259 return . B.toList $ (runF initialBlocks st) <> headlineBlocks
260 return . B.toList $ (runF initialBlocks st) <> headlineBlocks
260
261
261-- | Get the meta information safed in the state.
262-- | Get the meta information safed in the state.
262−meta :: OrgParser Meta
263+meta :: Monad m => OrgParser m Meta
263meta = do
264meta = do
264 meta' <- metaExport
265 meta' <- metaExport
265 runF meta' <$> getState
266 runF meta' <$> getState
266
267
267−blocks :: OrgParser (F Blocks)
268+blocks :: PandocMonad m => OrgParser m (F Blocks)
268blocks = mconcat <$> manyTill block (void (lookAhead headerStart) <|> eof)
269blocks = mconcat <$> manyTill block (void (lookAhead headerStart) <|> eof)
269
270
270−block :: OrgParser (F Blocks)
271+block :: PandocMonad m => OrgParser m (F Blocks)
271block = choice [ mempty <$ blanklines
272block = choice [ mempty <$ blanklines
272 , table
273 , table
273 , orgBlock
274 , orgBlock
@@ -306,7 +307,7 @@ attrFromBlockAttributes (BlockAttributes{..}) =
306 kv = filter ((`notElem` ["id", "class"]) . fst) blockAttrKeyValues
307 kv = filter ((`notElem` ["id", "class"]) . fst) blockAttrKeyValues
307 in (ident, classes, kv)
308 in (ident, classes, kv)
308
309
309−stringyMetaAttribute :: (String -> Bool) -> OrgParser (String, String)
310+stringyMetaAttribute :: Monad m => (String -> Bool) -> OrgParser m (String, String)
310stringyMetaAttribute attrCheck = try $ do
311stringyMetaAttribute attrCheck = try $ do
311 metaLineStart
312 metaLineStart
312 attrName <- map toUpper <$> many1Till nonspaceChar (char ':')
313 attrName <- map toUpper <$> many1Till nonspaceChar (char ':')
@@ -315,7 +316,7 @@ stringyMetaAttribute attrCheck = try $ do
315 attrValue <- anyLine
316 attrValue <- anyLine
316 return (attrName, attrValue)
317 return (attrName, attrValue)
317
318
318−blockAttributes :: OrgParser BlockAttributes
319+blockAttributes :: PandocMonad m => OrgParser m BlockAttributes
319blockAttributes = try $ do
320blockAttributes = try $ do
320 kv <- many (stringyMetaAttribute attrCheck)
321 kv <- many (stringyMetaAttribute attrCheck)
321 let caption = foldl' (appendValues "CAPTION") Nothing kv
322 let caption = foldl' (appendValues "CAPTION") Nothing kv
@@ -350,17 +351,17 @@ blockAttributes = try $ do
350 Just acc -> Just $ acc ++ ' ':value
351 Just acc -> Just $ acc ++ ' ':value
351 Nothing -> Just value
352 Nothing -> Just value
352
353
353−keyValues :: OrgParser [(String, String)]
354+keyValues :: Monad m => OrgParser m [(String, String)]
354keyValues = try $
355keyValues = try $
355 manyTill ((,) <$> key <*> value) newline
356 manyTill ((,) <$> key <*> value) newline
356 where
357 where
357− key :: OrgParser String
358+ key :: Monad m => OrgParser m String
358 key = try $ skipSpaces *> char ':' *> many1 nonspaceChar
359 key = try $ skipSpaces *> char ':' *> many1 nonspaceChar
359
360
360− value :: OrgParser String
361+ value :: Monad m => OrgParser m String
361 value = skipSpaces *> manyTill anyChar endOfValue
362 value = skipSpaces *> manyTill anyChar endOfValue
362
363
363− endOfValue :: OrgParser ()
364+ endOfValue :: Monad m => OrgParser m ()
364 endOfValue =
365 endOfValue =
365 lookAhead $ (() <$ try (many1 spaceChar <* key))
366 lookAhead $ (() <$ try (many1 spaceChar <* key))
366 <|> () <$ newline
367 <|> () <$ newline
@@ -371,7 +372,7 @@ keyValues = try $
371--
372--
372
373
373-- | Read an org-mode block delimited by #+BEGIN_TYPE and #+END_TYPE.
374-- | Read an org-mode block delimited by #+BEGIN_TYPE and #+END_TYPE.
374−orgBlock :: OrgParser (F Blocks)
375+orgBlock :: PandocMonad m => OrgParser m (F Blocks)
375orgBlock = try $ do
376orgBlock = try $ do
376 blockAttrs <- blockAttributes
377 blockAttrs <- blockAttributes
377 blkType <- blockHeaderStart
378 blkType <- blockHeaderStart
@@ -390,25 +391,25 @@ orgBlock = try $ do
390 let (ident, classes, kv) = attrFromBlockAttributes blockAttrs
391 let (ident, classes, kv) = attrFromBlockAttributes blockAttrs
391 in fmap $ B.divWith (ident, classes ++ [blkType], kv)
392 in fmap $ B.divWith (ident, classes ++ [blkType], kv)
392 where
393 where
393− blockHeaderStart :: OrgParser String
394+ blockHeaderStart :: Monad m => OrgParser m String
394 blockHeaderStart = try $ skipSpaces *> stringAnyCase "#+begin_" *> orgArgWord
395 blockHeaderStart = try $ skipSpaces *> stringAnyCase "#+begin_" *> orgArgWord
395
396
396 lowercase :: String -> String
397 lowercase :: String -> String
397 lowercase = map toLower
398 lowercase = map toLower
398
399
399−rawBlockLines :: (String -> F Blocks) -> String -> OrgParser (F Blocks)
400+rawBlockLines :: Monad m => (String -> F Blocks) -> String -> OrgParser m (F Blocks)
400rawBlockLines f blockType = (ignHeaders *> (f <$> rawBlockContent blockType))
401rawBlockLines f blockType = (ignHeaders *> (f <$> rawBlockContent blockType))
401
402
402−parseBlockLines :: (F Blocks -> F Blocks) -> String -> OrgParser (F Blocks)
403+parseBlockLines :: PandocMonad m => (F Blocks -> F Blocks) -> String -> OrgParser m (F Blocks)
403parseBlockLines f blockType = (ignHeaders *> (f <$> parsedBlockContent))
404parseBlockLines f blockType = (ignHeaders *> (f <$> parsedBlockContent))
404 where
405 where
405− parsedBlockContent :: OrgParser (F Blocks)
406+ parsedBlockContent :: PandocMonad m => OrgParser m (F Blocks)
406 parsedBlockContent = try $ do
407 parsedBlockContent = try $ do
407 raw <- rawBlockContent blockType
408 raw <- rawBlockContent blockType
408 parseFromString blocks (raw ++ "\n")
409 parseFromString blocks (raw ++ "\n")
409
410
410-- | Read the raw string content of a block
411-- | Read the raw string content of a block
411−rawBlockContent :: String -> OrgParser String
412+rawBlockContent :: Monad m => String -> OrgParser m String
412rawBlockContent blockType = try $ do
413rawBlockContent blockType = try $ do
413 blkLines <- manyTill rawLine blockEnder
414 blkLines <- manyTill rawLine blockEnder
414 tabLen <- getOption readerTabStop
415 tabLen <- getOption readerTabStop
@@ -418,10 +419,10 @@ rawBlockContent blockType = try $ do
418 . map (tabsToSpaces tabLen . commaEscaped)
419 . map (tabsToSpaces tabLen . commaEscaped)
419 $ blkLines
420 $ blkLines
420 where
421 where
421− rawLine :: OrgParser String
422+ rawLine :: Monad m => OrgParser m String
422 rawLine = try $ ("" <$ blankline) <|> anyLine
423 rawLine = try $ ("" <$ blankline) <|> anyLine
423
424
424− blockEnder :: OrgParser ()
425+ blockEnder :: Monad m => OrgParser m ()
425 blockEnder = try $ skipSpaces <* stringAnyCase ("#+end_" <> blockType)
426 blockEnder = try $ skipSpaces <* stringAnyCase ("#+end_" <> blockType)
426
427
427 stripIndent :: [String] -> [String]
428 stripIndent :: [String] -> [String]
@@ -448,18 +449,18 @@ rawBlockContent blockType = try $ do
448 commaEscaped cs = cs
449 commaEscaped cs = cs
449
450
450-- | Read but ignore all remaining block headers.
451-- | Read but ignore all remaining block headers.
451−ignHeaders :: OrgParser ()
452+ignHeaders :: Monad m => OrgParser m ()
452ignHeaders = (() <$ newline) <|> (() <$ anyLine)
453ignHeaders = (() <$ newline) <|> (() <$ anyLine)
453
454
454-- | Read a block containing code intended for export in specific backends
455-- | Read a block containing code intended for export in specific backends
455-- only.
456-- only.
456−exportBlock :: String -> OrgParser (F Blocks)
457+exportBlock :: Monad m => String -> OrgParser m (F Blocks)
457exportBlock blockType = try $ do
458exportBlock blockType = try $ do
458 exportType <- skipSpaces *> orgArgWord <* ignHeaders
459 exportType <- skipSpaces *> orgArgWord <* ignHeaders
459 contents <- rawBlockContent blockType
460 contents <- rawBlockContent blockType
460 returnF (B.rawBlock (map toLower exportType) contents)
461 returnF (B.rawBlock (map toLower exportType) contents)
461
462
462−verseBlock :: String -> OrgParser (F Blocks)
463+verseBlock :: PandocMonad m => String -> OrgParser m (F Blocks)
463verseBlock blockType = try $ do
464verseBlock blockType = try $ do
464 ignHeaders
465 ignHeaders
465 content <- rawBlockContent blockType
466 content <- rawBlockContent blockType
@@ -468,7 +469,7 @@ verseBlock blockType = try $ do
468 where
469 where
469 -- replace initial spaces with nonbreaking spaces to preserve
470 -- replace initial spaces with nonbreaking spaces to preserve
470 -- indentation, parse the rest as normal inline
471 -- indentation, parse the rest as normal inline
471− parseVerseLine :: String -> OrgParser (F Inlines)
472+ parseVerseLine :: PandocMonad m => String -> OrgParser m (F Inlines)
472 parseVerseLine cs = do
473 parseVerseLine cs = do
473 let (initialSpaces, indentedLine) = span isSpace cs
474 let (initialSpaces, indentedLine) = span isSpace cs
474 let nbspIndent = if null initialSpaces
475 let nbspIndent = if null initialSpaces
@@ -480,7 +481,7 @@ verseBlock blockType = try $ do
480-- | Read a code block and the associated results block if present. Which of
481-- | Read a code block and the associated results block if present. Which of
481-- boths blocks is included in the output is determined using the "exports"
482-- boths blocks is included in the output is determined using the "exports"
482-- argument in the block header.
483-- argument in the block header.
483−codeBlock :: BlockAttributes -> String -> OrgParser (F Blocks)
484+codeBlock :: PandocMonad m => BlockAttributes -> String -> OrgParser m (F Blocks)
484codeBlock blockAttrs blockType = do
485codeBlock blockAttrs blockType = do
485 skipSpaces
486 skipSpaces
486 (classes, kv) <- codeHeaderArgs <|> (mempty <$ ignHeaders)
487 (classes, kv) <- codeHeaderArgs <|> (mempty <$ ignHeaders)
@@ -513,7 +514,7 @@ exportsResults :: [(String, String)] -> Bool
513exportsResults attrs = ("rundoc-exports", "results") `elem` attrs
514exportsResults attrs = ("rundoc-exports", "results") `elem` attrs
514 || ("rundoc-exports", "both") `elem` attrs
515 || ("rundoc-exports", "both") `elem` attrs
515
516
516−trailingResultsBlock :: OrgParser (Maybe (F Blocks))
517+trailingResultsBlock :: PandocMonad m => OrgParser m (Maybe (F Blocks))
517trailingResultsBlock = optionMaybe . try $ do
518trailingResultsBlock = optionMaybe . try $ do
518 blanklines
519 blanklines
519 stringAnyCase "#+RESULTS:"
520 stringAnyCase "#+RESULTS:"
@@ -522,7 +523,7 @@ trailingResultsBlock = optionMaybe . try $ do
522
523
523-- | Parse code block arguments
524-- | Parse code block arguments
524-- TODO: We currently don't handle switches.
525-- TODO: We currently don't handle switches.
525−codeHeaderArgs :: OrgParser ([String], [(String, String)])
526+codeHeaderArgs :: Monad m => OrgParser m ([String], [(String, String)])
526codeHeaderArgs = try $ do
527codeHeaderArgs = try $ do
527 language <- skipSpaces *> orgArgWord
528 language <- skipSpaces *> orgArgWord
528 _ <- skipSpaces *> (try $ switch `sepBy` (many1 spaceChar))
529 _ <- skipSpaces *> (try $ switch `sepBy` (many1 spaceChar))
@@ -537,27 +538,27 @@ codeHeaderArgs = try $ do
537 where
538 where
538 hasRundocParameters = not . null
539 hasRundocParameters = not . null
539
540
540−switch :: OrgParser (Char, Maybe String)
541+switch :: Monad m => OrgParser m (Char, Maybe String)
541switch = try $ simpleSwitch <|> lineNumbersSwitch
542switch = try $ simpleSwitch <|> lineNumbersSwitch
542 where
543 where
543 simpleSwitch = (\c -> (c, Nothing)) <$> (oneOf "-+" *> letter)
544 simpleSwitch = (\c -> (c, Nothing)) <$> (oneOf "-+" *> letter)
544 lineNumbersSwitch = (\ls -> ('l', Just ls)) <$>
545 lineNumbersSwitch = (\ls -> ('l', Just ls)) <$>
545 (string "-l \"" *> many1Till nonspaceChar (char '"'))
546 (string "-l \"" *> many1Till nonspaceChar (char '"'))
546
547
547−blockOption :: OrgParser (String, String)
548+blockOption :: Monad m => OrgParser m (String, String)
548blockOption = try $ do
549blockOption = try $ do
549 argKey <- orgArgKey
550 argKey <- orgArgKey
550 paramValue <- option "yes" orgParamValue
551 paramValue <- option "yes" orgParamValue
551 return (argKey, paramValue)
552 return (argKey, paramValue)
552
553
553−orgParamValue :: OrgParser String
554+orgParamValue :: Monad m => OrgParser m String
554orgParamValue = try $
555orgParamValue = try $
555 skipSpaces
556 skipSpaces
556 *> notFollowedBy (char ':' )
557 *> notFollowedBy (char ':' )
557 *> many1 nonspaceChar
558 *> many1 nonspaceChar
558 <* skipSpaces
559 <* skipSpaces
559
560
560−horizontalRule :: OrgParser (F Blocks)
561+horizontalRule :: Monad m => OrgParser m (F Blocks)
561horizontalRule = return B.horizontalRule <$ try hline
562horizontalRule = return B.horizontalRule <$ try hline
562
563
563
564
@@ -568,7 +569,7 @@ horizontalRule = return B.horizontalRule <$ try hline
568-- | A generic drawer which has no special meaning for org-mode.
569-- | A generic drawer which has no special meaning for org-mode.
569-- Whether or not this drawer is included in the output depends on the drawers
570-- Whether or not this drawer is included in the output depends on the drawers
570-- export setting.
571-- export setting.
571−genericDrawer :: OrgParser (F Blocks)
572+genericDrawer :: PandocMonad m => OrgParser m (F Blocks)
572genericDrawer = try $ do
573genericDrawer = try $ do
573 name <- map toUpper <$> drawerStart
574 name <- map toUpper <$> drawerStart
574 content <- manyTill drawerLine (try drawerEnd)
575 content <- manyTill drawerLine (try drawerEnd)
@@ -582,35 +583,35 @@ genericDrawer = try $ do
582 Right names | name `notElem` names -> return mempty
583 Right names | name `notElem` names -> return mempty
583 _ -> drawerDiv name <$> parseLines content
584 _ -> drawerDiv name <$> parseLines content
584 where
585 where
585− parseLines :: [String] -> OrgParser (F Blocks)
586+ parseLines :: PandocMonad m => [String] -> OrgParser m (F Blocks)
586 parseLines = parseFromString blocks . (++ "\n") . unlines
587 parseLines = parseFromString blocks . (++ "\n") . unlines
587
588
588 drawerDiv :: String -> F Blocks -> F Blocks
589 drawerDiv :: String -> F Blocks -> F Blocks
589 drawerDiv drawerName = fmap $ B.divWith (mempty, [drawerName, "drawer"], mempty)
590 drawerDiv drawerName = fmap $ B.divWith (mempty, [drawerName, "drawer"], mempty)
590
591
591−drawerLine :: OrgParser String
592+drawerLine :: Monad m => OrgParser m String
592drawerLine = anyLine
593drawerLine = anyLine
593
594
594−drawerEnd :: OrgParser String
595+drawerEnd :: Monad m => OrgParser m String
595drawerEnd = try $
596drawerEnd = try $
596 skipSpaces *> stringAnyCase ":END:" <* skipSpaces <* newline
597 skipSpaces *> stringAnyCase ":END:" <* skipSpaces <* newline
597
598
598-- | Read a :PROPERTIES: drawer and return the key/value pairs contained
599-- | Read a :PROPERTIES: drawer and return the key/value pairs contained
599-- within.
600-- within.
600−propertiesDrawer :: OrgParser Properties
601+propertiesDrawer :: Monad m => OrgParser m Properties
601propertiesDrawer = try $ do
602propertiesDrawer = try $ do
602 drawerType <- drawerStart
603 drawerType <- drawerStart
603 guard $ map toUpper drawerType == "PROPERTIES"
604 guard $ map toUpper drawerType == "PROPERTIES"
604 manyTill property (try drawerEnd)
605 manyTill property (try drawerEnd)
605 where
606 where
606− property :: OrgParser (PropertyKey, PropertyValue)
607+ property :: Monad m => OrgParser m (PropertyKey, PropertyValue)
607 property = try $ (,) <$> key <*> value
608 property = try $ (,) <$> key <*> value
608
609
609− key :: OrgParser PropertyKey
610+ key :: Monad m => OrgParser m PropertyKey
610 key = fmap toPropertyKey . try $
611 key = fmap toPropertyKey . try $
611 skipSpaces *> char ':' *> many1Till nonspaceChar (char ':')
612 skipSpaces *> char ':' *> many1Till nonspaceChar (char ':')
612
613
613− value :: OrgParser PropertyValue
614+ value :: Monad m => OrgParser m PropertyValue
614 value = fmap toPropertyValue . try $
615 value = fmap toPropertyValue . try $
615 skipSpaces *> manyTill anyChar (try $ skipSpaces *> newline)
616 skipSpaces *> manyTill anyChar (try $ skipSpaces *> newline)
616
617
@@ -621,7 +622,7 @@ propertiesDrawer = try $ do
621
622
622-- | Figures or an image paragraph (i.e. an image on a line by itself). Only
623-- | Figures or an image paragraph (i.e. an image on a line by itself). Only
623-- images with a caption attribute are interpreted as figures.
624-- images with a caption attribute are interpreted as figures.
624−figure :: OrgParser (F Blocks)
625+figure :: PandocMonad m => OrgParser m (F Blocks)
625figure = try $ do
626figure = try $ do
626 figAttrs <- blockAttributes
627 figAttrs <- blockAttributes
627 src <- skipSpaces *> selfTarget <* skipSpaces <* endOfParagraph
628 src <- skipSpaces *> selfTarget <* skipSpaces <* endOfParagraph
@@ -632,7 +633,7 @@ figure = try $ do
632 let isFigure = not . isNothing $ blockAttrCaption figAttrs
633 let isFigure = not . isNothing $ blockAttrCaption figAttrs
633 return $ imageBlock isFigure figAttrs imgSrc
634 return $ imageBlock isFigure figAttrs imgSrc
634 where
635 where
635− selfTarget :: OrgParser String
636+ selfTarget :: PandocMonad m => OrgParser m String
636 selfTarget = try $ char '[' *> linkTarget <* char ']'
637 selfTarget = try $ char '[' *> linkTarget <* char ']'
637
638
638 imageBlock :: Bool -> BlockAttributes -> String -> F Blocks
639 imageBlock :: Bool -> BlockAttributes -> String -> F Blocks
@@ -654,7 +655,7 @@ figure = try $ do
654 else "fig:" ++ cs
655 else "fig:" ++ cs
655
656
656-- | Succeeds if looking at the end of the current paragraph
657-- | Succeeds if looking at the end of the current paragraph
657−endOfParagraph :: OrgParser ()
658+endOfParagraph :: Monad m => OrgParser m ()
658endOfParagraph = try $ skipSpaces *> newline *> endOfBlock
659endOfParagraph = try $ skipSpaces *> newline *> endOfBlock
659
660
660
661
@@ -663,11 +664,11 @@ endOfParagraph = try $ skipSpaces *> newline *> endOfBlock
663--
664--
664
665
665-- | Example code marked up by a leading colon.
666-- | Example code marked up by a leading colon.
666−example :: OrgParser (F Blocks)
667+example :: Monad m => OrgParser m (F Blocks)
667example = try $ do
668example = try $ do
668 return . return . exampleCode =<< unlines <$> many1 exampleLine
669 return . return . exampleCode =<< unlines <$> many1 exampleLine
669 where
670 where
670− exampleLine :: OrgParser String
671+ exampleLine :: Monad m => OrgParser m String
671 exampleLine = try $ exampleLineStart *> anyLine
672 exampleLine = try $ exampleLineStart *> anyLine
672
673
673exampleCode :: String -> Blocks
674exampleCode :: String -> Blocks
@@ -678,10 +679,10 @@ exampleCode = B.codeBlockWith ("", ["example"], [])
678-- Comments, Options and Metadata
679-- Comments, Options and Metadata
679--
680--
680
681
681−specialLine :: OrgParser (F Blocks)
682+specialLine :: PandocMonad m => OrgParser m (F Blocks)
682specialLine = fmap return . try $ rawExportLine <|> metaLine <|> commentLine
683specialLine = fmap return . try $ rawExportLine <|> metaLine <|> commentLine
683
684
684−rawExportLine :: OrgParser Blocks
685+rawExportLine :: PnadocMonad m => OrgParser m Blocks
685rawExportLine = try $ do
686rawExportLine = try $ do
686 metaLineStart
687 metaLineStart
687 key <- metaKey
688 key <- metaKey
@@ -689,7 +690,7 @@ rawExportLine = try $ do
689 then B.rawBlock key <$> anyLine
690 then B.rawBlock key <$> anyLine
690 else mzero
691 else mzero
691
692
692−commentLine :: OrgParser Blocks
693+commentLine :: Monad m => OrgParser m Blocks
693commentLine = commentLineStart *> anyLine *> pure mempty
694commentLine = commentLineStart *> anyLine *> pure mempty
694
695
695
696
@@ -718,7 +719,7 @@ data OrgTable = OrgTable
718 , orgTableRows :: [[Blocks]]
719 , orgTableRows :: [[Blocks]]
719 }
720 }
720
721
721−table :: OrgParser (F Blocks)
722+table :: PandocMonad m => OrgParser m (F Blocks)
722table = try $ do
723table = try $ do
723 blockAttrs <- blockAttributes
724 blockAttrs <- blockAttributes
724 lookAhead tableStart
725 lookAhead tableStart
@@ -745,18 +746,18 @@ orgToPandocTable (OrgTable colProps heads lns) caption =
745 <*> totalWidth
746 <*> totalWidth
746 in (align', width')
747 in (align', width')
747
748
748−tableRows :: OrgParser [OrgTableRow]
749+tableRows :: PandocMonad m => OrgParser m [OrgTableRow]
749tableRows = try $ many (tableAlignRow <|> tableHline <|> tableContentRow)
750tableRows = try $ many (tableAlignRow <|> tableHline <|> tableContentRow)
750
751
751−tableContentRow :: OrgParser OrgTableRow
752+tableContentRow :: PandocMonad m => OrgParser m OrgTableRow
752tableContentRow = try $
753tableContentRow = try $
753 OrgContentRow . sequence <$> (tableStart *> many1Till tableContentCell newline)
754 OrgContentRow . sequence <$> (tableStart *> many1Till tableContentCell newline)
754
755
755−tableContentCell :: OrgParser (F Blocks)
756+tableContentCell :: PandocMonad m => OrgParser m (F Blocks)
756tableContentCell = try $
757tableContentCell = try $
757 fmap B.plain . trimInlinesF . mconcat <$> manyTill inline endOfCell
758 fmap B.plain . trimInlinesF . mconcat <$> manyTill inline endOfCell
758
759
759−tableAlignRow :: OrgParser OrgTableRow
760+tableAlignRow :: Monad m => OrgParser m OrgTableRow
760tableAlignRow = try $ do
761tableAlignRow = try $ do
761 tableStart
762 tableStart
762 colProps <- many1Till columnPropertyCell newline
763 colProps <- many1Till columnPropertyCell newline
@@ -764,7 +765,7 @@ tableAlignRow = try $ do
764 guard $ any (/= def) colProps
765 guard $ any (/= def) colProps
765 return $ OrgAlignRow colProps
766 return $ OrgAlignRow colProps
766
767
767−columnPropertyCell :: OrgParser ColumnProperty
768+columnPropertyCell :: Monad m => OrgParser m ColumnProperty
768columnPropertyCell = emptyCell <|> propCell <?> "alignment info"
769columnPropertyCell = emptyCell <|> propCell <?> "alignment info"
769 where
770 where
770 emptyCell = ColumnProperty Nothing Nothing <$ (try $ skipSpaces *> endOfCell)
771 emptyCell = ColumnProperty Nothing Nothing <$ (try $ skipSpaces *> endOfCell)
@@ -776,18 +777,18 @@ columnPropertyCell = emptyCell <|> propCell <?> "alignment info"
776 <* char '>'
777 <* char '>'
777 <* emptyCell)
778 <* emptyCell)
778
779
779−tableAlignFromChar :: OrgParser Alignment
780+tableAlignFromChar :: Monad m => OrgParser m Alignment
780tableAlignFromChar = try $
781tableAlignFromChar = try $
781 choice [ char 'l' *> return AlignLeft
782 choice [ char 'l' *> return AlignLeft
782 , char 'c' *> return AlignCenter
783 , char 'c' *> return AlignCenter
783 , char 'r' *> return AlignRight
784 , char 'r' *> return AlignRight
784 ]
785 ]
785
786
786−tableHline :: OrgParser OrgTableRow
787+tableHline :: Monad m => OrgParser m OrgTableRow
787tableHline = try $
788tableHline = try $
788 OrgHlineRow <$ (tableStart *> char '-' *> anyLine)
789 OrgHlineRow <$ (tableStart *> char '-' *> anyLine)
789
790
790−endOfCell :: OrgParser Char
791+endOfCell :: Monad m => OrgParser m Char
791endOfCell = try $ char '|' <|> lookAhead newline
792endOfCell = try $ char '|' <|> lookAhead newline
792
793
793rowsToTable :: [OrgTableRow]
794rowsToTable :: [OrgTableRow]
@@ -840,7 +841,7 @@ rowToContent orgTable row =
840--
841--
841-- LaTeX fragments
842-- LaTeX fragments
842--
843--
843−latexFragment :: OrgParser (F Blocks)
844+latexFragment :: Monad m => OrgParser m (F Blocks)
844latexFragment = try $ do
845latexFragment = try $ do
845 envName <- latexEnvStart
846 envName <- latexEnvStart
846 content <- mconcat <$> manyTill anyLineNewline (latexEnd envName)
847 content <- mconcat <$> manyTill anyLineNewline (latexEnd envName)
@@ -851,7 +852,7 @@ latexFragment = try $ do
851 , "\\end{", e, "}\n"
852 , "\\end{", e, "}\n"
852 ]
853 ]
853
854
854−latexEnd :: String -> OrgParser ()
855+latexEnd :: Monad m => String -> OrgParser m ()
855latexEnd envName = try $
856latexEnd envName = try $
856 () <$ skipSpaces
857 () <$ skipSpaces
857 <* string ("\\end{" ++ envName ++ "}")
858 <* string ("\\end{" ++ envName ++ "}")
@@ -861,7 +862,7 @@ latexEnd envName = try $
861--
862--
862-- Footnote defintions
863-- Footnote defintions
863--
864--
864−noteBlock :: OrgParser (F Blocks)
865+noteBlock :: PandocMonad m => OrgParser m (F Blocks)
865noteBlock = try $ do
866noteBlock = try $ do
866 ref <- noteMarker <* skipSpaces
867 ref <- noteMarker <* skipSpaces
867 content <- mconcat <$> blocksTillHeaderOrNote
868 content <- mconcat <$> blocksTillHeaderOrNote
@@ -873,7 +874,7 @@ noteBlock = try $ do
873 <|> () <$ lookAhead headerStart)
874 <|> () <$ lookAhead headerStart)
874
875
875-- Paragraphs or Plain text
876-- Paragraphs or Plain text
876−paraOrPlain :: OrgParser (F Blocks)
877+paraOrPlain :: PandocMonad m => OrgParser m (F Blocks)
877paraOrPlain = try $ do
878paraOrPlain = try $ do
878 -- Make sure we are not looking at a headline
879 -- Make sure we are not looking at a headline
879 notFollowedBy' (char '*' *> (oneOf " *"))
880 notFollowedBy' (char '*' *> (oneOf " *"))
@@ -892,24 +893,24 @@ paraOrPlain = try $ do
892-- list blocks
893-- list blocks
893--
894--
894
895
895−list :: OrgParser (F Blocks)
896+list :: PandocMonad m => OrgParser m (F Blocks)
896list = choice [ definitionList, bulletList, orderedList ] <?> "list"
897list = choice [ definitionList, bulletList, orderedList ] <?> "list"
897
898
898−definitionList :: OrgParser (F Blocks)
899+definitionList :: PandocMonad m => OrgParser m (F Blocks)
899definitionList = try $ do n <- lookAhead (bulletListStart' Nothing)
900definitionList = try $ do n <- lookAhead (bulletListStart' Nothing)
900 fmap B.definitionList . fmap compactify'DL . sequence
901 fmap B.definitionList . fmap compactify'DL . sequence
901 <$> many1 (definitionListItem $ bulletListStart' (Just n))
902 <$> many1 (definitionListItem $ bulletListStart' (Just n))
902
903
903−bulletList :: OrgParser (F Blocks)
904+bulletList :: PandocMonad m => OrgParser m (F Blocks)
904bulletList = try $ do n <- lookAhead (bulletListStart' Nothing)
905bulletList = try $ do n <- lookAhead (bulletListStart' Nothing)
905 fmap B.bulletList . fmap compactify' . sequence
906 fmap B.bulletList . fmap compactify' . sequence
906 <$> many1 (listItem (bulletListStart' $ Just n))
907 <$> many1 (listItem (bulletListStart' $ Just n))
907
908
908−orderedList :: OrgParser (F Blocks)
909+orderedList :: PandocMonad m => OrgParser m (F Blocks)
909orderedList = fmap B.orderedList . fmap compactify' . sequence
910orderedList = fmap B.orderedList . fmap compactify' . sequence
910 <$> many1 (listItem orderedListStart)
911 <$> many1 (listItem orderedListStart)
911
912
912−bulletListStart' :: Maybe Int -> OrgParser Int
913+bulletListStart' :: Monad m => Maybe Int -> OrgParser m Int
913-- returns length of bulletList prefix, inclusive of marker
914-- returns length of bulletList prefix, inclusive of marker
914bulletListStart' Nothing = do ind <- length <$> many spaceChar
915bulletListStart' Nothing = do ind <- length <$> many spaceChar
915 oneOf (bullets $ ind == 0)
916 oneOf (bullets $ ind == 0)
@@ -925,8 +926,9 @@ bulletListStart' (Just n) = do count (n-1) spaceChar
925bullets :: Bool -> String
926bullets :: Bool -> String
926bullets unindented = if unindented then "+-" else "*+-"
927bullets unindented = if unindented then "+-" else "*+-"
927
928
928−definitionListItem :: OrgParser Int
929+definitionListItem :: PandocMonad m
930+ => OrgParser m Int
929− -> OrgParser (F (Inlines, [Blocks]))
931+ -> OrgParser m (F (Inlines, [Blocks]))
930definitionListItem parseMarkerGetLength = try $ do
932definitionListItem parseMarkerGetLength = try $ do
931 markerLength <- parseMarkerGetLength
933 markerLength <- parseMarkerGetLength
932 term <- manyTill (noneOf "\n\r") (try definitionMarker)
934 term <- manyTill (noneOf "\n\r") (try definitionMarker)
@@ -942,8 +944,9 @@ definitionListItem parseMarkerGetLength = try $ do
942
944
943
945
944-- parse raw text for one list item, excluding start marker and continuations
946-- parse raw text for one list item, excluding start marker and continuations
947+listItem :: PandocMonad m
945−listItem :: OrgParser Int
948+ => OrgParser m Int
946− -> OrgParser (F Blocks)
949+ -> OrgParser m (F Blocks)
947listItem start = try . withContext ListItemState $ do
950listItem start = try . withContext ListItemState $ do
948 markerLength <- try start
951 markerLength <- try start
949 firstLine <- anyLineNewline
952 firstLine <- anyLineNewline
@@ -953,8 +956,8 @@ listItem start = try . withContext ListItemState $ do
953
956
954-- continuation of a list item - indented and separated by blankline or endline.
957-- continuation of a list item - indented and separated by blankline or endline.
955-- Note: nested lists are parsed as continuations.
958-- Note: nested lists are parsed as continuations.
956−listContinuation :: Int
959+listContinuation :: Monad m => Int
957− -> OrgParser String
960+ -> OrgParser m String
958listContinuation markerLength = try $
961listContinuation markerLength = try $
959 notFollowedBy' blankline
962 notFollowedBy' blankline
960 *> (mappend <$> (concat <$> many1 listLine)
963 *> (mappend <$> (concat <$> many1 listLine)
@@ -963,7 +966,7 @@ listContinuation markerLength = try $
963 listLine = try $ indentWith markerLength *> anyLineNewline
966 listLine = try $ indentWith markerLength *> anyLineNewline
964
967
965 -- indent by specified number of spaces (or equiv. tabs)
968 -- indent by specified number of spaces (or equiv. tabs)
966− indentWith :: Int -> OrgParser String
969+ indentWith :: Monad m => Int -> OrgParser m String
967 indentWith num = do
970 indentWith num = do
968 tabStop <- getOption readerTabStop
971 tabStop <- getOption readerTabStop
969 if num < tabStop
972 if num < tabStop
@@ -972,5 +975,5 @@ listContinuation markerLength = try $
972 , try (char '\t' >> count (num - tabStop) (char ' ')) ]
975 , try (char '\t' >> count (num - tabStop) (char ' ')) ]
973
976
974-- | Parse any line, include the final newline in the output.
977-- | Parse any line, include the final newline in the output.
975−anyLineNewline :: OrgParser String
978+anyLineNewline :: Monad m => OrgParser m String
976anyLineNewline = (++ "\n") <$> anyLine
979anyLineNewline = (++ "\n") <$> anyLine
src/Text/Pandoc/Readers/Org/ExportSettings.hs+18−15
@@ -37,14 +37,14 @@ import Data.Char ( toLower )
37import Data.Maybe ( listToMaybe )
37import Data.Maybe ( listToMaybe )
38
38
39-- | Read and handle space separated org-mode export settings.
39-- | Read and handle space separated org-mode export settings.
40−exportSettings :: OrgParser ()
40+exportSettings :: Monad m => OrgParser m ()
41exportSettings = void $ sepBy spaces exportSetting
41exportSettings = void $ sepBy spaces exportSetting
42
42
43-- | Setter function for export settings.
43-- | Setter function for export settings.
44type ExportSettingSetter a = a -> ExportSettings -> ExportSettings
44type ExportSettingSetter a = a -> ExportSettings -> ExportSettings
45
45
46-- | Read and process a single org-mode export option.
46-- | Read and process a single org-mode export option.
47−exportSetting :: OrgParser ()
47+exportSetting :: Monad m => OrgParser m ()
48exportSetting = choice
48exportSetting = choice
49 [ booleanSetting "^" (\val es -> es { exportSubSuperscripts = val })
49 [ booleanSetting "^" (\val es -> es { exportSubSuperscripts = val })
50 , booleanSetting "'" (\val es -> es { exportSmartQuotes = val })
50 , booleanSetting "'" (\val es -> es { exportSmartQuotes = val })
@@ -81,10 +81,11 @@ exportSetting = choice
81 , ignoredSetting "|"
81 , ignoredSetting "|"
82 ] <?> "export setting"
82 ] <?> "export setting"
83
83
84−genericExportSetting :: OrgParser a
84+genericExportSetting :: Monad m
85+ => OrgParser m a
85 -> String
86 -> String
86 -> ExportSettingSetter a
87 -> ExportSettingSetter a
87− -> OrgParser ()
88+ -> OrgParser m ()
88genericExportSetting optionParser settingIdentifier setter = try $ do
89genericExportSetting optionParser settingIdentifier setter = try $ do
89 _ <- string settingIdentifier *> char ':'
90 _ <- string settingIdentifier *> char ':'
90 value <- optionParser
91 value <- optionParser
@@ -94,11 +95,11 @@ genericExportSetting optionParser settingIdentifier setter = try $ do
94 st { orgStateExportSettings = setter val . orgStateExportSettings $ st }
95 st { orgStateExportSettings = setter val . orgStateExportSettings $ st }
95
96
96-- | A boolean option, either nil (False) or non-nil (True).
97-- | A boolean option, either nil (False) or non-nil (True).
97−booleanSetting :: String -> ExportSettingSetter Bool -> OrgParser ()
98+booleanSetting :: Monad m => String -> ExportSettingSetter Bool -> OrgParser m ()
98booleanSetting = genericExportSetting elispBoolean
99booleanSetting = genericExportSetting elispBoolean
99
100
100-- | An integer-valued option.
101-- | An integer-valued option.
101−integerSetting :: String -> ExportSettingSetter Int -> OrgParser ()
102+integerSetting :: Monad m => String -> ExportSettingSetter Int -> OrgParser m ()
102integerSetting = genericExportSetting parseInt
103integerSetting = genericExportSetting parseInt
103 where
104 where
104 parseInt = try $
105 parseInt = try $
@@ -106,9 +107,10 @@ integerSetting = genericExportSetting parseInt
106
107
107-- | Either the string "headline" or an elisp boolean and treated as an
108-- | Either the string "headline" or an elisp boolean and treated as an
108-- @ArchivedTreesOption@.
109-- @ArchivedTreesOption@.
109−archivedTreeSetting :: String
110+archivedTreeSetting :: Monad m
111+ => String
110 -> ExportSettingSetter ArchivedTreesOption
112 -> ExportSettingSetter ArchivedTreesOption
111− -> OrgParser ()
113+ -> OrgParser m ()
112archivedTreeSetting =
114archivedTreeSetting =
113 genericExportSetting $ archivedTreesHeadlineSetting <|> archivedTreesBoolean
115 genericExportSetting $ archivedTreesHeadlineSetting <|> archivedTreesBoolean
114 where
116 where
@@ -125,9 +127,10 @@ archivedTreeSetting =
125 else ArchivedTreesNoExport
127 else ArchivedTreesNoExport
126
128
127-- | A list or a complement list (i.e. a list starting with `not`).
129-- | A list or a complement list (i.e. a list starting with `not`).
128−complementableListSetting :: String
130+complementableListSetting :: Monad m
131+ => String
129 -> ExportSettingSetter (Either [String] [String])
132 -> ExportSettingSetter (Either [String] [String])
130− -> OrgParser ()
133+ -> OrgParser m ()
131complementableListSetting = genericExportSetting $ choice
134complementableListSetting = genericExportSetting $ choice
132 [ Left <$> complementStringList
135 [ Left <$> complementStringList
133 , Right <$> stringList
136 , Right <$> stringList
@@ -135,31 +138,31 @@ complementableListSetting = genericExportSetting $ choice
135 ]
138 ]
136 where
139 where
137 -- Read a plain list of strings.
140 -- Read a plain list of strings.
138− stringList :: OrgParser [String]
141+ stringList :: Monad m => OrgParser m [String]
139 stringList = try $
142 stringList = try $
140 char '('
143 char '('
141 *> sepBy elispString spaces
144 *> sepBy elispString spaces
142 <* char ')'
145 <* char ')'
143
146
144 -- Read an emacs lisp list specifying a complement set.
147 -- Read an emacs lisp list specifying a complement set.
145− complementStringList :: OrgParser [String]
148+ complementStringList :: Monad m => OrgParser m [String]
146 complementStringList = try $
149 complementStringList = try $
147 string "(not "
150 string "(not "
148 *> sepBy elispString spaces
151 *> sepBy elispString spaces
149 <* char ')'
152 <* char ')'
150
153
151− elispString :: OrgParser String
154+ elispString :: Monad m => OrgParser m String
152 elispString = try $
155 elispString = try $
153 char '"'
156 char '"'
154 *> manyTill alphaNum (char '"')
157 *> manyTill alphaNum (char '"')
155
158
156-- | Read but ignore the export setting.
159-- | Read but ignore the export setting.
157−ignoredSetting :: String -> OrgParser ()
160+ignoredSetting :: Monad m => String -> OrgParser m ()
158ignoredSetting s = try (() <$ string s <* char ':' <* many1 nonspaceChar)
161ignoredSetting s = try (() <$ string s <* char ':' <* many1 nonspaceChar)
159
162
160-- | Read an elisp boolean. Only NIL is treated as false, non-NIL values are
163-- | Read an elisp boolean. Only NIL is treated as false, non-NIL values are
161-- interpreted as true.
164-- interpreted as true.
162−elispBoolean :: OrgParser Bool
165+elispBoolean :: Monad m => OrgParser m Bool
163elispBoolean = try $ do
166elispBoolean = try $ do
164 value <- many1 nonspaceChar
167 value <- many1 nonspaceChar
165 return $ case map toLower value of
168 return $ case map toLower value of
src/Text/Pandoc/Readers/Org/Inlines.hs+129−117
@@ -47,9 +47,11 @@ import Text.Pandoc.Options
47import Text.Pandoc.Readers.LaTeX ( inlineCommand, rawLaTeXInline )
47import Text.Pandoc.Readers.LaTeX ( inlineCommand, rawLaTeXInline )
48import Text.TeXMath ( readTeX, writePandoc, DisplayType(..) )
48import Text.TeXMath ( readTeX, writePandoc, DisplayType(..) )
49import qualified Text.TeXMath.Readers.MathML.EntityMap as MathMLEntityMap
49import qualified Text.TeXMath.Readers.MathML.EntityMap as MathMLEntityMap
50+import Text.Pandoc.Class (PandocMonad)
50
51
51import Prelude hiding (sequence)
52import Prelude hiding (sequence)
52import Control.Monad ( guard, mplus, mzero, when, void )
53import Control.Monad ( guard, mplus, mzero, when, void )
54+import Control.Monad.Trans ( lift )
53import Data.Char ( isAlphaNum, isSpace )
55import Data.Char ( isAlphaNum, isSpace )
54import Data.List ( intersperse )
56import Data.List ( intersperse )
55import Data.Maybe ( fromMaybe )
57import Data.Maybe ( fromMaybe )
@@ -60,46 +62,46 @@ import Data.Traversable (sequence)
60--
62--
61-- Functions acting on the parser state
63-- Functions acting on the parser state
62--
64--
63−recordAnchorId :: String -> OrgParser ()
65+recordAnchorId :: PandocMonad m => String -> OrgParser m ()
64recordAnchorId i = updateState $ \s ->
66recordAnchorId i = updateState $ \s ->
65 s{ orgStateAnchorIds = i : (orgStateAnchorIds s) }
67 s{ orgStateAnchorIds = i : (orgStateAnchorIds s) }
66
68
67−pushToInlineCharStack :: Char -> OrgParser ()
69+pushToInlineCharStack :: PandocMonad m => Char -> OrgParser m ()
68pushToInlineCharStack c = updateState $ \s ->
70pushToInlineCharStack c = updateState $ \s ->
69 s{ orgStateEmphasisCharStack = c:orgStateEmphasisCharStack s }
71 s{ orgStateEmphasisCharStack = c:orgStateEmphasisCharStack s }
70
72
71−popInlineCharStack :: OrgParser ()
73+popInlineCharStack :: PandocMonad m => OrgParser m ()
72popInlineCharStack = updateState $ \s ->
74popInlineCharStack = updateState $ \s ->
73 s{ orgStateEmphasisCharStack = drop 1 . orgStateEmphasisCharStack $ s }
75 s{ orgStateEmphasisCharStack = drop 1 . orgStateEmphasisCharStack $ s }
74
76
75−surroundingEmphasisChar :: OrgParser [Char]
77+surroundingEmphasisChar :: PandocMonad m => OrgParser m [Char]
76surroundingEmphasisChar =
78surroundingEmphasisChar =
77 take 1 . drop 1 . orgStateEmphasisCharStack <$> getState
79 take 1 . drop 1 . orgStateEmphasisCharStack <$> getState
78
80
79−startEmphasisNewlinesCounting :: Int -> OrgParser ()
81+startEmphasisNewlinesCounting :: PandocMonad m => Int -> OrgParser m ()
80startEmphasisNewlinesCounting maxNewlines = updateState $ \s ->
82startEmphasisNewlinesCounting maxNewlines = updateState $ \s ->
81 s{ orgStateEmphasisNewlines = Just maxNewlines }
83 s{ orgStateEmphasisNewlines = Just maxNewlines }
82
84
83−decEmphasisNewlinesCount :: OrgParser ()
85+decEmphasisNewlinesCount :: PandocMonad m => OrgParser m ()
84decEmphasisNewlinesCount = updateState $ \s ->
86decEmphasisNewlinesCount = updateState $ \s ->
85 s{ orgStateEmphasisNewlines = (\n -> n - 1) <$> orgStateEmphasisNewlines s }
87 s{ orgStateEmphasisNewlines = (\n -> n - 1) <$> orgStateEmphasisNewlines s }
86
88
87−newlinesCountWithinLimits :: OrgParser Bool
89+newlinesCountWithinLimits :: PandocMonad m => OrgParser m Bool
88newlinesCountWithinLimits = do
90newlinesCountWithinLimits = do
89 st <- getState
91 st <- getState
90 return $ ((< 0) <$> orgStateEmphasisNewlines st) /= Just True
92 return $ ((< 0) <$> orgStateEmphasisNewlines st) /= Just True
91
93
92−resetEmphasisNewlines :: OrgParser ()
94+resetEmphasisNewlines :: PandocMonad m => OrgParser m ()
93resetEmphasisNewlines = updateState $ \s ->
95resetEmphasisNewlines = updateState $ \s ->
94 s{ orgStateEmphasisNewlines = Nothing }
96 s{ orgStateEmphasisNewlines = Nothing }
95
97
96−addToNotesTable :: OrgNoteRecord -> OrgParser ()
98+addToNotesTable :: PandocMonad m => OrgNoteRecord -> OrgParser m ()
97addToNotesTable note = do
99addToNotesTable note = do
98 oldnotes <- orgStateNotes' <$> getState
100 oldnotes <- orgStateNotes' <$> getState
99 updateState $ \s -> s{ orgStateNotes' = note:oldnotes }
101 updateState $ \s -> s{ orgStateNotes' = note:oldnotes }
100
102
101-- | Parse a single Org-mode inline element
103-- | Parse a single Org-mode inline element
102−inline :: OrgParser (F Inlines)
104+inline :: PandocMonad m => OrgParser m (F Inlines)
103inline =
105inline =
104 choice [ whitespace
106 choice [ whitespace
105 , linebreak
107 , linebreak
@@ -125,7 +127,7 @@ inline =
125 <?> "inline"
127 <?> "inline"
126
128
127-- | Read the rest of the input as inlines.
129-- | Read the rest of the input as inlines.
128−inlines :: OrgParser (F Inlines)
130+inlines :: PandocMonad m => OrgParser m (F Inlines)
129inlines = trimInlinesF . mconcat <$> many1 inline
131inlines = trimInlinesF . mconcat <$> many1 inline
130
132
131-- treat these as potentially non-text when parsing inline:
133-- treat these as potentially non-text when parsing inline:
@@ -133,23 +135,23 @@ specialChars :: [Char]
133specialChars = "\"$'()*+-,./:;<=>@[\\]^_{|}~"
135specialChars = "\"$'()*+-,./:;<=>@[\\]^_{|}~"
134
136
135
137
136−whitespace :: OrgParser (F Inlines)
138+whitespace :: PandocMonad m => OrgParser m (F Inlines)
137whitespace = pure B.space <$ skipMany1 spaceChar
139whitespace = pure B.space <$ skipMany1 spaceChar
138 <* updateLastPreCharPos
140 <* updateLastPreCharPos
139 <* updateLastForbiddenCharPos
141 <* updateLastForbiddenCharPos
140 <?> "whitespace"
142 <?> "whitespace"
141
143
142−linebreak :: OrgParser (F Inlines)
144+linebreak :: PandocMonad m => OrgParser m (F Inlines)
143linebreak = try $ pure B.linebreak <$ string "\\\\" <* skipSpaces <* newline
145linebreak = try $ pure B.linebreak <$ string "\\\\" <* skipSpaces <* newline
144
146
145−str :: OrgParser (F Inlines)
147+str :: PandocMonad m => OrgParser m (F Inlines)
146str = return . B.str <$> many1 (noneOf $ specialChars ++ "\n\r ")
148str = return . B.str <$> many1 (noneOf $ specialChars ++ "\n\r ")
147 <* updateLastStrPos
149 <* updateLastStrPos
148
150
149-- | An endline character that can be treated as a space, not a structural
151-- | An endline character that can be treated as a space, not a structural
150-- break. This should reflect the values of the Emacs variable
152-- break. This should reflect the values of the Emacs variable
151-- @org-element-pagaraph-separate@.
153-- @org-element-pagaraph-separate@.
152−endline :: OrgParser (F Inlines)
154+endline :: PandocMonad m => OrgParser m (F Inlines)
153endline = try $ do
155endline = try $ do
154 newline
156 newline
155 notFollowedBy' endOfBlock
157 notFollowedBy' endOfBlock
@@ -174,7 +176,7 @@ endline = try $ do
174-- contributors. All this should be consolidated once an official Org-mode
176-- contributors. All this should be consolidated once an official Org-mode
175-- citation syntax has emerged.
177-- citation syntax has emerged.
176
178
177−cite :: OrgParser (F Inlines)
179+cite :: PandocMonad m => OrgParser m (F Inlines)
178cite = try $ berkeleyCite <|> do
180cite = try $ berkeleyCite <|> do
179 guardEnabled Ext_citations
181 guardEnabled Ext_citations
180 (cs, raw) <- withRaw $ choice
182 (cs, raw) <- withRaw $ choice
@@ -185,40 +187,41 @@ cite = try $ berkeleyCite <|> do
185 return $ (flip B.cite (B.text raw)) <$> cs
187 return $ (flip B.cite (B.text raw)) <$> cs
186
188
187-- | A citation in Pandoc Org-mode style (@[prefix \@citekey suffix]@).
189-- | A citation in Pandoc Org-mode style (@[prefix \@citekey suffix]@).
188−pandocOrgCite :: OrgParser (F [Citation])
190+pandocOrgCite :: PandocMonad m => OrgParser m (F [Citation])
189pandocOrgCite = try $
191pandocOrgCite = try $
190 char '[' *> skipSpaces *> citeList <* skipSpaces <* char ']'
192 char '[' *> skipSpaces *> citeList <* skipSpaces <* char ']'
191
193
192−orgRefCite :: OrgParser (F [Citation])
194+orgRefCite :: PandocMonad m => OrgParser m (F [Citation])
193orgRefCite = try $ choice
195orgRefCite = try $ choice
194 [ normalOrgRefCite
196 [ normalOrgRefCite
195 , fmap (:[]) <$> linkLikeOrgRefCite
197 , fmap (:[]) <$> linkLikeOrgRefCite
196 ]
198 ]
197
199
198−normalOrgRefCite :: OrgParser (F [Citation])
200+normalOrgRefCite :: PandocMonad m => OrgParser m (F [Citation])
199normalOrgRefCite = try $ do
201normalOrgRefCite = try $ do
200 mode <- orgRefCiteMode
202 mode <- orgRefCiteMode
201− -- org-ref style citation key, parsed into a citation of the given mode
202− let orgRefCiteItem :: OrgParser (F Citation)
203− orgRefCiteItem = try $ do
204− key <- orgRefCiteKey
205− returnF $ Citation
206− { citationId = key
207− , citationPrefix = mempty
208− , citationSuffix = mempty
209− , citationMode = mode
210− , citationNoteNum = 0
211− , citationHash = 0
212− }
213− firstCitation <- orgRefCiteItem
203+ firstCitation <- orgRefCiteList mode
214− moreCitations <- many (try $ char ',' *> orgRefCiteItem)
204+ moreCitations <- many (try $ char ',' *> orgRefCiteList mode)
215 return . sequence $ firstCitation : moreCitations
205 return . sequence $ firstCitation : moreCitations
216− where
206+ where
207+ -- | A list of org-ref style citation keys, parsed as citation of the given
208+ -- citation mode.
209+ orgRefCiteList :: PandocMonad m => CitationMode -> OrgParser m (F Citation)
210+ orgRefCiteList citeMode = try $ do
211+ key <- orgRefCiteKey
212+ returnF $ Citation
213+ { citationId = key
214+ , citationPrefix = mempty
215+ , citationSuffix = mempty
216+ , citationMode = citeMode
217+ , citationNoteNum = 0
218+ , citationHash = 0
219+ }
217
220
218-- | Read an Berkeley-style Org-mode citation. Berkeley citation style was
221-- | Read an Berkeley-style Org-mode citation. Berkeley citation style was
219-- develop and adjusted to Org-mode style by John MacFarlane and Richard
222-- develop and adjusted to Org-mode style by John MacFarlane and Richard
220-- Lawrence, respectively, both philosophers at UC Berkeley.
223-- Lawrence, respectively, both philosophers at UC Berkeley.
221−berkeleyCite :: OrgParser (F Inlines)
224+berkeleyCite :: PandocMonad m => OrgParser m (F Inlines)
222berkeleyCite = try $ do
225berkeleyCite = try $ do
223 bcl <- berkeleyCitationList
226 bcl <- berkeleyCitationList
224 return $ do
227 return $ do
@@ -260,7 +263,7 @@ data BerkeleyCitationList = BerkeleyCitationList
260 , berkeleyCiteCommonSuffix :: Maybe Inlines
263 , berkeleyCiteCommonSuffix :: Maybe Inlines
261 , berkeleyCiteCitations :: [Citation]
264 , berkeleyCiteCitations :: [Citation]
262 }
265 }
263−berkeleyCitationList :: OrgParser (F BerkeleyCitationList)
266+berkeleyCitationList :: PandocMonad m => OrgParser m (F BerkeleyCitationList)
264berkeleyCitationList = try $ do
267berkeleyCitationList = try $ do
265 char '['
268 char '['
266 parens <- choice [ False <$ berkeleyBareTag, True <$ berkeleyParensTag ]
269 parens <- choice [ False <$ berkeleyBareTag, True <$ berkeleyParensTag ]
@@ -275,22 +278,22 @@ berkeleyCitationList = try $ do
275 <*> sequence commonSuffix
278 <*> sequence commonSuffix
276 <*> citations)
279 <*> citations)
277 where
280 where
278− citationListPart :: OrgParser (F Inlines)
281+ citationListPart :: PandocMonad m => OrgParser m (F Inlines)
279 citationListPart = fmap (trimInlinesF . mconcat) . try . many1 $ do
282 citationListPart = fmap (trimInlinesF . mconcat) . try . many1 $ do
280 notFollowedBy' citeKey
283 notFollowedBy' citeKey
281 notFollowedBy (oneOf ";]")
284 notFollowedBy (oneOf ";]")
282 inline
285 inline
283
286
284−berkeleyBareTag :: OrgParser ()
287+berkeleyBareTag :: PandocMonad m => OrgParser m ()
285berkeleyBareTag = try $ void berkeleyBareTag'
288berkeleyBareTag = try $ void berkeleyBareTag'
286
289
287−berkeleyParensTag :: OrgParser ()
290+berkeleyParensTag :: PandocMonad m => OrgParser m ()
288berkeleyParensTag = try . void $ enclosedByPair '(' ')' berkeleyBareTag'
291berkeleyParensTag = try . void $ enclosedByPair '(' ')' berkeleyBareTag'
289
292
290−berkeleyBareTag' :: OrgParser ()
293+berkeleyBareTag' :: PandocMonad m => OrgParser m ()
291berkeleyBareTag' = try $ void (string "cite")
294berkeleyBareTag' = try $ void (string "cite")
292
295
293−berkeleyTextualCite :: OrgParser (F [Citation])
296+berkeleyTextualCite :: PandocMonad m => OrgParser m (F [Citation])
294berkeleyTextualCite = try $ do
297berkeleyTextualCite = try $ do
295 (suppressAuthor, key) <- citeKey
298 (suppressAuthor, key) <- citeKey
296 returnF . return $ Citation
299 returnF . return $ Citation
@@ -305,14 +308,14 @@ berkeleyTextualCite = try $ do
305-- The following is what a Berkeley-style bracketed textual citation parser
308-- The following is what a Berkeley-style bracketed textual citation parser
306-- would look like. However, as these citations are a subset of Pandoc's Org
309-- would look like. However, as these citations are a subset of Pandoc's Org
307-- citation style, this isn't used.
310-- citation style, this isn't used.
308−-- berkeleyBracketedTextualCite :: OrgParser (F [Citation])
311+-- berkeleyBracketedTextualCite :: PandocMonad m => OrgParser m (F [Citation])
309-- berkeleyBracketedTextualCite = try . (fmap head) $
312-- berkeleyBracketedTextualCite = try . (fmap head) $
310-- enclosedByPair '[' ']' berkeleyTextualCite
313-- enclosedByPair '[' ']' berkeleyTextualCite
311
314
312-- | Read a link-like org-ref style citation. The citation includes pre and
315-- | Read a link-like org-ref style citation. The citation includes pre and
313-- post text. However, multiple citations are not possible due to limitations
316-- post text. However, multiple citations are not possible due to limitations
314-- in the syntax.
317-- in the syntax.
315−linkLikeOrgRefCite :: OrgParser (F Citation)
318+linkLikeOrgRefCite :: PandocMonad m => OrgParser m (F Citation)
316linkLikeOrgRefCite = try $ do
319linkLikeOrgRefCite = try $ do
317 _ <- string "[["
320 _ <- string "[["
318 mode <- orgRefCiteMode
321 mode <- orgRefCiteMode
@@ -335,13 +338,13 @@ linkLikeOrgRefCite = try $ do
335
338
336-- | Read a citation key. The characters allowed in citation keys are taken
339-- | Read a citation key. The characters allowed in citation keys are taken
337-- from the `org-ref-cite-re` variable in `org-ref.el`.
340-- from the `org-ref-cite-re` variable in `org-ref.el`.
338−orgRefCiteKey :: OrgParser String
341+orgRefCiteKey :: PandocMonad m => OrgParser m String
339orgRefCiteKey = try . many1 . satisfy $ \c ->
342orgRefCiteKey = try . many1 . satisfy $ \c ->
340 isAlphaNum c || c `elem` ("-_:\\./"::String)
343 isAlphaNum c || c `elem` ("-_:\\./"::String)
341
344
342-- | Supported citation types. Only a small subset of org-ref types is
345-- | Supported citation types. Only a small subset of org-ref types is
343-- supported for now. TODO: rewrite this, use LaTeX reader as template.
346-- supported for now. TODO: rewrite this, use LaTeX reader as template.
344−orgRefCiteMode :: OrgParser CitationMode
347+orgRefCiteMode :: PandocMonad m => OrgParser m CitationMode
345orgRefCiteMode =
348orgRefCiteMode =
346 choice $ map (\(s, mode) -> mode <$ try (string s <* char ':'))
349 choice $ map (\(s, mode) -> mode <$ try (string s <* char ':'))
347 [ ("cite", AuthorInText)
350 [ ("cite", AuthorInText)
@@ -352,10 +355,10 @@ orgRefCiteMode =
352 , ("citeyear", SuppressAuthor)
355 , ("citeyear", SuppressAuthor)
353 ]
356 ]
354
357
355−citeList :: OrgParser (F [Citation])
358+citeList :: PandocMonad m => OrgParser m (F [Citation])
356citeList = sequence <$> sepEndBy1 citation (try $ char ';' *> skipSpaces)
359citeList = sequence <$> sepEndBy1 citation (try $ char ';' *> skipSpaces)
357
360
358−citation :: OrgParser (F Citation)
361+citation :: PandocMonad m => OrgParser m (F Citation)
359citation = try $ do
362citation = try $ do
360 pref <- prefix
363 pref <- prefix
361 (suppress_author, key) <- citeKey
364 (suppress_author, key) <- citeKey
@@ -384,10 +387,10 @@ citation = try $ do
384 then (B.space <>) <$> rest
387 then (B.space <>) <$> rest
385 else rest
388 else rest
386
389
387−footnote :: OrgParser (F Inlines)
390+footnote :: PandocMonad m => OrgParser m (F Inlines)
388footnote = try $ inlineNote <|> referencedNote
391footnote = try $ inlineNote <|> referencedNote
389
392
390−inlineNote :: OrgParser (F Inlines)
393+inlineNote :: PandocMonad m => OrgParser m (F Inlines)
391inlineNote = try $ do
394inlineNote = try $ do
392 string "[fn:"
395 string "[fn:"
393 ref <- many alphaNum
396 ref <- many alphaNum
@@ -397,7 +400,7 @@ inlineNote = try $ do
397 addToNotesTable ("fn:" ++ ref, note)
400 addToNotesTable ("fn:" ++ ref, note)
398 return $ B.note <$> note
401 return $ B.note <$> note
399
402
400−referencedNote :: OrgParser (F Inlines)
403+referencedNote :: PandocMonad m => OrgParser m (F Inlines)
401referencedNote = try $ do
404referencedNote = try $ do
402 ref <- noteMarker
405 ref <- noteMarker
403 return $ do
406 return $ do
@@ -409,14 +412,14 @@ referencedNote = try $ do
409 let contents' = runF contents st{ orgStateNotes' = [] }
412 let contents' = runF contents st{ orgStateNotes' = [] }
410 return $ B.note contents'
413 return $ B.note contents'
411
414
412−linkOrImage :: OrgParser (F Inlines)
415+linkOrImage :: PandocMonad m => OrgParser m (F Inlines)
413linkOrImage = explicitOrImageLink
416linkOrImage = explicitOrImageLink
414 <|> selflinkOrImage
417 <|> selflinkOrImage
415 <|> angleLink
418 <|> angleLink
416 <|> plainLink
419 <|> plainLink
417 <?> "link or image"
420 <?> "link or image"
418
421
419−explicitOrImageLink :: OrgParser (F Inlines)
422+explicitOrImageLink :: PandocMonad m => OrgParser m (F Inlines)
420explicitOrImageLink = try $ do
423explicitOrImageLink = try $ do
421 char '['
424 char '['
422 srcF <- applyCustomLinkFormat =<< possiblyEmptyLinkTarget
425 srcF <- applyCustomLinkFormat =<< possiblyEmptyLinkTarget
@@ -431,30 +434,30 @@ explicitOrImageLink = try $ do
431 _ ->
434 _ ->
432 linkToInlinesF src =<< title'
435 linkToInlinesF src =<< title'
433
436
434−selflinkOrImage :: OrgParser (F Inlines)
437+selflinkOrImage :: PandocMonad m => OrgParser m (F Inlines)
435selflinkOrImage = try $ do
438selflinkOrImage = try $ do
436 src <- char '[' *> linkTarget <* char ']'
439 src <- char '[' *> linkTarget <* char ']'
437 return $ linkToInlinesF src (B.str src)
440 return $ linkToInlinesF src (B.str src)
438
441
439−plainLink :: OrgParser (F Inlines)
442+plainLink :: PandocMonad m => OrgParser m (F Inlines)
440plainLink = try $ do
443plainLink = try $ do
441 (orig, src) <- uri
444 (orig, src) <- uri
442 returnF $ B.link src "" (B.str orig)
445 returnF $ B.link src "" (B.str orig)
443
446
444−angleLink :: OrgParser (F Inlines)
447+angleLink :: PandocMonad m => OrgParser m (F Inlines)
445angleLink = try $ do
448angleLink = try $ do
446 char '<'
449 char '<'
447 link <- plainLink
450 link <- plainLink
448 char '>'
451 char '>'
449 return link
452 return link
450
453
451−linkTarget :: OrgParser String
454+linkTarget :: PandocMonad m => OrgParser m String
452linkTarget = enclosedByPair '[' ']' (noneOf "\n\r[]")
455linkTarget = enclosedByPair '[' ']' (noneOf "\n\r[]")
453
456
454−possiblyEmptyLinkTarget :: OrgParser String
457+possiblyEmptyLinkTarget :: PandocMonad m => OrgParser m String
455possiblyEmptyLinkTarget = try linkTarget <|> ("" <$ string "[]")
458possiblyEmptyLinkTarget = try linkTarget <|> ("" <$ string "[]")
456
459
457−applyCustomLinkFormat :: String -> OrgParser (F String)
460+applyCustomLinkFormat :: String -> OrgParser m (F String)
458applyCustomLinkFormat link = do
461applyCustomLinkFormat link = do
459 let (linkType, rest) = break (== ':') link
462 let (linkType, rest) = break (== ':') link
460 return $ do
463 return $ do
@@ -487,7 +490,7 @@ internalLink link title = do
487-- @anchor-id@ contains spaces, we are more restrictive in what is accepted as
490-- @anchor-id@ contains spaces, we are more restrictive in what is accepted as
488-- an anchor.
491-- an anchor.
489
492
490−anchor :: OrgParser (F Inlines)
493+anchor :: PandocMonad m => OrgParser m (F Inlines)
491anchor = try $ do
494anchor = try $ do
492 anchorId <- parseAnchor
495 anchorId <- parseAnchor
493 recordAnchorId anchorId
496 recordAnchorId anchorId
@@ -509,7 +512,7 @@ solidify = map replaceSpecialChar
509 | otherwise = '-'
512 | otherwise = '-'
510
513
511-- | Parses an inline code block and marks it as an babel block.
514-- | Parses an inline code block and marks it as an babel block.
512−inlineCodeBlock :: OrgParser (F Inlines)
515+inlineCodeBlock :: PandocMonad m => OrgParser m (F Inlines)
513inlineCodeBlock = try $ do
516inlineCodeBlock = try $ do
514 string "src_"
517 string "src_"
515 lang <- many1 orgArgWordChar
518 lang <- many1 orgArgWordChar
@@ -519,13 +522,13 @@ inlineCodeBlock = try $ do
519 let attrKeyVal = map toRundocAttrib (("language", lang) : opts)
522 let attrKeyVal = map toRundocAttrib (("language", lang) : opts)
520 returnF $ B.codeWith ("", attrClasses, attrKeyVal) inlineCode
523 returnF $ B.codeWith ("", attrClasses, attrKeyVal) inlineCode
521 where
524 where
522− inlineBlockOption :: OrgParser (String, String)
525+ inlineBlockOption :: PandocMonad m => OrgParser m (String, String)
523 inlineBlockOption = try $ do
526 inlineBlockOption = try $ do
524 argKey <- orgArgKey
527 argKey <- orgArgKey
525 paramValue <- option "yes" orgInlineParamValue
528 paramValue <- option "yes" orgInlineParamValue
526 return (argKey, paramValue)
529 return (argKey, paramValue)
527
530
528− orgInlineParamValue :: OrgParser String
531+ orgInlineParamValue :: PandocMonad m => OrgParser m String
529 orgInlineParamValue = try $
532 orgInlineParamValue = try $
530 skipSpaces
533 skipSpaces
531 *> notFollowedBy (char ':')
534 *> notFollowedBy (char ':')
@@ -533,7 +536,7 @@ inlineCodeBlock = try $ do
533 <* skipSpaces
536 <* skipSpaces
534
537
535
538
536−emphasizedText :: OrgParser (F Inlines)
539+emphasizedText :: PandocMonad m => OrgParser m (F Inlines)
537emphasizedText = do
540emphasizedText = do
538 state <- getState
541 state <- getState
539 guard . exportEmphasizedText . orgStateExportSettings $ state
542 guard . exportEmphasizedText . orgStateExportSettings $ state
@@ -544,60 +547,63 @@ emphasizedText = do
544 , underline
547 , underline
545 ]
548 ]
546
549
550+enclosedByPair :: PandocMonad m
547−enclosedByPair :: Char -- ^ opening char
551+ => Char -- ^ opening char
548 -> Char -- ^ closing char
552 -> Char -- ^ closing char
549− -> OrgParser a -- ^ parser
553+ -> OrgParser m a -- ^ parser
550− -> OrgParser [a]
554+ -> OrgParser m [a]
551enclosedByPair s e p = char s *> many1Till p (char e)
555enclosedByPair s e p = char s *> many1Till p (char e)
552
556
553−emph :: OrgParser (F Inlines)
557+emph :: PandocMonad m => OrgParser m (F Inlines)
554emph = fmap B.emph <$> emphasisBetween '/'
558emph = fmap B.emph <$> emphasisBetween '/'
555
559
556−strong :: OrgParser (F Inlines)
560+strong :: PandocMonad m => OrgParser m (F Inlines)
557strong = fmap B.strong <$> emphasisBetween '*'
561strong = fmap B.strong <$> emphasisBetween '*'
558
562
559−strikeout :: OrgParser (F Inlines)
563+strikeout :: PandocMonad m => OrgParser m (F Inlines)
560strikeout = fmap B.strikeout <$> emphasisBetween '+'
564strikeout = fmap B.strikeout <$> emphasisBetween '+'
561
565
562-- There is no underline, so we use strong instead.
566-- There is no underline, so we use strong instead.
563−underline :: OrgParser (F Inlines)
567+underline :: PandocMonad m => OrgParser m (F Inlines)
564underline = fmap B.strong <$> emphasisBetween '_'
568underline = fmap B.strong <$> emphasisBetween '_'
565
569
566−verbatim :: OrgParser (F Inlines)
570+verbatim :: PandocMonad m => OrgParser m (F Inlines)
567verbatim = return . B.code <$> verbatimBetween '='
571verbatim = return . B.code <$> verbatimBetween '='
568
572
569−code :: OrgParser (F Inlines)
573+code :: PandocMonad m => OrgParser m (F Inlines)
570code = return . B.code <$> verbatimBetween '~'
574code = return . B.code <$> verbatimBetween '~'
571
575
572−subscript :: OrgParser (F Inlines)
576+subscript :: PandocMonad m => OrgParser m (F Inlines)
573subscript = fmap B.subscript <$> try (char '_' *> subOrSuperExpr)
577subscript = fmap B.subscript <$> try (char '_' *> subOrSuperExpr)
574
578
575−superscript :: OrgParser (F Inlines)
579+superscript :: PandocMonad m => OrgParser m (F Inlines)
576superscript = fmap B.superscript <$> try (char '^' *> subOrSuperExpr)
580superscript = fmap B.superscript <$> try (char '^' *> subOrSuperExpr)
577
581
578−math :: OrgParser (F Inlines)
582+math :: PandocMonad m => OrgParser m (F Inlines)
579math = return . B.math <$> choice [ math1CharBetween '$'
583math = return . B.math <$> choice [ math1CharBetween '$'
580 , mathStringBetween '$'
584 , mathStringBetween '$'
581 , rawMathBetween "\\(" "\\)"
585 , rawMathBetween "\\(" "\\)"
582 ]
586 ]
583
587
584−displayMath :: OrgParser (F Inlines)
588+displayMath :: PandocMonad m => OrgParser m (F Inlines)
585displayMath = return . B.displayMath <$> choice [ rawMathBetween "\\[" "\\]"
589displayMath = return . B.displayMath <$> choice [ rawMathBetween "\\[" "\\]"
586 , rawMathBetween "$$" "$$"
590 , rawMathBetween "$$" "$$"
587 ]
591 ]
588
592
589−updatePositions :: Char
593+updatePositions :: PandocMonad m
594+ => Char
590− -> OrgParser Char
595+ -> OrgParser m Char
591updatePositions c = do
596updatePositions c = do
592 when (c `elem` emphasisPreChars) updateLastPreCharPos
597 when (c `elem` emphasisPreChars) updateLastPreCharPos
593 when (c `elem` emphasisForbiddenBorderChars) updateLastForbiddenCharPos
598 when (c `elem` emphasisForbiddenBorderChars) updateLastForbiddenCharPos
594 return c
599 return c
595
600
596−symbol :: OrgParser (F Inlines)
601+symbol :: PandocMonad m => OrgParser m (F Inlines)
597symbol = return . B.str . (: "") <$> (oneOf specialChars >>= updatePositions)
602symbol = return . B.str . (: "") <$> (oneOf specialChars >>= updatePositions)
598
603
599−emphasisBetween :: Char
604+emphasisBetween :: PandocMonad m
605+ => Char
600− -> OrgParser (F Inlines)
606+ -> OrgParser m (F Inlines)
601emphasisBetween c = try $ do
607emphasisBetween c = try $ do
602 startEmphasisNewlinesCounting emphasisAllowedNewlines
608 startEmphasisNewlinesCounting emphasisAllowedNewlines
603 res <- enclosedInlines (emphasisStart c) (emphasisEnd c)
609 res <- enclosedInlines (emphasisStart c) (emphasisEnd c)
@@ -606,8 +612,9 @@ emphasisBetween c = try $ do
606 resetEmphasisNewlines
612 resetEmphasisNewlines
607 return res
613 return res
608
614
609−verbatimBetween :: Char
615+verbatimBetween :: PandocMonad m
616+ => Char
610− -> OrgParser String
617+ -> OrgParser m String
611verbatimBetween c = try $
618verbatimBetween c = try $
612 emphasisStart c *>
619 emphasisStart c *>
613 many1TillNOrLessNewlines 1 verbatimChar (emphasisEnd c)
620 many1TillNOrLessNewlines 1 verbatimChar (emphasisEnd c)
@@ -615,8 +622,9 @@ verbatimBetween c = try $
615 verbatimChar = noneOf "\n\r" >>= updatePositions
622 verbatimChar = noneOf "\n\r" >>= updatePositions
616
623
617-- | Parses a raw string delimited by @c@ using Org's math rules
624-- | Parses a raw string delimited by @c@ using Org's math rules
618−mathStringBetween :: Char
625+mathStringBetween :: PandocMonad m
626+ => Char
619− -> OrgParser String
627+ -> OrgParser m String
620mathStringBetween c = try $ do
628mathStringBetween c = try $ do
621 mathStart c
629 mathStart c
622 body <- many1TillNOrLessNewlines mathAllowedNewlines
630 body <- many1TillNOrLessNewlines mathAllowedNewlines
@@ -626,8 +634,9 @@ mathStringBetween c = try $ do
626 return $ body ++ [final]
634 return $ body ++ [final]
627
635
628-- | Parse a single character between @c@ using math rules
636-- | Parse a single character between @c@ using math rules
629−math1CharBetween :: Char
637+math1CharBetween :: PandocMonad m
638+ => Char
630− -> OrgParser String
639+ -> OrgParser m String
631math1CharBetween c = try $ do
640math1CharBetween c = try $ do
632 char c
641 char c
633 res <- noneOf $ c:mathForbiddenBorderChars
642 res <- noneOf $ c:mathForbiddenBorderChars
@@ -635,13 +644,14 @@ math1CharBetween c = try $ do
635 eof <|> () <$ lookAhead (oneOf mathPostChars)
644 eof <|> () <$ lookAhead (oneOf mathPostChars)
636 return [res]
645 return [res]
637
646
638−rawMathBetween :: String
647+rawMathBetween :: PandocMonad m
648+ => String
639 -> String
649 -> String
640− -> OrgParser String
650+ -> OrgParser m String
641rawMathBetween s e = try $ string s *> manyTill anyChar (try $ string e)
651rawMathBetween s e = try $ string s *> manyTill anyChar (try $ string e)
642
652
643-- | Parses the start (opening character) of emphasis
653-- | Parses the start (opening character) of emphasis
644−emphasisStart :: Char -> OrgParser Char
654+emphasisStart :: PandocMonad m => Char -> OrgParser m Char
645emphasisStart c = try $ do
655emphasisStart c = try $ do
646 guard =<< afterEmphasisPreChar
656 guard =<< afterEmphasisPreChar
647 guard =<< notAfterString
657 guard =<< notAfterString
@@ -654,7 +664,7 @@ emphasisStart c = try $ do
654 return c
664 return c
655
665
656-- | Parses the closing character of emphasis
666-- | Parses the closing character of emphasis
657−emphasisEnd :: Char -> OrgParser Char
667+emphasisEnd :: PandocMonad m => Char -> OrgParser m Char
658emphasisEnd c = try $ do
668emphasisEnd c = try $ do
659 guard =<< notAfterForbiddenBorderChar
669 guard =<< notAfterForbiddenBorderChar
660 char c
670 char c
@@ -665,11 +675,11 @@ emphasisEnd c = try $ do
665 where acceptablePostChars =
675 where acceptablePostChars =
666 surroundingEmphasisChar >>= \x -> oneOf (x ++ emphasisPostChars)
676 surroundingEmphasisChar >>= \x -> oneOf (x ++ emphasisPostChars)
667
677
668−mathStart :: Char -> OrgParser Char
678+mathStart :: PandocMonad m => Char -> OrgParser m Char
669mathStart c = try $
679mathStart c = try $
670 char c <* notFollowedBy' (oneOf (c:mathForbiddenBorderChars))
680 char c <* notFollowedBy' (oneOf (c:mathForbiddenBorderChars))
671
681
672−mathEnd :: Char -> OrgParser Char
682+mathEnd :: PandocMonad m => Char -> OrgParser m Char
673mathEnd c = try $ do
683mathEnd c = try $ do
674 res <- noneOf (c:mathForbiddenBorderChars)
684 res <- noneOf (c:mathForbiddenBorderChars)
675 char c
685 char c
@@ -677,15 +687,15 @@ mathEnd c = try $ do
677 return res
687 return res
678
688
679
689
680−enclosedInlines :: OrgParser a
690+enclosedInlines :: PandocMonad m => OrgParser m a
681− -> OrgParser b
691+ -> OrgParser m b
682− -> OrgParser (F Inlines)
692+ -> OrgParser m (F Inlines)
683enclosedInlines start end = try $
693enclosedInlines start end = try $
684 trimInlinesF . mconcat <$> enclosed start end inline
694 trimInlinesF . mconcat <$> enclosed start end inline
685
695
686−enclosedRaw :: OrgParser a
696+enclosedRaw :: PandocMonad m => OrgParser m a
687− -> OrgParser b
697+ -> OrgParser m b
688− -> OrgParser String
698+ -> OrgParser m String
689enclosedRaw start end = try $
699enclosedRaw start end = try $
690 start *> (onSingleLine <|> spanningTwoLines)
700 start *> (onSingleLine <|> spanningTwoLines)
691 where onSingleLine = try $ many1Till (noneOf "\n\r") end
701 where onSingleLine = try $ many1Till (noneOf "\n\r") end
@@ -694,10 +704,10 @@ enclosedRaw start end = try $
694
704
695-- | Like many1Till, but parses at most @n+1@ lines. @p@ must not consume
705-- | Like many1Till, but parses at most @n+1@ lines. @p@ must not consume
696-- newlines.
706-- newlines.
697−many1TillNOrLessNewlines :: Int
707+many1TillNOrLessNewlines :: PandocMonad m => Int
698− -> OrgParser Char
708+ -> OrgParser m Char
699− -> OrgParser a
709+ -> OrgParser m a
700− -> OrgParser String
710+ -> OrgParser m String
701many1TillNOrLessNewlines n p end = try $
711many1TillNOrLessNewlines n p end = try $
702 nMoreLines (Just n) mempty >>= oneOrMore
712 nMoreLines (Just n) mempty >>= oneOrMore
703 where
713 where
@@ -746,21 +756,21 @@ mathAllowedNewlines :: Int
746mathAllowedNewlines = 2
756mathAllowedNewlines = 2
747
757
748-- | Whether we are right behind a char allowed before emphasis
758-- | Whether we are right behind a char allowed before emphasis
749−afterEmphasisPreChar :: OrgParser Bool
759+afterEmphasisPreChar :: PandocMonad m => OrgParser m Bool
750afterEmphasisPreChar = do
760afterEmphasisPreChar = do
751 pos <- getPosition
761 pos <- getPosition
752 lastPrePos <- orgStateLastPreCharPos <$> getState
762 lastPrePos <- orgStateLastPreCharPos <$> getState
753 return . fromMaybe True $ (== pos) <$> lastPrePos
763 return . fromMaybe True $ (== pos) <$> lastPrePos
754
764
755-- | Whether the parser is right after a forbidden border char
765-- | Whether the parser is right after a forbidden border char
756−notAfterForbiddenBorderChar :: OrgParser Bool
766+notAfterForbiddenBorderChar :: PandocMonad m => OrgParser m Bool
757notAfterForbiddenBorderChar = do
767notAfterForbiddenBorderChar = do
758 pos <- getPosition
768 pos <- getPosition
759 lastFBCPos <- orgStateLastForbiddenCharPos <$> getState
769 lastFBCPos <- orgStateLastForbiddenCharPos <$> getState
760 return $ lastFBCPos /= Just pos
770 return $ lastFBCPos /= Just pos
761
771
762-- | Read a sub- or superscript expression
772-- | Read a sub- or superscript expression
763−subOrSuperExpr :: OrgParser (F Inlines)
773+subOrSuperExpr :: PandocMonad m => OrgParser m (F Inlines)
764subOrSuperExpr = try $
774subOrSuperExpr = try $
765 choice [ id <$> charsInBalanced '{' '}' (noneOf "\n\r")
775 choice [ id <$> charsInBalanced '{' '}' (noneOf "\n\r")
766 , enclosing ('(', ')') <$> charsInBalanced '(' ')' (noneOf "\n\r")
776 , enclosing ('(', ')') <$> charsInBalanced '(' ')' (noneOf "\n\r")
@@ -768,7 +778,7 @@ subOrSuperExpr = try $
768 ] >>= parseFromString (mconcat <$> many inline)
778 ] >>= parseFromString (mconcat <$> many inline)
769 where enclosing (left, right) s = left : s ++ [right]
779 where enclosing (left, right) s = left : s ++ [right]
770
780
771−simpleSubOrSuperString :: OrgParser String
781+simpleSubOrSuperString :: PandocMonad m => OrgParser m String
772simpleSubOrSuperString = try $ do
782simpleSubOrSuperString = try $ do
773 state <- getState
783 state <- getState
774 guard . exportSubSuperscripts . orgStateExportSettings $ state
784 guard . exportSubSuperscripts . orgStateExportSettings $ state
@@ -777,17 +787,18 @@ simpleSubOrSuperString = try $ do
777 <*> many1 alphaNum
787 <*> many1 alphaNum
778 ]
788 ]
779
789
780−inlineLaTeX :: OrgParser (F Inlines)
790+inlineLaTeX :: PandocMonad m => OrgParser m (F Inlines)
781inlineLaTeX = try $ do
791inlineLaTeX = try $ do
782 cmd <- inlineLaTeXCommand
792 cmd <- inlineLaTeXCommand
793+ ils <- (lift . lift) $ parseAsInlineLaTeX cmd
783 maybe mzero returnF $
794 maybe mzero returnF $
784− parseAsMath cmd `mplus` parseAsMathMLSym cmd `mplus` parseAsInlineLaTeX cmd
795+ parseAsMath cmd `mplus` parseAsMathMLSym cmd `mplus` ils
785 where
796 where
786 parseAsMath :: String -> Maybe Inlines
797 parseAsMath :: String -> Maybe Inlines
787 parseAsMath cs = B.fromList <$> texMathToPandoc cs
798 parseAsMath cs = B.fromList <$> texMathToPandoc cs
788
799
789− parseAsInlineLaTeX :: String -> Maybe Inlines
800+ parseAsInlineLaTeX :: PandocMonad m => String -> m (Maybe Inlines)
790− parseAsInlineLaTeX cs = maybeRight $ runParser inlineCommand state "" cs
801+ parseAsInlineLaTeX cs = maybeRight <$> runParserT inlineCommand state "" cs
791
802
792 parseAsMathMLSym :: String -> Maybe Inlines
803 parseAsMathMLSym :: String -> Maybe Inlines
793 parseAsMathMLSym cs = B.str <$> MathMLEntityMap.getUnicode (clean cs)
804 parseAsMathMLSym cs = B.str <$> MathMLEntityMap.getUnicode (clean cs)
@@ -803,10 +814,11 @@ inlineLaTeX = try $ do
803maybeRight :: Either a b -> Maybe b
814maybeRight :: Either a b -> Maybe b
804maybeRight = either (const Nothing) Just
815maybeRight = either (const Nothing) Just
805
816
806−inlineLaTeXCommand :: OrgParser String
817+inlineLaTeXCommand :: PandocMonad m => OrgParser m String
807inlineLaTeXCommand = try $ do
818inlineLaTeXCommand = try $ do
808 rest <- getInput
819 rest <- getInput
809− case runParser rawLaTeXInline def "source" rest of
820+ parsed <- (lift . lift) $ runParserT rawLaTeXInline def "source" rest
821+ case parsed of
810 Right (RawInline _ cs) -> do
822 Right (RawInline _ cs) -> do
811 -- drop any trailing whitespace, those are not be part of the command as
823 -- drop any trailing whitespace, those are not be part of the command as
812 -- far as org mode is concerned.
824 -- far as org mode is concerned.
@@ -820,14 +832,14 @@ inlineLaTeXCommand = try $ do
820dropWhileEnd :: (a -> Bool) -> [a] -> [a]
832dropWhileEnd :: (a -> Bool) -> [a] -> [a]
821dropWhileEnd p = foldr (\x xs -> if p x && null xs then [] else x : xs) []
833dropWhileEnd p = foldr (\x xs -> if p x && null xs then [] else x : xs) []
822
834
823−exportSnippet :: OrgParser (F Inlines)
835+exportSnippet :: PandocMonad m => OrgParser m (F Inlines)
824exportSnippet = try $ do
836exportSnippet = try $ do
825 string "@@"
837 string "@@"
826 format <- many1Till (alphaNum <|> char '-') (char ':')
838 format <- many1Till (alphaNum <|> char '-') (char ':')
827 snippet <- manyTill anyChar (try $ string "@@")
839 snippet <- manyTill anyChar (try $ string "@@")
828 returnF $ B.rawInline format snippet
840 returnF $ B.rawInline format snippet
829
841
830−smart :: OrgParser (F Inlines)
842+smart :: PandocMonad m => OrgParser m (F Inlines)
831smart = do
843smart = do
832 getOption readerSmart >>= guard
844 getOption readerSmart >>= guard
833 doubleQuoted <|> singleQuoted <|>
845 doubleQuoted <|> singleQuoted <|>
@@ -844,7 +856,7 @@ smart = do
844 <* updateLastForbiddenCharPos
856 <* updateLastForbiddenCharPos
845 *> return (B.str "\x2019")
857 *> return (B.str "\x2019")
846
858
847−singleQuoted :: OrgParser (F Inlines)
859+singleQuoted :: PandocMonad m => OrgParser m (F Inlines)
848singleQuoted = try $ do
860singleQuoted = try $ do
849 guard =<< getExportSetting exportSmartQuotes
861 guard =<< getExportSetting exportSmartQuotes
850 singleQuoteStart
862 singleQuoteStart
@@ -856,7 +868,7 @@ singleQuoted = try $ do
856-- doubleQuoted will handle regular double-quoted sections, as well
868-- doubleQuoted will handle regular double-quoted sections, as well
857-- as dialogues with an open double-quote without a close double-quote
869-- as dialogues with an open double-quote without a close double-quote
858-- in the same paragraph.
870-- in the same paragraph.
859−doubleQuoted :: OrgParser (F Inlines)
871+doubleQuoted :: PandocMonad m => OrgParser m (F Inlines)
860doubleQuoted = try $ do
872doubleQuoted = try $ do
861 guard =<< getExportSetting exportSmartQuotes
873 guard =<< getExportSetting exportSmartQuotes
862 doubleQuoteStart
874 doubleQuoteStart
src/Text/Pandoc/Readers/Org/Meta.hs+23−22
@@ -41,6 +41,7 @@ import Text.Pandoc.Readers.Org.Parsing
41
41
42import qualified Text.Pandoc.Builder as B
42import qualified Text.Pandoc.Builder as B
43import Text.Pandoc.Builder ( Blocks, Inlines )
43import Text.Pandoc.Builder ( Blocks, Inlines )
44+import Text.Pandoc.Class ( PandocMonad )
44import Text.Pandoc.Definition
45import Text.Pandoc.Definition
45
46
46import Control.Monad ( mzero, void )
47import Control.Monad ( mzero, void )
@@ -51,7 +52,7 @@ import Data.Monoid ( (<>) )
51import Network.HTTP ( urlEncode )
52import Network.HTTP ( urlEncode )
52
53
53-- | Returns the current meta, respecting export options.
54-- | Returns the current meta, respecting export options.
54−metaExport :: OrgParser (F Meta)
55+metaExport :: Monad m => OrgParser m (F Meta)
55metaExport = do
56metaExport = do
56 st <- getState
57 st <- getState
57 let settings = orgStateExportSettings st
58 let settings = orgStateExportSettings st
@@ -68,10 +69,10 @@ removeMeta key meta' =
68-- | Parse and handle a single line containing meta information
69-- | Parse and handle a single line containing meta information
69-- The order, in which blocks are tried, makes sure that we're not looking at
70-- The order, in which blocks are tried, makes sure that we're not looking at
70-- the beginning of a block, so we don't need to check for it
71-- the beginning of a block, so we don't need to check for it
71−metaLine :: OrgParser Blocks
72+metaLine :: PandocMonad m => OrgParser m Blocks
72metaLine = mempty <$ metaLineStart <* (optionLine <|> declarationLine)
73metaLine = mempty <$ metaLineStart <* (optionLine <|> declarationLine)
73
74
74−declarationLine :: OrgParser ()
75+declarationLine :: PandocMonad m => OrgParser m ()
75declarationLine = try $ do
76declarationLine = try $ do
76 key <- map toLower <$> metaKey
77 key <- map toLower <$> metaKey
77 (key', value) <- metaValue key
78 (key', value) <- metaValue key
@@ -79,12 +80,12 @@ declarationLine = try $ do
79 let meta' = B.setMeta key' <$> value <*> pure nullMeta
80 let meta' = B.setMeta key' <$> value <*> pure nullMeta
80 in st { orgStateMeta = meta' <> orgStateMeta st }
81 in st { orgStateMeta = meta' <> orgStateMeta st }
81
82
82−metaKey :: OrgParser String
83+metaKey :: Monad m => OrgParser m String
83metaKey = map toLower <$> many1 (noneOf ": \n\r")
84metaKey = map toLower <$> many1 (noneOf ": \n\r")
84 <* char ':'
85 <* char ':'
85 <* skipSpaces
86 <* skipSpaces
86
87
87−metaValue :: String -> OrgParser (String, (F MetaValue))
88+metaValue :: PandocMonad m => String -> OrgParser m (String, (F MetaValue))
88metaValue key =
89metaValue key =
89 let inclKey = "header-includes"
90 let inclKey = "header-includes"
90 in case key of
91 in case key of
@@ -103,10 +104,10 @@ metaValue key =
103 accumulatingList inclKey (metaExportSnippet "html")
104 accumulatingList inclKey (metaExportSnippet "html")
104 _ -> (key,) <$> metaString
105 _ -> (key,) <$> metaString
105
106
106−metaInlines :: OrgParser (F MetaValue)
107+metaInlines :: PandocMonad m => OrgParser m (F MetaValue)
107metaInlines = fmap (MetaInlines . B.toList) <$> inlinesTillNewline
108metaInlines = fmap (MetaInlines . B.toList) <$> inlinesTillNewline
108
109
109−metaInlinesCommaSeparated :: OrgParser (F MetaValue)
110+metaInlinesCommaSeparated :: PandocMonad m => OrgParser m (F MetaValue)
110metaInlinesCommaSeparated = do
111metaInlinesCommaSeparated = do
111 authStrs <- (many1 (noneOf ",\n")) `sepBy1` (char ',')
112 authStrs <- (many1 (noneOf ",\n")) `sepBy1` (char ',')
112 newline
113 newline
@@ -114,21 +115,21 @@ metaInlinesCommaSeparated = do
114 let toMetaInlines = MetaInlines . B.toList
115 let toMetaInlines = MetaInlines . B.toList
115 return $ MetaList . map toMetaInlines <$> sequence authors
116 return $ MetaList . map toMetaInlines <$> sequence authors
116
117
117−metaString :: OrgParser (F MetaValue)
118+metaString :: Monad m => OrgParser m (F MetaValue)
118metaString = metaModifiedString id
119metaString = metaModifiedString id
119
120
120−metaModifiedString :: (String -> String) -> OrgParser (F MetaValue)
121+metaModifiedString :: Monad m => (String -> String) -> OrgParser m (F MetaValue)
121metaModifiedString f = return . MetaString . f <$> anyLine
122metaModifiedString f = return . MetaString . f <$> anyLine
122
123
123-- | Read an format specific meta definition
124-- | Read an format specific meta definition
124−metaExportSnippet :: String -> OrgParser (F MetaValue)
125+metaExportSnippet :: Monad m => String -> OrgParser m (F MetaValue)
125metaExportSnippet format =
126metaExportSnippet format =
126 return . MetaInlines . B.toList . B.rawInline format <$> anyLine
127 return . MetaInlines . B.toList . B.rawInline format <$> anyLine
127
128
128-- | Accumulate the result of the @parser@ in a list under @key@.
129-- | Accumulate the result of the @parser@ in a list under @key@.
129−accumulatingList :: String
130+accumulatingList :: Monad m => String
130− -> OrgParser (F MetaValue)
131+ -> OrgParser m (F MetaValue)
131− -> OrgParser (F MetaValue)
132+ -> OrgParser m (F MetaValue)
132accumulatingList key p = do
133accumulatingList key p = do
133 value <- p
134 value <- p
134 meta' <- orgStateMeta <$> getState
135 meta' <- orgStateMeta <$> getState
@@ -141,7 +142,7 @@ accumulatingList key p = do
141--
142--
142-- export options
143-- export options
143--
144--
144−optionLine :: OrgParser ()
145+optionLine :: Monad m => OrgParser m ()
145optionLine = try $ do
146optionLine = try $ do
146 key <- metaKey
147 key <- metaKey
147 case key of
148 case key of
@@ -152,14 +153,14 @@ optionLine = try $ do
152 "typ_todo" -> todoSequence >>= updateState . registerTodoSequence
153 "typ_todo" -> todoSequence >>= updateState . registerTodoSequence
153 _ -> mzero
154 _ -> mzero
154
155
155−addLinkFormat :: String
156+addLinkFormat :: Monad m => String
156 -> (String -> String)
157 -> (String -> String)
157− -> OrgParser ()
158+ -> OrgParser m ()
158addLinkFormat key formatter = updateState $ \s ->
159addLinkFormat key formatter = updateState $ \s ->
159 let fs = orgStateLinkFormatters s
160 let fs = orgStateLinkFormatters s
160 in s{ orgStateLinkFormatters = M.insert key formatter fs }
161 in s{ orgStateLinkFormatters = M.insert key formatter fs }
161
162
162−parseLinkFormat :: OrgParser ((String, String -> String))
163+parseLinkFormat :: Monad m => OrgParser m ((String, String -> String))
163parseLinkFormat = try $ do
164parseLinkFormat = try $ do
164 linkType <- (:) <$> letter <*> many (alphaNum <|> oneOf "-_") <* skipSpaces
165 linkType <- (:) <$> letter <*> many (alphaNum <|> oneOf "-_") <* skipSpaces
165 linkSubst <- parseFormat
166 linkSubst <- parseFormat
@@ -167,7 +168,7 @@ parseLinkFormat = try $ do
167
168
168-- | An ad-hoc, single-argument-only implementation of a printf-style format
169-- | An ad-hoc, single-argument-only implementation of a printf-style format
169-- parser.
170-- parser.
170−parseFormat :: OrgParser (String -> String)
171+parseFormat :: Monad m => OrgParser m (String -> String)
171parseFormat = try $ do
172parseFormat = try $ do
172 replacePlain <|> replaceUrl <|> justAppend
173 replacePlain <|> replaceUrl <|> justAppend
173 where
174 where
@@ -181,13 +182,13 @@ parseFormat = try $ do
181 rest = manyTill anyChar (eof <|> () <$ oneOf "\n\r")
182 rest = manyTill anyChar (eof <|> () <$ oneOf "\n\r")
182 tillSpecifier c = manyTill (noneOf "\n\r") (try $ string ('%':c:""))
183 tillSpecifier c = manyTill (noneOf "\n\r") (try $ string ('%':c:""))
183
184
184−inlinesTillNewline :: OrgParser (F Inlines)
185+inlinesTillNewline :: PandocMonad m => OrgParser m (F Inlines)
185inlinesTillNewline = trimInlinesF . mconcat <$> manyTill inline newline
186inlinesTillNewline = trimInlinesF . mconcat <$> manyTill inline newline
186
187
187--
188--
188-- ToDo Sequences and Keywords
189-- ToDo Sequences and Keywords
189--
190--
190−todoSequence :: OrgParser TodoSequence
191+todoSequence :: Monad m => OrgParser m TodoSequence
191todoSequence = try $ do
192todoSequence = try $ do
192 todoKws <- todoKeywords
193 todoKws <- todoKeywords
193 doneKws <- optionMaybe $ todoDoneSep *> todoKeywords
194 doneKws <- optionMaybe $ todoDoneSep *> todoKeywords
@@ -201,13 +202,13 @@ todoSequence = try $ do
201 (x:xs) -> return $ keywordsToSequence (reverse xs) [x]
202 (x:xs) -> return $ keywordsToSequence (reverse xs) [x]
202
203
203 where
204 where
204− todoKeywords :: OrgParser [String]
205+ todoKeywords :: Monad m => OrgParser m [String]
205 todoKeywords = try $
206 todoKeywords = try $
206 let keyword = many1 nonspaceChar <* skipSpaces
207 let keyword = many1 nonspaceChar <* skipSpaces
207 endOfKeywords = todoDoneSep <|> void newline
208 endOfKeywords = todoDoneSep <|> void newline
208 in manyTill keyword (lookAhead endOfKeywords)
209 in manyTill keyword (lookAhead endOfKeywords)
209
210
210− todoDoneSep :: OrgParser ()
211+ todoDoneSep :: Monad m => OrgParser m ()
211 todoDoneSep = void . try $ skipSpaces *> char '|' <* skipSpaces1
212 todoDoneSep = void . try $ skipSpaces *> char '|' <* skipSpaces1
212
213
213 keywordsToSequence :: [String] -> [String] -> TodoSequence
214 keywordsToSequence :: [String] -> [String] -> TodoSequence
src/Text/Pandoc/Readers/Org/ParserState.hs+2−2
@@ -51,7 +51,7 @@ module Text.Pandoc.Readers.Org.ParserState
51 ) where
51 ) where
52
52
53import Control.Monad (liftM, liftM2)
53import Control.Monad (liftM, liftM2)
54−import Control.Monad.Reader (Reader, runReader, ask, asks, local)
54+import Control.Monad.Reader (Reader, runReader, ReaderT, ask, asks, local)
55
55
56import Data.Default (Default(..))
56import Data.Default (Default(..))
57import qualified Data.Map as M
57import qualified Data.Map as M
@@ -122,7 +122,7 @@ instance HasLastStrPosition OrgParserState where
122 getLastStrPos = orgStateLastStrPos
122 getLastStrPos = orgStateLastStrPos
123 setLastStrPos pos st = st{ orgStateLastStrPos = Just pos }
123 setLastStrPos pos st = st{ orgStateLastStrPos = Just pos }
124
124
125−instance HasQuoteContext st (Reader OrgParserLocal) where
125+instance Monad m => HasQuoteContext st (ReaderT OrgParserLocal m) where
126 getQuoteContext = asks orgLocalQuoteContext
126 getQuoteContext = asks orgLocalQuoteContext
127 withQuoteContext q = local (\s -> s{orgLocalQuoteContext = q})
127 withQuoteContext q = local (\s -> s{orgLocalQuoteContext = q})
128
128
src/Text/Pandoc/Readers/Org/Parsing.hs+19−17
@@ -72,6 +72,7 @@ module Text.Pandoc.Readers.Org.Parsing
72 , citeKey
72 , citeKey
73 -- * Re-exports from Text.Pandoc.Parsec
73 -- * Re-exports from Text.Pandoc.Parsec
74 , runParser
74 , runParser
75+ , runParserT
75 , getInput
76 , getInput
76 , char
77 , char
77 , letter
78 , letter
@@ -114,17 +115,17 @@ import Text.Pandoc.Parsing hiding ( anyLine, blanklines, newline
114 , parseFromString )
115 , parseFromString )
115
116
116import Control.Monad ( guard )
117import Control.Monad ( guard )
117−import Control.Monad.Reader ( Reader )
118+import Control.Monad.Reader ( ReaderT )
118
119
119-- | The parser used to read org files.
120-- | The parser used to read org files.
120−type OrgParser = ParserT [Char] OrgParserState (Reader OrgParserLocal)
121+type OrgParser m = ParserT [Char] OrgParserState (ReaderT OrgParserLocal m)
121
122
122--
123--
123-- Adaptions and specializations of parsing utilities
124-- Adaptions and specializations of parsing utilities
124--
125--
125
126
126-- | Parse any line of text
127-- | Parse any line of text
127−anyLine :: OrgParser String
128+anyLine :: Monad m => OrgParser m String
128anyLine =
129anyLine =
129 P.anyLine
130 P.anyLine
130 <* updateLastPreCharPos
131 <* updateLastPreCharPos
@@ -132,7 +133,7 @@ anyLine =
132
133
133-- The version Text.Pandoc.Parsing cannot be used, as we need additional parts
134-- The version Text.Pandoc.Parsing cannot be used, as we need additional parts
134-- of the state saved and restored.
135-- of the state saved and restored.
135−parseFromString :: OrgParser a -> String -> OrgParser a
136+parseFromString :: Monad m => OrgParser m a -> String -> OrgParser m a
136parseFromString parser str' = do
137parseFromString parser str' = do
137 oldLastPreCharPos <- orgStateLastPreCharPos <$> getState
138 oldLastPreCharPos <- orgStateLastPreCharPos <$> getState
138 updateState $ \s -> s{ orgStateLastPreCharPos = Nothing }
139 updateState $ \s -> s{ orgStateLastPreCharPos = Nothing }
@@ -141,33 +142,34 @@ parseFromString parser str' = do
141 return result
142 return result
142
143
143-- | Skip one or more tab or space characters.
144-- | Skip one or more tab or space characters.
144−skipSpaces1 :: OrgParser ()
145+skipSpaces1 :: Monad m => OrgParser m ()
145skipSpaces1 = skipMany1 spaceChar
146skipSpaces1 = skipMany1 spaceChar
146
147
147-- | Like @Text.Parsec.Char.newline@, but causes additional state changes.
148-- | Like @Text.Parsec.Char.newline@, but causes additional state changes.
148−newline :: OrgParser Char
149+newline :: Monad m => OrgParser m Char
149newline =
150newline =
150 P.newline
151 P.newline
151 <* updateLastPreCharPos
152 <* updateLastPreCharPos
152 <* updateLastForbiddenCharPos
153 <* updateLastForbiddenCharPos
153
154
154-- | Like @Text.Parsec.Char.blanklines@, but causes additional state changes.
155-- | Like @Text.Parsec.Char.blanklines@, but causes additional state changes.
155−blanklines :: OrgParser [Char]
156+blanklines :: Monad m => OrgParser m [Char]
156blanklines =
157blanklines =
157 P.blanklines
158 P.blanklines
158 <* updateLastPreCharPos
159 <* updateLastPreCharPos
159 <* updateLastForbiddenCharPos
160 <* updateLastForbiddenCharPos
160
161
161-- | Succeeds when we're in list context.
162-- | Succeeds when we're in list context.
162−inList :: OrgParser ()
163+inList :: Monad m => OrgParser m ()
163inList = do
164inList = do
164 ctx <- orgStateParserContext <$> getState
165 ctx <- orgStateParserContext <$> getState
165 guard (ctx == ListItemState)
166 guard (ctx == ListItemState)
166
167
167-- | Parse in different context
168-- | Parse in different context
169+withContext :: Monad m
168−withContext :: ParserContext -- ^ New parser context
170+ => ParserContext -- ^ New parser context
169− -> OrgParser a -- ^ Parser to run in that context
171+ -> OrgParser m a -- ^ Parser to run in that context
170− -> OrgParser a
172+ -> OrgParser m a
171withContext context parser = do
173withContext context parser = do
172 oldContext <- orgStateParserContext <$> getState
174 oldContext <- orgStateParserContext <$> getState
173 updateState $ \s -> s{ orgStateParserContext = context }
175 updateState $ \s -> s{ orgStateParserContext = context }
@@ -180,19 +182,19 @@ withContext context parser = do
180--
182--
181
183
182-- | Get an export setting.
184-- | Get an export setting.
183−getExportSetting :: (ExportSettings -> a) -> OrgParser a
185+getExportSetting :: Monad m => (ExportSettings -> a) -> OrgParser m a
184getExportSetting s = s . orgStateExportSettings <$> getState
186getExportSetting s = s . orgStateExportSettings <$> getState
185
187
186-- | Set the current position as the last position at which a forbidden char
188-- | Set the current position as the last position at which a forbidden char
187-- was found (i.e. a character which is not allowed at the inner border of
189-- was found (i.e. a character which is not allowed at the inner border of
188-- markup).
190-- markup).
189−updateLastForbiddenCharPos :: OrgParser ()
191+updateLastForbiddenCharPos :: Monad m => OrgParser m ()
190updateLastForbiddenCharPos = getPosition >>= \p ->
192updateLastForbiddenCharPos = getPosition >>= \p ->
191 updateState $ \s -> s{ orgStateLastForbiddenCharPos = Just p}
193 updateState $ \s -> s{ orgStateLastForbiddenCharPos = Just p}
192
194
193-- | Set the current parser position as the position at which a character was
195-- | Set the current parser position as the position at which a character was
194-- seen which allows inline markup to follow.
196-- seen which allows inline markup to follow.
195−updateLastPreCharPos :: OrgParser ()
197+updateLastPreCharPos :: Monad m => OrgParser m ()
196updateLastPreCharPos = getPosition >>= \p ->
198updateLastPreCharPos = getPosition >>= \p ->
197 updateState $ \s -> s{ orgStateLastPreCharPos = Just p}
199 updateState $ \s -> s{ orgStateLastPreCharPos = Just p}
198
200
@@ -201,15 +203,15 @@ updateLastPreCharPos = getPosition >>= \p ->
201--
203--
202
204
203-- | Read the key of a plist style key-value list.
205-- | Read the key of a plist style key-value list.
204−orgArgKey :: OrgParser String
206+orgArgKey :: Monad m => OrgParser m String
205orgArgKey = try $
207orgArgKey = try $
206 skipSpaces *> char ':'
208 skipSpaces *> char ':'
207 *> many1 orgArgWordChar
209 *> many1 orgArgWordChar
208
210
209-- | Read the value of a plist style key-value list.
211-- | Read the value of a plist style key-value list.
210−orgArgWord :: OrgParser String
212+orgArgWord :: Monad m => OrgParser m String
211orgArgWord = many1 orgArgWordChar
213orgArgWord = many1 orgArgWordChar
212
214
213-- | Chars treated as part of a word in plists.
215-- | Chars treated as part of a word in plists.
214−orgArgWordChar :: OrgParser Char
216+orgArgWordChar :: Monad m => OrgParser m Char
215orgArgWordChar = alphaNum <|> oneOf "-_"
217orgArgWordChar = alphaNum <|> oneOf "-_"
src/Text/Pandoc/Readers/RST.hs+130−115
@@ -49,18 +49,29 @@ import qualified Text.Pandoc.Builder as B
49import Data.Sequence (viewr, ViewR(..))
49import Data.Sequence (viewr, ViewR(..))
50import Data.Char (toLower, isHexDigit, isSpace)
50import Data.Char (toLower, isHexDigit, isSpace)
51import Data.Monoid ((<>))
51import Data.Monoid ((<>))
52−import Text.Pandoc.Error
52+import Control.Monad.Except (throwError)
53+import Control.Monad.Trans (lift)
54+import Text.Pandoc.Class (PandocMonad, PandocExecutionError(..))
55+import qualified Text.Pandoc.Class as P
53
56
54-- | Parse reStructuredText string and return Pandoc document.
57-- | Parse reStructuredText string and return Pandoc document.
58+readRST :: PandocMonad m
55−readRST :: ReaderOptions -- ^ Reader options
59+ => ReaderOptions -- ^ Reader options
56 -> String -- ^ String to parse (assuming @'\n'@ line endings)
60 -> String -- ^ String to parse (assuming @'\n'@ line endings)
57− -> Either PandocError Pandoc
61+ -> m Pandoc
62+readRST opts s = do
58−readRST opts s = (readWith parseRST) def{ stateOptions = opts } (s ++ "\n\n")
63+ parsed <- (readWithM parseRST) def{ stateOptions = opts } (s ++ "\n\n")
64+ case parsed of
65+ Right result -> return result
66+ Left _ -> throwError $ PandocParseError "error parsing rst"
59
67
60−readRSTWithWarnings :: ReaderOptions -> String -> Either PandocError (Pandoc, [String])
68+readRSTWithWarnings :: PandocMonad m
61−readRSTWithWarnings opts s = (readWithWarnings parseRST) def{ stateOptions = opts } (s ++ "\n\n")
69+ => ReaderOptions -- ^ Reader options
70+ -> String -- ^ String to parse (assuming @'\n'@ line endings)
71+ -> m Pandoc
72+readRSTWithWarnings = readRST
62
73
63−type RSTParser = Parser [Char] ParserState
74+type RSTParser m = ParserT [Char] ParserState m
64
75
65--
76--
66-- Constants and data structure definitions
77-- Constants and data structure definitions
@@ -141,7 +152,7 @@ metaFromDefList ds meta = adjustAuthors $ foldr f meta ds
141 factorSemi (Str ys)
152 factorSemi (Str ys)
142 factorSemi x = [x]
153 factorSemi x = [x]
143
154
144−parseRST :: RSTParser Pandoc
155+parseRST :: PandocMonad m => RSTParser m Pandoc
145parseRST = do
156parseRST = do
146 optional blanklines -- skip blank lines at beginning of file
157 optional blanklines -- skip blank lines at beginning of file
147 startPos <- getPosition
158 startPos <- getPosition
@@ -168,10 +179,10 @@ parseRST = do
168-- parsing blocks
179-- parsing blocks
169--
180--
170
181
171−parseBlocks :: RSTParser Blocks
182+parseBlocks :: PandocMonad m => RSTParser m Blocks
172parseBlocks = mconcat <$> manyTill block eof
183parseBlocks = mconcat <$> manyTill block eof
173
184
174−block :: RSTParser Blocks
185+block :: PandocMonad m => RSTParser m Blocks
175block = choice [ codeBlock
186block = choice [ codeBlock
176 , blockQuote
187 , blockQuote
177 , fieldList
188 , fieldList
@@ -191,7 +202,7 @@ block = choice [ codeBlock
191-- field list
202-- field list
192--
203--
193
204
194−rawFieldListItem :: Int -> RSTParser (String, String)
205+rawFieldListItem :: Monad m => Int -> RSTParser m (String, String)
195rawFieldListItem minIndent = try $ do
206rawFieldListItem minIndent = try $ do
196 indent <- length <$> many (char ' ')
207 indent <- length <$> many (char ' ')
197 guard $ indent >= minIndent
208 guard $ indent >= minIndent
@@ -204,7 +215,7 @@ rawFieldListItem minIndent = try $ do
204 let raw = (if null first then "" else (first ++ "\n")) ++ rest ++ "\n"
215 let raw = (if null first then "" else (first ++ "\n")) ++ rest ++ "\n"
205 return (name, raw)
216 return (name, raw)
206
217
207−fieldListItem :: Int -> RSTParser (Inlines, [Blocks])
218+fieldListItem :: PandocMonad m => Int -> RSTParser m (Inlines, [Blocks])
208fieldListItem minIndent = try $ do
219fieldListItem minIndent = try $ do
209 (name, raw) <- rawFieldListItem minIndent
220 (name, raw) <- rawFieldListItem minIndent
210 term <- parseInlineFromString name
221 term <- parseInlineFromString name
@@ -212,7 +223,7 @@ fieldListItem minIndent = try $ do
212 optional blanklines
223 optional blanklines
213 return (term, [contents])
224 return (term, [contents])
214
225
215−fieldList :: RSTParser Blocks
226+fieldList :: PandocMonad m => RSTParser m Blocks
216fieldList = try $ do
227fieldList = try $ do
217 indent <- length <$> lookAhead (many spaceChar)
228 indent <- length <$> lookAhead (many spaceChar)
218 items <- many1 $ fieldListItem indent
229 items <- many1 $ fieldListItem indent
@@ -224,7 +235,7 @@ fieldList = try $ do
224-- line block
235-- line block
225--
236--
226
237
227−lineBlock :: RSTParser Blocks
238+lineBlock :: PandocMonad m => RSTParser m Blocks
228lineBlock = try $ do
239lineBlock = try $ do
229 lines' <- lineBlockLines
240 lines' <- lineBlockLines
230 lines'' <- mapM parseInlineFromString lines'
241 lines'' <- mapM parseInlineFromString lines'
@@ -235,7 +246,7 @@ lineBlock = try $ do
235--
246--
236
247
237-- note: paragraph can end in a :: starting a code block
248-- note: paragraph can end in a :: starting a code block
238−para :: RSTParser Blocks
249+para :: PandocMonad m => RSTParser m Blocks
239para = try $ do
250para = try $ do
240 result <- trimInlines . mconcat <$> many1 inline
251 result <- trimInlines . mconcat <$> many1 inline
241 option (B.plain result) $ try $ do
252 option (B.plain result) $ try $ do
@@ -248,18 +259,18 @@ para = try $ do
248 <> raw
259 <> raw
249 _ -> return (B.para result)
260 _ -> return (B.para result)
250
261
251−plain :: RSTParser Blocks
262+plain :: PandocMonad m => RSTParser m Blocks
252plain = B.plain . trimInlines . mconcat <$> many1 inline
263plain = B.plain . trimInlines . mconcat <$> many1 inline
253
264
254--
265--
255-- header blocks
266-- header blocks
256--
267--
257
268
258−header :: RSTParser Blocks
269+header :: PandocMonad m => RSTParser m Blocks
259header = doubleHeader <|> singleHeader <?> "header"
270header = doubleHeader <|> singleHeader <?> "header"
260
271
261-- a header with lines on top and bottom
272-- a header with lines on top and bottom
262−doubleHeader :: RSTParser Blocks
273+doubleHeader :: PandocMonad m => RSTParser m Blocks
263doubleHeader = try $ do
274doubleHeader = try $ do
264 c <- oneOf underlineChars
275 c <- oneOf underlineChars
265 rest <- many (char c) -- the top line
276 rest <- many (char c) -- the top line
@@ -285,7 +296,7 @@ doubleHeader = try $ do
285 return $ B.headerWith attr level txt
296 return $ B.headerWith attr level txt
286
297
287-- a header with line on the bottom only
298-- a header with line on the bottom only
288−singleHeader :: RSTParser Blocks
299+singleHeader :: PandocMonad m => RSTParser m Blocks
289singleHeader = try $ do
300singleHeader = try $ do
290 notFollowedBy' whitespace
301 notFollowedBy' whitespace
291 txt <- trimInlines . mconcat <$> many1 (do {notFollowedBy blankline; inline})
302 txt <- trimInlines . mconcat <$> many1 (do {notFollowedBy blankline; inline})
@@ -309,7 +320,7 @@ singleHeader = try $ do
309-- hrule block
320-- hrule block
310--
321--
311
322
312−hrule :: Parser [Char] st Blocks
323+hrule :: Monad m => ParserT [Char] st m Blocks
313hrule = try $ do
324hrule = try $ do
314 chr <- oneOf underlineChars
325 chr <- oneOf underlineChars
315 count 3 (char chr)
326 count 3 (char chr)
@@ -323,14 +334,14 @@ hrule = try $ do
323--
334--
324
335
325-- read a line indented by a given string
336-- read a line indented by a given string
326−indentedLine :: String -> Parser [Char] st [Char]
337+indentedLine :: Monad m => String -> ParserT [Char] st m [Char]
327indentedLine indents = try $ do
338indentedLine indents = try $ do
328 string indents
339 string indents
329 anyLine
340 anyLine
330
341
331-- one or more indented lines, possibly separated by blank lines.
342-- one or more indented lines, possibly separated by blank lines.
332-- any amount of indentation will work.
343-- any amount of indentation will work.
333−indentedBlock :: Parser [Char] st [Char]
344+indentedBlock :: Monad m => ParserT [Char] st m [Char]
334indentedBlock = try $ do
345indentedBlock = try $ do
335 indents <- lookAhead $ many1 spaceChar
346 indents <- lookAhead $ many1 spaceChar
336 lns <- many1 $ try $ do b <- option "" blanklines
347 lns <- many1 $ try $ do b <- option "" blanklines
@@ -339,24 +350,24 @@ indentedBlock = try $ do
339 optional blanklines
350 optional blanklines
340 return $ unlines lns
351 return $ unlines lns
341
352
342−quotedBlock :: Parser [Char] st [Char]
353+quotedBlock :: Monad m => ParserT [Char] st m [Char]
343quotedBlock = try $ do
354quotedBlock = try $ do
344 quote <- lookAhead $ oneOf "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~"
355 quote <- lookAhead $ oneOf "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~"
345 lns <- many1 $ lookAhead (char quote) >> anyLine
356 lns <- many1 $ lookAhead (char quote) >> anyLine
346 optional blanklines
357 optional blanklines
347 return $ unlines lns
358 return $ unlines lns
348
359
349−codeBlockStart :: Parser [Char] st Char
360+codeBlockStart :: Monad m => ParserT [Char] st m Char
350codeBlockStart = string "::" >> blankline >> blankline
361codeBlockStart = string "::" >> blankline >> blankline
351
362
352−codeBlock :: Parser [Char] st Blocks
363+codeBlock :: Monad m => ParserT [Char] st m Blocks
353codeBlock = try $ codeBlockStart >> codeBlockBody
364codeBlock = try $ codeBlockStart >> codeBlockBody
354
365
355−codeBlockBody :: Parser [Char] st Blocks
366+codeBlockBody :: Monad m => ParserT [Char] st m Blocks
356codeBlockBody = try $ B.codeBlock . stripTrailingNewlines <$>
367codeBlockBody = try $ B.codeBlock . stripTrailingNewlines <$>
357 (indentedBlock <|> quotedBlock)
368 (indentedBlock <|> quotedBlock)
358
369
359−lhsCodeBlock :: RSTParser Blocks
370+lhsCodeBlock :: Monad m => RSTParser m Blocks
360lhsCodeBlock = try $ do
371lhsCodeBlock = try $ do
361 getPosition >>= guard . (==1) . sourceColumn
372 getPosition >>= guard . (==1) . sourceColumn
362 guardEnabled Ext_literate_haskell
373 guardEnabled Ext_literate_haskell
@@ -366,14 +377,14 @@ lhsCodeBlock = try $ do
366 return $ B.codeBlockWith ("", ["sourceCode", "literate", "haskell"], [])
377 return $ B.codeBlockWith ("", ["sourceCode", "literate", "haskell"], [])
367 $ intercalate "\n" lns
378 $ intercalate "\n" lns
368
379
369−latexCodeBlock :: Parser [Char] st [[Char]]
380+latexCodeBlock :: Monad m => ParserT [Char] st m [[Char]]
370latexCodeBlock = try $ do
381latexCodeBlock = try $ do
371 try (latexBlockLine "\\begin{code}")
382 try (latexBlockLine "\\begin{code}")
372 many1Till anyLine (try $ latexBlockLine "\\end{code}")
383 many1Till anyLine (try $ latexBlockLine "\\end{code}")
373 where
384 where
374 latexBlockLine s = skipMany spaceChar >> string s >> blankline
385 latexBlockLine s = skipMany spaceChar >> string s >> blankline
375
386
376−birdCodeBlock :: Parser [Char] st [[Char]]
387+birdCodeBlock :: Monad m => ParserT [Char] st m [[Char]]
377birdCodeBlock = filterSpace <$> many1 birdTrackLine
388birdCodeBlock = filterSpace <$> many1 birdTrackLine
378 where filterSpace lns =
389 where filterSpace lns =
379 -- if (as is normal) there is always a space after >, drop it
390 -- if (as is normal) there is always a space after >, drop it
@@ -381,14 +392,14 @@ birdCodeBlock = filterSpace <$> many1 birdTrackLine
381 then map (drop 1) lns
392 then map (drop 1) lns
382 else lns
393 else lns
383
394
384−birdTrackLine :: Parser [Char] st [Char]
395+birdTrackLine :: Monad m => ParserT [Char] st m [Char]
385birdTrackLine = char '>' >> anyLine
396birdTrackLine = char '>' >> anyLine
386
397
387--
398--
388-- block quotes
399-- block quotes
389--
400--
390
401
391−blockQuote :: RSTParser Blocks
402+blockQuote :: PandocMonad m => RSTParser m Blocks
392blockQuote = do
403blockQuote = do
393 raw <- indentedBlock
404 raw <- indentedBlock
394 -- parse the extracted block, which may contain various block elements:
405 -- parse the extracted block, which may contain various block elements:
@@ -399,10 +410,10 @@ blockQuote = do
399-- list blocks
410-- list blocks
400--
411--
401
412
402−list :: RSTParser Blocks
413+list :: PandocMonad m => RSTParser m Blocks
403list = choice [ bulletList, orderedList, definitionList ] <?> "list"
414list = choice [ bulletList, orderedList, definitionList ] <?> "list"
404
415
405−definitionListItem :: RSTParser (Inlines, [Blocks])
416+definitionListItem :: PandocMonad m => RSTParser m (Inlines, [Blocks])
406definitionListItem = try $ do
417definitionListItem = try $ do
407 -- avoid capturing a directive or comment
418 -- avoid capturing a directive or comment
408 notFollowedBy (try $ char '.' >> char '.')
419 notFollowedBy (try $ char '.' >> char '.')
@@ -412,11 +423,11 @@ definitionListItem = try $ do
412 contents <- parseFromString parseBlocks $ raw ++ "\n"
423 contents <- parseFromString parseBlocks $ raw ++ "\n"
413 return (term, [contents])
424 return (term, [contents])
414
425
415−definitionList :: RSTParser Blocks
426+definitionList :: PandocMonad m => RSTParser m Blocks
416definitionList = B.definitionList <$> many1 definitionListItem
427definitionList = B.definitionList <$> many1 definitionListItem
417
428
418-- parses bullet list start and returns its length (inc. following whitespace)
429-- parses bullet list start and returns its length (inc. following whitespace)
419−bulletListStart :: Parser [Char] st Int
430+bulletListStart :: Monad m => ParserT [Char] st m Int
420bulletListStart = try $ do
431bulletListStart = try $ do
421 notFollowedBy' hrule -- because hrules start out just like lists
432 notFollowedBy' hrule -- because hrules start out just like lists
422 marker <- oneOf bulletListMarkers
433 marker <- oneOf bulletListMarkers
@@ -424,16 +435,16 @@ bulletListStart = try $ do
424 return $ length (marker:white)
435 return $ length (marker:white)
425
436
426-- parses ordered list start and returns its length (inc following whitespace)
437-- parses ordered list start and returns its length (inc following whitespace)
427−orderedListStart :: ListNumberStyle
438+orderedListStart :: Monad m => ListNumberStyle
428 -> ListNumberDelim
439 -> ListNumberDelim
429− -> RSTParser Int
440+ -> RSTParser m Int
430orderedListStart style delim = try $ do
441orderedListStart style delim = try $ do
431 (_, markerLen) <- withHorizDisplacement (orderedListMarker style delim)
442 (_, markerLen) <- withHorizDisplacement (orderedListMarker style delim)
432 white <- many1 spaceChar
443 white <- many1 spaceChar
433 return $ markerLen + length white
444 return $ markerLen + length white
434
445
435-- parse a line of a list item
446-- parse a line of a list item
436−listLine :: Int -> RSTParser [Char]
447+listLine :: Monad m => Int -> RSTParser m [Char]
437listLine markerLength = try $ do
448listLine markerLength = try $ do
438 notFollowedBy blankline
449 notFollowedBy blankline
439 indentWith markerLength
450 indentWith markerLength
@@ -441,7 +452,7 @@ listLine markerLength = try $ do
441 return $ line ++ "\n"
452 return $ line ++ "\n"
442
453
443-- indent by specified number of spaces (or equiv. tabs)
454-- indent by specified number of spaces (or equiv. tabs)
444−indentWith :: Int -> RSTParser [Char]
455+indentWith :: Monad m => Int -> RSTParser m [Char]
445indentWith num = do
456indentWith num = do
446 tabStop <- getOption readerTabStop
457 tabStop <- getOption readerTabStop
447 if (num < tabStop)
458 if (num < tabStop)
@@ -450,8 +461,8 @@ indentWith num = do
450 (try (char '\t' >> count (num - tabStop) (char ' '))) ]
461 (try (char '\t' >> count (num - tabStop) (char ' '))) ]
451
462
452-- parse raw text for one list item, excluding start marker and continuations
463-- parse raw text for one list item, excluding start marker and continuations
453−rawListItem :: RSTParser Int
464+rawListItem :: Monad m => RSTParser m Int
454− -> RSTParser (Int, [Char])
465+ -> RSTParser m (Int, [Char])
455rawListItem start = try $ do
466rawListItem start = try $ do
456 markerLength <- start
467 markerLength <- start
457 firstLine <- anyLine
468 firstLine <- anyLine
@@ -461,14 +472,15 @@ rawListItem start = try $ do
461-- continuation of a list item - indented and separated by blankline or
472-- continuation of a list item - indented and separated by blankline or
462-- (in compact lists) endline.
473-- (in compact lists) endline.
463-- Note: nested lists are parsed as continuations.
474-- Note: nested lists are parsed as continuations.
464−listContinuation :: Int -> RSTParser [Char]
475+listContinuation :: Monad m => Int -> RSTParser m [Char]
465listContinuation markerLength = try $ do
476listContinuation markerLength = try $ do
466 blanks <- many1 blankline
477 blanks <- many1 blankline
467 result <- many1 (listLine markerLength)
478 result <- many1 (listLine markerLength)
468 return $ blanks ++ concat result
479 return $ blanks ++ concat result
469
480
481+listItem :: PandocMonad m
470−listItem :: RSTParser Int
482+ => RSTParser m Int
471− -> RSTParser Blocks
483+ -> RSTParser m Blocks
472listItem start = try $ do
484listItem start = try $ do
473 (markerLength, first) <- rawListItem start
485 (markerLength, first) <- rawListItem start
474 rest <- many (listContinuation markerLength)
486 rest <- many (listContinuation markerLength)
@@ -490,21 +502,21 @@ listItem start = try $ do
490 [Para xs, DefinitionList ys] -> B.fromList [Plain xs, DefinitionList ys]
502 [Para xs, DefinitionList ys] -> B.fromList [Plain xs, DefinitionList ys]
491 _ -> parsed
503 _ -> parsed
492
504
493−orderedList :: RSTParser Blocks
505+orderedList :: PandocMonad m => RSTParser m Blocks
494orderedList = try $ do
506orderedList = try $ do
495 (start, style, delim) <- lookAhead (anyOrderedListMarker <* spaceChar)
507 (start, style, delim) <- lookAhead (anyOrderedListMarker <* spaceChar)
496 items <- many1 (listItem (orderedListStart style delim))
508 items <- many1 (listItem (orderedListStart style delim))
497 let items' = compactify' items
509 let items' = compactify' items
498 return $ B.orderedListWith (start, style, delim) items'
510 return $ B.orderedListWith (start, style, delim) items'
499
511
500−bulletList :: RSTParser Blocks
512+bulletList :: PandocMonad m => RSTParser m Blocks
501bulletList = B.bulletList . compactify' <$> many1 (listItem bulletListStart)
513bulletList = B.bulletList . compactify' <$> many1 (listItem bulletListStart)
502
514
503--
515--
504-- directive (e.g. comment, container, compound-paragraph)
516-- directive (e.g. comment, container, compound-paragraph)
505--
517--
506
518
507−comment :: RSTParser Blocks
519+comment :: Monad m => RSTParser m Blocks
508comment = try $ do
520comment = try $ do
509 string ".."
521 string ".."
510 skipMany1 spaceChar <|> (() <$ lookAhead newline)
522 skipMany1 spaceChar <|> (() <$ lookAhead newline)
@@ -513,11 +525,11 @@ comment = try $ do
513 optional indentedBlock
525 optional indentedBlock
514 return mempty
526 return mempty
515
527
516−directiveLabel :: RSTParser String
528+directiveLabel :: Monad m => RSTParser m String
517directiveLabel = map toLower
529directiveLabel = map toLower
518 <$> many1Till (letter <|> char '-') (try $ string "::")
530 <$> many1Till (letter <|> char '-') (try $ string "::")
519
531
520−directive :: RSTParser Blocks
532+directive :: PandocMonad m => RSTParser m Blocks
521directive = try $ do
533directive = try $ do
522 string ".."
534 string ".."
523 directive'
535 directive'
@@ -526,7 +538,7 @@ directive = try $ do
526-- date
538-- date
527-- include
539-- include
528-- title
540-- title
529−directive' :: RSTParser Blocks
541+directive' :: PandocMonad m => RSTParser m Blocks
530directive' = do
542directive' = do
531 skipMany1 spaceChar
543 skipMany1 spaceChar
532 label <- directiveLabel
544 label <- directiveLabel
@@ -614,13 +626,13 @@ directive' = do
614 return $ B.divWith attrs children
626 return $ B.divWith attrs children
615 other -> do
627 other -> do
616 pos <- getPosition
628 pos <- getPosition
617− addWarning (Just pos) $ "ignoring unknown directive: " ++ other
629+ P.addWarningWithPos (Just pos) $ "ignoring unknown directive: " ++ other
618 return mempty
630 return mempty
619
631
620-- TODO:
632-- TODO:
621-- - Only supports :format: fields with a single format for :raw: roles,
633-- - Only supports :format: fields with a single format for :raw: roles,
622-- change Text.Pandoc.Definition.Format to fix
634-- change Text.Pandoc.Definition.Format to fix
623−addNewRole :: String -> [(String, String)] -> RSTParser Blocks
635+addNewRole :: PandocMonad m => String -> [(String, String)] -> RSTParser m Blocks
624addNewRole roleString fields = do
636addNewRole roleString fields = do
625 (role, parentRole) <- parseFromString inheritedRole roleString
637 (role, parentRole) <- parseFromString inheritedRole roleString
626 customRoles <- stateRstCustomRoles <$> getState
638 customRoles <- stateRstCustomRoles <$> getState
@@ -642,20 +654,20 @@ addNewRole roleString fields = do
642
654
643 -- warn about syntax we ignore
655 -- warn about syntax we ignore
644 flip mapM_ fields $ \(key, _) -> case key of
656 flip mapM_ fields $ \(key, _) -> case key of
645− "language" -> when (baseRole /= "code") $ addWarning Nothing $
657+ "language" -> when (baseRole /= "code") $ lift $ P.warn $
646 "ignoring :language: field because the parent of role :" ++
658 "ignoring :language: field because the parent of role :" ++
647 role ++ ": is :" ++ baseRole ++ ": not :code:"
659 role ++ ": is :" ++ baseRole ++ ": not :code:"
648− "format" -> when (baseRole /= "raw") $ addWarning Nothing $
660+ "format" -> when (baseRole /= "raw") $ lift $ P.warn $
649 "ignoring :format: field because the parent of role :" ++
661 "ignoring :format: field because the parent of role :" ++
650 role ++ ": is :" ++ baseRole ++ ": not :raw:"
662 role ++ ": is :" ++ baseRole ++ ": not :raw:"
651− _ -> addWarning Nothing $ "ignoring unknown field :" ++ key ++
663+ _ -> lift $ P.warn $ "ignoring unknown field :" ++ key ++
652 ": in definition of role :" ++ role ++ ": in"
664 ": in definition of role :" ++ role ++ ": in"
653 when (parentRole == "raw" && countKeys "format" > 1) $
665 when (parentRole == "raw" && countKeys "format" > 1) $
654− addWarning Nothing $
666+ lift $ P.warn $
655 "ignoring :format: fields after the first in the definition of role :"
667 "ignoring :format: fields after the first in the definition of role :"
656 ++ role ++": in"
668 ++ role ++": in"
657 when (parentRole == "code" && countKeys "language" > 1) $
669 when (parentRole == "code" && countKeys "language" > 1) $
658− addWarning Nothing $
670+ lift $ P.warn $
659 "ignoring :language: fields after the first in the definition of role :"
671 "ignoring :language: fields after the first in the definition of role :"
660 ++ role ++": in"
672 ++ role ++": in"
661
673
@@ -700,7 +712,7 @@ extractUnicodeChar s = maybe Nothing (\c -> Just (c,rest)) mbc
700 where (ds,rest) = span isHexDigit s
712 where (ds,rest) = span isHexDigit s
701 mbc = safeRead ('\'':'\\':'x':ds ++ "'")
713 mbc = safeRead ('\'':'\\':'x':ds ++ "'")
702
714
703−extractCaption :: RSTParser (Inlines, Blocks)
715+extractCaption :: PandocMonad m => RSTParser m (Inlines, Blocks)
704extractCaption = do
716extractCaption = do
705 capt <- trimInlines . mconcat <$> many inline
717 capt <- trimInlines . mconcat <$> many inline
706 legend <- optional blanklines >> (mconcat <$> many block)
718 legend <- optional blanklines >> (mconcat <$> many block)
@@ -712,7 +724,7 @@ toChunks = dropWhile null
712 . map (trim . unlines)
724 . map (trim . unlines)
713 . splitBy (all (`elem` (" \t" :: String))) . lines
725 . splitBy (all (`elem` (" \t" :: String))) . lines
714
726
715−codeblock :: [String] -> Maybe String -> String -> String -> RSTParser Blocks
727+codeblock :: [String] -> Maybe String -> String -> String -> RSTParser m Blocks
716codeblock classes numberLines lang body =
728codeblock classes numberLines lang body =
717 return $ B.codeBlockWith attribs $ stripTrailingNewlines body
729 return $ B.codeBlockWith attribs $ stripTrailingNewlines body
718 where attribs = ("", classes', kvs)
730 where attribs = ("", classes', kvs)
@@ -728,7 +740,7 @@ codeblock classes numberLines lang body =
728--- note block
740--- note block
729---
741---
730
742
731−noteBlock :: RSTParser [Char]
743+noteBlock :: Monad m => RSTParser m [Char]
732noteBlock = try $ do
744noteBlock = try $ do
733 startPos <- getPosition
745 startPos <- getPosition
734 string ".."
746 string ".."
@@ -747,7 +759,7 @@ noteBlock = try $ do
747 -- return blanks so line count isn't affected
759 -- return blanks so line count isn't affected
748 return $ replicate (sourceLine endPos - sourceLine startPos) '\n'
760 return $ replicate (sourceLine endPos - sourceLine startPos) '\n'
749
761
750−noteMarker :: RSTParser [Char]
762+noteMarker :: Monad m => RSTParser m [Char]
751noteMarker = do
763noteMarker = do
752 char '['
764 char '['
753 res <- many1 digit
765 res <- many1 digit
@@ -760,13 +772,13 @@ noteMarker = do
760-- reference key
772-- reference key
761--
773--
762
774
763−quotedReferenceName :: RSTParser Inlines
775+quotedReferenceName :: PandocMonad m => RSTParser m Inlines
764quotedReferenceName = try $ do
776quotedReferenceName = try $ do
765 char '`' >> notFollowedBy (char '`') -- `` means inline code!
777 char '`' >> notFollowedBy (char '`') -- `` means inline code!
766 label' <- trimInlines . mconcat <$> many1Till inline (char '`')
778 label' <- trimInlines . mconcat <$> many1Till inline (char '`')
767 return label'
779 return label'
768
780
769−unquotedReferenceName :: RSTParser Inlines
781+unquotedReferenceName :: PandocMonad m => RSTParser m Inlines
770unquotedReferenceName = try $ do
782unquotedReferenceName = try $ do
771 label' <- trimInlines . mconcat <$> many1Till inline (lookAhead $ char ':')
783 label' <- trimInlines . mconcat <$> many1Till inline (lookAhead $ char ':')
772 return label'
784 return label'
@@ -775,24 +787,24 @@ unquotedReferenceName = try $ do
775-- plus isolated (no two adjacent) internal hyphens, underscores,
787-- plus isolated (no two adjacent) internal hyphens, underscores,
776-- periods, colons and plus signs; no whitespace or other characters
788-- periods, colons and plus signs; no whitespace or other characters
777-- are allowed.
789-- are allowed.
778−simpleReferenceName' :: Parser [Char] st String
790+simpleReferenceName' :: Monad m => ParserT [Char] st m String
779simpleReferenceName' = do
791simpleReferenceName' = do
780 x <- alphaNum
792 x <- alphaNum
781 xs <- many $ alphaNum
793 xs <- many $ alphaNum
782 <|> (try $ oneOf "-_:+." <* lookAhead alphaNum)
794 <|> (try $ oneOf "-_:+." <* lookAhead alphaNum)
783 return (x:xs)
795 return (x:xs)
784
796
785−simpleReferenceName :: Parser [Char] st Inlines
797+simpleReferenceName :: Monad m => ParserT [Char] st m Inlines
786simpleReferenceName = do
798simpleReferenceName = do
787 raw <- simpleReferenceName'
799 raw <- simpleReferenceName'
788 return $ B.str raw
800 return $ B.str raw
789
801
790−referenceName :: RSTParser Inlines
802+referenceName :: PandocMonad m => RSTParser m Inlines
791referenceName = quotedReferenceName <|>
803referenceName = quotedReferenceName <|>
792 (try $ simpleReferenceName <* lookAhead (char ':')) <|>
804 (try $ simpleReferenceName <* lookAhead (char ':')) <|>
793 unquotedReferenceName
805 unquotedReferenceName
794
806
795−referenceKey :: RSTParser [Char]
807+referenceKey :: PandocMonad m => RSTParser m [Char]
796referenceKey = do
808referenceKey = do
797 startPos <- getPosition
809 startPos <- getPosition
798 choice [substKey, anonymousKey, regularKey]
810 choice [substKey, anonymousKey, regularKey]
@@ -801,7 +813,7 @@ referenceKey = do
801 -- return enough blanks to replace key
813 -- return enough blanks to replace key
802 return $ replicate (sourceLine endPos - sourceLine startPos) '\n'
814 return $ replicate (sourceLine endPos - sourceLine startPos) '\n'
803
815
804−targetURI :: Parser [Char] st [Char]
816+targetURI :: Monad m => ParserT [Char] st m [Char]
805targetURI = do
817targetURI = do
806 skipSpaces
818 skipSpaces
807 optional newline
819 optional newline
@@ -810,7 +822,7 @@ targetURI = do
810 blanklines
822 blanklines
811 return $ escapeURI $ trim $ contents
823 return $ escapeURI $ trim $ contents
812
824
813−substKey :: RSTParser ()
825+substKey :: PandocMonad m => RSTParser m ()
814substKey = try $ do
826substKey = try $ do
815 string ".."
827 string ".."
816 skipMany1 spaceChar
828 skipMany1 spaceChar
@@ -828,7 +840,7 @@ substKey = try $ do
828 let key = toKey $ stripFirstAndLast ref
840 let key = toKey $ stripFirstAndLast ref
829 updateState $ \s -> s{ stateSubstitutions = M.insert key il $ stateSubstitutions s }
841 updateState $ \s -> s{ stateSubstitutions = M.insert key il $ stateSubstitutions s }
830
842
831−anonymousKey :: RSTParser ()
843+anonymousKey :: Monad m => RSTParser m ()
832anonymousKey = try $ do
844anonymousKey = try $ do
833 oneOfStrings [".. __:", "__"]
845 oneOfStrings [".. __:", "__"]
834 src <- targetURI
846 src <- targetURI
@@ -842,7 +854,7 @@ stripTicks = reverse . stripTick . reverse . stripTick
842 where stripTick ('`':xs) = xs
854 where stripTick ('`':xs) = xs
843 stripTick xs = xs
855 stripTick xs = xs
844
856
845−regularKey :: RSTParser ()
857+regularKey :: PandocMonad m => RSTParser m ()
846regularKey = try $ do
858regularKey = try $ do
847 string ".. _"
859 string ".. _"
848 (_,ref) <- withRaw referenceName
860 (_,ref) <- withRaw referenceName
@@ -869,31 +881,31 @@ regularKey = try $ do
869-- Grid tables TODO:
881-- Grid tables TODO:
870-- - column spans
882-- - column spans
871
883
872−dashedLine :: Char -> Parser [Char] st (Int, Int)
884+dashedLine :: Monad m => Char -> ParserT [Char] st m (Int, Int)
873dashedLine ch = do
885dashedLine ch = do
874 dashes <- many1 (char ch)
886 dashes <- many1 (char ch)
875 sp <- many (char ' ')
887 sp <- many (char ' ')
876 return (length dashes, length $ dashes ++ sp)
888 return (length dashes, length $ dashes ++ sp)
877
889
878−simpleDashedLines :: Char -> Parser [Char] st [(Int,Int)]
890+simpleDashedLines :: Monad m => Char -> ParserT [Char] st m [(Int,Int)]
879simpleDashedLines ch = try $ many1 (dashedLine ch)
891simpleDashedLines ch = try $ many1 (dashedLine ch)
880
892
881-- Parse a table row separator
893-- Parse a table row separator
882−simpleTableSep :: Char -> RSTParser Char
894+simpleTableSep :: Monad m => Char -> RSTParser m Char
883simpleTableSep ch = try $ simpleDashedLines ch >> newline
895simpleTableSep ch = try $ simpleDashedLines ch >> newline
884
896
885-- Parse a table footer
897-- Parse a table footer
886−simpleTableFooter :: RSTParser [Char]
898+simpleTableFooter :: Monad m => RSTParser m [Char]
887simpleTableFooter = try $ simpleTableSep '=' >> blanklines
899simpleTableFooter = try $ simpleTableSep '=' >> blanklines
888
900
889-- Parse a raw line and split it into chunks by indices.
901-- Parse a raw line and split it into chunks by indices.
890−simpleTableRawLine :: [Int] -> RSTParser [String]
902+simpleTableRawLine :: Monad m => [Int] -> RSTParser m [String]
891simpleTableRawLine indices = do
903simpleTableRawLine indices = do
892 line <- many1Till anyChar newline
904 line <- many1Till anyChar newline
893 return (simpleTableSplitLine indices line)
905 return (simpleTableSplitLine indices line)
894
906
895-- Parse a table row and return a list of blocks (columns).
907-- Parse a table row and return a list of blocks (columns).
896−simpleTableRow :: [Int] -> RSTParser [[Block]]
908+simpleTableRow :: PandocMonad m => [Int] -> RSTParser m [[Block]]
897simpleTableRow indices = do
909simpleTableRow indices = do
898 notFollowedBy' simpleTableFooter
910 notFollowedBy' simpleTableFooter
899 firstLine <- simpleTableRawLine indices
911 firstLine <- simpleTableRawLine indices
@@ -906,8 +918,9 @@ simpleTableSplitLine indices line =
906 map trim
918 map trim
907 $ tail $ splitByIndices (init indices) line
919 $ tail $ splitByIndices (init indices) line
908
920
921+simpleTableHeader :: PandocMonad m
909−simpleTableHeader :: Bool -- ^ Headerless table
922+ => Bool -- ^ Headerless table
910− -> RSTParser ([[Block]], [Alignment], [Int])
923+ -> RSTParser m ([[Block]], [Alignment], [Int])
911simpleTableHeader headless = try $ do
924simpleTableHeader headless = try $ do
912 optional blanklines
925 optional blanklines
913 rawContent <- if headless
926 rawContent <- if headless
@@ -926,8 +939,9 @@ simpleTableHeader headless = try $ do
926 return (heads, aligns, indices)
939 return (heads, aligns, indices)
927
940
928-- Parse a simple table.
941-- Parse a simple table.
942+simpleTable :: PandocMonad m
929−simpleTable :: Bool -- ^ Headerless table
943+ => Bool -- ^ Headerless table
930− -> RSTParser Blocks
944+ -> RSTParser m Blocks
931simpleTable headless = do
945simpleTable headless = do
932 Table c a _w h l <- tableWith (simpleTableHeader headless) simpleTableRow sep simpleTableFooter
946 Table c a _w h l <- tableWith (simpleTableHeader headless) simpleTableRow sep simpleTableFooter
933 -- Simple tables get 0s for relative column widths (i.e., use default)
947 -- Simple tables get 0s for relative column widths (i.e., use default)
@@ -935,12 +949,13 @@ simpleTable headless = do
935 where
949 where
936 sep = return () -- optional (simpleTableSep '-')
950 sep = return () -- optional (simpleTableSep '-')
937
951
952+gridTable :: PandocMonad m
938−gridTable :: Bool -- ^ Headerless table
953+ => Bool -- ^ Headerless table
939− -> RSTParser Blocks
954+ -> RSTParser m Blocks
940gridTable headerless = B.singleton
955gridTable headerless = B.singleton
941 <$> gridTableWith (B.toList <$> parseBlocks) headerless
956 <$> gridTableWith (B.toList <$> parseBlocks) headerless
942
957
943−table :: RSTParser Blocks
958+table :: PandocMonad m => RSTParser m Blocks
944table = gridTable False <|> simpleTable False <|>
959table = gridTable False <|> simpleTable False <|>
945 gridTable True <|> simpleTable True <?> "table"
960 gridTable True <|> simpleTable True <?> "table"
946
961
@@ -948,7 +963,7 @@ table = gridTable False <|> simpleTable False <|>
948-- inline
963-- inline
949--
964--
950
965
951−inline :: RSTParser Inlines
966+inline :: PandocMonad m => RSTParser m Inlines
952inline = choice [ note -- can start with whitespace, so try before ws
967inline = choice [ note -- can start with whitespace, so try before ws
953 , whitespace
968 , whitespace
954 , link
969 , link
@@ -964,29 +979,29 @@ inline = choice [ note -- can start with whitespace, so try before ws
964 , escapedChar
979 , escapedChar
965 , symbol ] <?> "inline"
980 , symbol ] <?> "inline"
966
981
967−parseInlineFromString :: String -> RSTParser Inlines
982+parseInlineFromString :: PandocMonad m => String -> RSTParser m Inlines
968parseInlineFromString = parseFromString (trimInlines . mconcat <$> many inline)
983parseInlineFromString = parseFromString (trimInlines . mconcat <$> many inline)
969
984
970−hyphens :: RSTParser Inlines
985+hyphens :: Monad m => RSTParser m Inlines
971hyphens = do
986hyphens = do
972 result <- many1 (char '-')
987 result <- many1 (char '-')
973 optional endline
988 optional endline
974 -- don't want to treat endline after hyphen or dash as a space
989 -- don't want to treat endline after hyphen or dash as a space
975 return $ B.str result
990 return $ B.str result
976
991
977−escapedChar :: Parser [Char] st Inlines
992+escapedChar :: Monad m => ParserT [Char] st m Inlines
978escapedChar = do c <- escaped anyChar
993escapedChar = do c <- escaped anyChar
979 return $ if c == ' ' -- '\ ' is null in RST
994 return $ if c == ' ' -- '\ ' is null in RST
980 then mempty
995 then mempty
981 else B.str [c]
996 else B.str [c]
982
997
983−symbol :: RSTParser Inlines
998+symbol :: Monad m => RSTParser m Inlines
984symbol = do
999symbol = do
985 result <- oneOf specialChars
1000 result <- oneOf specialChars
986 return $ B.str [result]
1001 return $ B.str [result]
987
1002
988-- parses inline code, between codeStart and codeEnd
1003-- parses inline code, between codeStart and codeEnd
989−code :: RSTParser Inlines
1004+code :: Monad m => RSTParser m Inlines
990code = try $ do
1005code = try $ do
991 string "``"
1006 string "``"
992 result <- manyTill anyChar (try (string "``"))
1007 result <- manyTill anyChar (try (string "``"))
@@ -994,7 +1009,7 @@ code = try $ do
994 $ trim $ unwords $ lines result
1009 $ trim $ unwords $ lines result
995
1010
996-- succeeds only if we're not right after a str (ie. in middle of word)
1011-- succeeds only if we're not right after a str (ie. in middle of word)
997−atStart :: RSTParser a -> RSTParser a
1012+atStart :: Monad m => RSTParser m a -> RSTParser m a
998atStart p = do
1013atStart p = do
999 pos <- getPosition
1014 pos <- getPosition
1000 st <- getState
1015 st <- getState
@@ -1002,11 +1017,11 @@ atStart p = do
1002 guard $ stateLastStrPos st /= Just pos
1017 guard $ stateLastStrPos st /= Just pos
1003 p
1018 p
1004
1019
1005−emph :: RSTParser Inlines
1020+emph :: PandocMonad m => RSTParser m Inlines
1006emph = B.emph . trimInlines . mconcat <$>
1021emph = B.emph . trimInlines . mconcat <$>
1007 enclosed (atStart $ char '*') (char '*') inline
1022 enclosed (atStart $ char '*') (char '*') inline
1008
1023
1009−strong :: RSTParser Inlines
1024+strong :: PandocMonad m => RSTParser m Inlines
1010strong = B.strong . trimInlines . mconcat <$>
1025strong = B.strong . trimInlines . mconcat <$>
1011 enclosed (atStart $ string "**") (try $ string "**") inline
1026 enclosed (atStart $ string "**") (try $ string "**") inline
1012
1027
@@ -1018,12 +1033,12 @@ strong = B.strong . trimInlines . mconcat <$>
1018-- - Classes are silently discarded in addNewRole
1033-- - Classes are silently discarded in addNewRole
1019-- - Lacks sensible implementation for title-reference (which is the default)
1034-- - Lacks sensible implementation for title-reference (which is the default)
1020-- - Allows direct use of the :raw: role, rST only allows inherited use.
1035-- - Allows direct use of the :raw: role, rST only allows inherited use.
1021−interpretedRole :: RSTParser Inlines
1036+interpretedRole :: PandocMonad m => RSTParser m Inlines
1022interpretedRole = try $ do
1037interpretedRole = try $ do
1023 (role, contents) <- roleBefore <|> roleAfter
1038 (role, contents) <- roleBefore <|> roleAfter
1024 renderRole contents Nothing role nullAttr
1039 renderRole contents Nothing role nullAttr
1025
1040
1026−renderRole :: String -> Maybe String -> String -> Attr -> RSTParser Inlines
1041+renderRole :: PandocMonad m => String -> Maybe String -> String -> Attr -> RSTParser m Inlines
1027renderRole contents fmt role attr = case role of
1042renderRole contents fmt role attr = case role of
1028 "sup" -> return $ B.superscript $ B.str contents
1043 "sup" -> return $ B.superscript $ B.str contents
1029 "superscript" -> return $ B.superscript $ B.str contents
1044 "superscript" -> return $ B.superscript $ B.str contents
@@ -1050,7 +1065,7 @@ renderRole contents fmt role attr = case role of
1050 renderRole contents newFmt newRole newAttr
1065 renderRole contents newFmt newRole newAttr
1051 Nothing -> do
1066 Nothing -> do
1052 pos <- getPosition
1067 pos <- getPosition
1053− addWarning (Just pos) $ "ignoring unknown role :" ++ custom ++ ": in"
1068+ P.addWarningWithPos (Just pos) $ "ignoring unknown role :" ++ custom ++ ": in"
1054 return $ B.str contents -- Undefined role
1069 return $ B.str contents -- Undefined role
1055 where
1070 where
1056 titleRef ref = return $ B.str ref -- FIXME: Not a sensible behaviour
1071 titleRef ref = return $ B.str ref -- FIXME: Not a sensible behaviour
@@ -1063,31 +1078,31 @@ renderRole contents fmt role attr = case role of
1063addClass :: String -> Attr -> Attr
1078addClass :: String -> Attr -> Attr
1064addClass c (ident, classes, keyValues) = (ident, union classes [c], keyValues)
1079addClass c (ident, classes, keyValues) = (ident, union classes [c], keyValues)
1065
1080
1066−roleName :: RSTParser String
1081+roleName :: PandocMonad m => RSTParser m String
1067roleName = many1 (letter <|> char '-')
1082roleName = many1 (letter <|> char '-')
1068
1083
1069−roleMarker :: RSTParser String
1084+roleMarker :: PandocMonad m => RSTParser m String
1070roleMarker = char ':' *> roleName <* char ':'
1085roleMarker = char ':' *> roleName <* char ':'
1071
1086
1072−roleBefore :: RSTParser (String,String)
1087+roleBefore :: PandocMonad m => RSTParser m (String,String)
1073roleBefore = try $ do
1088roleBefore = try $ do
1074 role <- roleMarker
1089 role <- roleMarker
1075 contents <- unmarkedInterpretedText
1090 contents <- unmarkedInterpretedText
1076 return (role,contents)
1091 return (role,contents)
1077
1092
1078−roleAfter :: RSTParser (String,String)
1093+roleAfter :: PandocMonad m => RSTParser m (String,String)
1079roleAfter = try $ do
1094roleAfter = try $ do
1080 contents <- unmarkedInterpretedText
1095 contents <- unmarkedInterpretedText
1081 role <- roleMarker <|> (stateRstDefaultRole <$> getState)
1096 role <- roleMarker <|> (stateRstDefaultRole <$> getState)
1082 return (role,contents)
1097 return (role,contents)
1083
1098
1084−unmarkedInterpretedText :: RSTParser [Char]
1099+unmarkedInterpretedText :: PandocMonad m => RSTParser m [Char]
1085unmarkedInterpretedText = enclosed (atStart $ char '`') (char '`') anyChar
1100unmarkedInterpretedText = enclosed (atStart $ char '`') (char '`') anyChar
1086
1101
1087−whitespace :: RSTParser Inlines
1102+whitespace :: PandocMonad m => RSTParser m Inlines
1088whitespace = B.space <$ skipMany1 spaceChar <?> "whitespace"
1103whitespace = B.space <$ skipMany1 spaceChar <?> "whitespace"
1089
1104
1090−str :: RSTParser Inlines
1105+str :: Monad m => RSTParser m Inlines
1091str = do
1106str = do
1092 let strChar = noneOf ("\t\n " ++ specialChars)
1107 let strChar = noneOf ("\t\n " ++ specialChars)
1093 result <- many1 strChar
1108 result <- many1 strChar
@@ -1095,7 +1110,7 @@ str = do
1095 return $ B.str result
1110 return $ B.str result
1096
1111
1097-- an endline character that can be treated as a space, not a structural break
1112-- an endline character that can be treated as a space, not a structural break
1098−endline :: RSTParser Inlines
1113+endline :: Monad m => RSTParser m Inlines
1099endline = try $ do
1114endline = try $ do
1100 newline
1115 newline
1101 notFollowedBy blankline
1116 notFollowedBy blankline
@@ -1111,10 +1126,10 @@ endline = try $ do
1111-- links
1126-- links
1112--
1127--
1113
1128
1114−link :: RSTParser Inlines
1129+link :: PandocMonad m => RSTParser m Inlines
1115link = choice [explicitLink, referenceLink, autoLink] <?> "link"
1130link = choice [explicitLink, referenceLink, autoLink] <?> "link"
1116
1131
1117−explicitLink :: RSTParser Inlines
1132+explicitLink :: PandocMonad m => RSTParser m Inlines
1118explicitLink = try $ do
1133explicitLink = try $ do
1119 char '`'
1134 char '`'
1120 notFollowedBy (char '`') -- `` marks start of inline code
1135 notFollowedBy (char '`') -- `` marks start of inline code
@@ -1143,7 +1158,7 @@ explicitLink = try $ do
1143 _ -> return (src, "", nullAttr)
1158 _ -> return (src, "", nullAttr)
1144 return $ B.linkWith attr (escapeURI src') tit label''
1159 return $ B.linkWith attr (escapeURI src') tit label''
1145
1160
1146−referenceLink :: RSTParser Inlines
1161+referenceLink :: PandocMonad m => RSTParser m Inlines
1147referenceLink = try $ do
1162referenceLink = try $ do
1148 (label',ref) <- withRaw (quotedReferenceName <|> simpleReferenceName) <*
1163 (label',ref) <- withRaw (quotedReferenceName <|> simpleReferenceName) <*
1149 char '_'
1164 char '_'
@@ -1169,20 +1184,20 @@ referenceLink = try $ do
1169 when (isAnonKey key) $ updateState $ \s -> s{ stateKeys = M.delete key keyTable }
1184 when (isAnonKey key) $ updateState $ \s -> s{ stateKeys = M.delete key keyTable }
1170 return $ B.linkWith attr src tit label'
1185 return $ B.linkWith attr src tit label'
1171
1186
1172−autoURI :: RSTParser Inlines
1187+autoURI :: Monad m => RSTParser m Inlines
1173autoURI = do
1188autoURI = do
1174 (orig, src) <- uri
1189 (orig, src) <- uri
1175 return $ B.link src "" $ B.str orig
1190 return $ B.link src "" $ B.str orig
1176
1191
1177−autoEmail :: RSTParser Inlines
1192+autoEmail :: Monad m => RSTParser m Inlines
1178autoEmail = do
1193autoEmail = do
1179 (orig, src) <- emailAddress
1194 (orig, src) <- emailAddress
1180 return $ B.link src "" $ B.str orig
1195 return $ B.link src "" $ B.str orig
1181
1196
1182−autoLink :: RSTParser Inlines
1197+autoLink :: PandocMonad m => RSTParser m Inlines
1183autoLink = autoURI <|> autoEmail
1198autoLink = autoURI <|> autoEmail
1184
1199
1185−subst :: RSTParser Inlines
1200+subst :: PandocMonad m => RSTParser m Inlines
1186subst = try $ do
1201subst = try $ do
1187 (_,ref) <- withRaw $ enclosed (char '|') (char '|') inline
1202 (_,ref) <- withRaw $ enclosed (char '|') (char '|') inline
1188 state <- getState
1203 state <- getState
@@ -1196,7 +1211,7 @@ subst = try $ do
1196 return mempty
1211 return mempty
1197 Just target -> return target
1212 Just target -> return target
1198
1213
1199−note :: RSTParser Inlines
1214+note :: PandocMonad m => RSTParser m Inlines
1200note = try $ do
1215note = try $ do
1201 optional whitespace
1216 optional whitespace
1202 ref <- noteMarker
1217 ref <- noteMarker
@@ -1224,20 +1239,20 @@ note = try $ do
1224 updateState $ \st -> st{ stateNotes = newnotes }
1239 updateState $ \st -> st{ stateNotes = newnotes }
1225 return $ B.note contents
1240 return $ B.note contents
1226
1241
1227−smart :: RSTParser Inlines
1242+smart :: PandocMonad m => RSTParser m Inlines
1228smart = do
1243smart = do
1229 getOption readerSmart >>= guard
1244 getOption readerSmart >>= guard
1230 doubleQuoted <|> singleQuoted <|>
1245 doubleQuoted <|> singleQuoted <|>
1231 choice [apostrophe, dash, ellipses]
1246 choice [apostrophe, dash, ellipses]
1232
1247
1233−singleQuoted :: RSTParser Inlines
1248+singleQuoted :: PandocMonad m => RSTParser m Inlines
1234singleQuoted = try $ do
1249singleQuoted = try $ do
1235 singleQuoteStart
1250 singleQuoteStart
1236 withQuoteContext InSingleQuote $
1251 withQuoteContext InSingleQuote $
1237 B.singleQuoted . trimInlines . mconcat <$>
1252 B.singleQuoted . trimInlines . mconcat <$>
1238 many1Till inline singleQuoteEnd
1253 many1Till inline singleQuoteEnd
1239
1254
1240−doubleQuoted :: RSTParser Inlines
1255+doubleQuoted :: PandocMonad m => RSTParser m Inlines
1241doubleQuoted = try $ do
1256doubleQuoted = try $ do
1242 doubleQuoteStart
1257 doubleQuoteStart
1243 withQuoteContext InDoubleQuote $
1258 withQuoteContext InDoubleQuote $
src/Text/Pandoc/Readers/TWiki.hs+16−9
@@ -30,7 +30,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
30Conversion of twiki text to 'Pandoc' document.
30Conversion of twiki text to 'Pandoc' document.
31-}
31-}
32module Text.Pandoc.Readers.TWiki ( readTWiki
32module Text.Pandoc.Readers.TWiki ( readTWiki
33− , readTWikiWithWarnings
34 ) where
33 ) where
35
34
36import Text.Pandoc.Definition
35import Text.Pandoc.Definition
@@ -48,17 +47,25 @@ import Data.Char (isAlphaNum)
48import qualified Data.Foldable as F
47import qualified Data.Foldable as F
49import Text.Pandoc.Error
48import Text.Pandoc.Error
50
49
51−-- | Read twiki from an input string and return a Pandoc document.
50+import Control.Monad.Except (throwError)
52−readTWiki :: ReaderOptions -- ^ Reader options
51+import Text.Pandoc.Class (PandocMonad, PandocExecutionError(..))
53− -> String -- ^ String to parse (assuming @'\n'@ line endings)
52+import qualified Text.Pandoc.Class as P
54− -> Either PandocError Pandoc
55−readTWiki opts s =
56− (readWith parseTWiki) def{ stateOptions = opts } (s ++ "\n\n")
57
53
54+-- | Read twiki from an input string and return a Pandoc document.
55+readTWiki :: PandocMonad m
56+ => ReaderOptions
57+ -> String
58+ -> m Pandoc
59+readTWiki opts s = case readTWikiWithWarnings' opts s of
60+ Right (doc, warns) -> do
61+ mapM_ P.warn warns
62+ return doc
63+ Left _ -> throwError $ PandocParseError "couldn't parse TWiki"
64+
58−readTWikiWithWarnings :: ReaderOptions -- ^ Reader options
65+readTWikiWithWarnings' :: ReaderOptions -- ^ Reader options
59 -> String -- ^ String to parse (assuming @'\n'@ line endings)
66 -> String -- ^ String to parse (assuming @'\n'@ line endings)
60 -> Either PandocError (Pandoc, [String])
67 -> Either PandocError (Pandoc, [String])
61−readTWikiWithWarnings opts s =
68+readTWikiWithWarnings' opts s =
62 (readWith parseTWikiWithWarnings) def{ stateOptions = opts } (s ++ "\n\n")
69 (readWith parseTWikiWithWarnings) def{ stateOptions = opts } (s ++ "\n\n")
63 where parseTWikiWithWarnings = do
70 where parseTWikiWithWarnings = do
64 doc <- parseTWiki
71 doc <- parseTWiki
src/Text/Pandoc/Readers/Textile.hs+92−84
@@ -68,18 +68,23 @@ import Control.Monad ( guard, liftM, when )
68import Data.Monoid ((<>))
68import Data.Monoid ((<>))
69import Text.Printf
69import Text.Printf
70import Debug.Trace (trace)
70import Debug.Trace (trace)
71−import Text.Pandoc.Error
71+import Text.Pandoc.Class (PandocMonad, PandocExecutionError(..))
72+import Control.Monad.Except (throwError)
72
73
73-- | Parse a Textile text and return a Pandoc document.
74-- | Parse a Textile text and return a Pandoc document.
75+readTextile :: PandocMonad m
74−readTextile :: ReaderOptions -- ^ Reader options
76+ => ReaderOptions -- ^ Reader options
75 -> String -- ^ String to parse (assuming @'\n'@ line endings)
77 -> String -- ^ String to parse (assuming @'\n'@ line endings)
76− -> Either PandocError Pandoc
78+ -> m Pandoc
77−readTextile opts s =
79+readTextile opts s = do
78− (readWith parseTextile) def{ stateOptions = opts } (s ++ "\n\n")
80+ parsed <- readWithM parseTextile def{ stateOptions = opts } (s ++ "\n\n")
81+ case parsed of
82+ Right result -> return result
83+ Left _ -> throwError $ PandocParseError "textile parse error"
79
84
80
85
81-- | Generate a Pandoc ADT from a textile document
86-- | Generate a Pandoc ADT from a textile document
82−parseTextile :: Parser [Char] ParserState Pandoc
87+parseTextile :: PandocMonad m => ParserT [Char] ParserState m Pandoc
83parseTextile = do
88parseTextile = do
84 -- textile allows raw HTML and does smart punctuation by default,
89 -- textile allows raw HTML and does smart punctuation by default,
85 -- but we do not enable smart punctuation unless it is explicitly
90 -- but we do not enable smart punctuation unless it is explicitly
@@ -103,10 +108,10 @@ parseTextile = do
103 blocks <- parseBlocks
108 blocks <- parseBlocks
104 return $ Pandoc nullMeta (B.toList blocks) -- FIXME
109 return $ Pandoc nullMeta (B.toList blocks) -- FIXME
105
110
106−noteMarker :: Parser [Char] ParserState [Char]
111+noteMarker :: PandocMonad m => ParserT [Char] ParserState m [Char]
107noteMarker = skipMany spaceChar >> string "fn" >> manyTill digit (char '.')
112noteMarker = skipMany spaceChar >> string "fn" >> manyTill digit (char '.')
108
113
109−noteBlock :: Parser [Char] ParserState [Char]
114+noteBlock :: PandocMonad m => ParserT [Char] ParserState m [Char]
110noteBlock = try $ do
115noteBlock = try $ do
111 startPos <- getPosition
116 startPos <- getPosition
112 ref <- noteMarker
117 ref <- noteMarker
@@ -121,11 +126,11 @@ noteBlock = try $ do
121 return $ replicate (sourceLine endPos - sourceLine startPos) '\n'
126 return $ replicate (sourceLine endPos - sourceLine startPos) '\n'
122
127
123-- | Parse document blocks
128-- | Parse document blocks
124−parseBlocks :: Parser [Char] ParserState Blocks
129+parseBlocks :: PandocMonad m => ParserT [Char] ParserState m Blocks
125parseBlocks = mconcat <$> manyTill block eof
130parseBlocks = mconcat <$> manyTill block eof
126
131
127-- | Block parsers list tried in definition order
132-- | Block parsers list tried in definition order
128−blockParsers :: [Parser [Char] ParserState Blocks]
133+blockParsers :: PandocMonad m => [ParserT [Char] ParserState m Blocks]
129blockParsers = [ codeBlock
134blockParsers = [ codeBlock
130 , header
135 , header
131 , blockQuote
136 , blockQuote
@@ -140,7 +145,7 @@ blockParsers = [ codeBlock
140 ]
145 ]
141
146
142-- | Any block in the order of definition of blockParsers
147-- | Any block in the order of definition of blockParsers
143−block :: Parser [Char] ParserState Blocks
148+block :: PandocMonad m => ParserT [Char] ParserState m Blocks
144block = do
149block = do
145 res <- choice blockParsers <?> "block"
150 res <- choice blockParsers <?> "block"
146 pos <- getPosition
151 pos <- getPosition
@@ -150,16 +155,16 @@ block = do
150 (take 60 $ show $ B.toList res)) (return ())
155 (take 60 $ show $ B.toList res)) (return ())
151 return res
156 return res
152
157
153−commentBlock :: Parser [Char] ParserState Blocks
158+commentBlock :: PandocMonad m => ParserT [Char] ParserState m Blocks
154commentBlock = try $ do
159commentBlock = try $ do
155 string "###."
160 string "###."
156 manyTill anyLine blanklines
161 manyTill anyLine blanklines
157 return mempty
162 return mempty
158
163
159−codeBlock :: Parser [Char] ParserState Blocks
164+codeBlock :: PandocMonad m => ParserT [Char] ParserState m Blocks
160codeBlock = codeBlockBc <|> codeBlockPre
165codeBlock = codeBlockBc <|> codeBlockPre
161
166
162−codeBlockBc :: Parser [Char] ParserState Blocks
167+codeBlockBc :: PandocMonad m => ParserT [Char] ParserState m Blocks
163codeBlockBc = try $ do
168codeBlockBc = try $ do
164 string "bc."
169 string "bc."
165 extended <- option False (True <$ char '.')
170 extended <- option False (True <$ char '.')
@@ -179,7 +184,7 @@ trimTrailingNewlines :: String -> String
179trimTrailingNewlines = reverse . dropWhile (=='\n') . reverse
184trimTrailingNewlines = reverse . dropWhile (=='\n') . reverse
180
185
181-- | Code Blocks in Textile are between <pre> and </pre>
186-- | Code Blocks in Textile are between <pre> and </pre>
182−codeBlockPre :: Parser [Char] ParserState Blocks
187+codeBlockPre :: PandocMonad m => ParserT [Char] ParserState m Blocks
183codeBlockPre = try $ do
188codeBlockPre = try $ do
184 (t@(TagOpen _ attrs),_) <- htmlTag (tagOpen (=="pre") (const True))
189 (t@(TagOpen _ attrs),_) <- htmlTag (tagOpen (=="pre") (const True))
185 result' <- manyTill anyChar (htmlTag (tagClose (=="pre")))
190 result' <- manyTill anyChar (htmlTag (tagClose (=="pre")))
@@ -198,7 +203,7 @@ codeBlockPre = try $ do
198 return $ B.codeBlockWith (ident,classes,kvs) result'''
203 return $ B.codeBlockWith (ident,classes,kvs) result'''
199
204
200-- | Header of the form "hN. content" with N in 1..6
205-- | Header of the form "hN. content" with N in 1..6
201−header :: Parser [Char] ParserState Blocks
206+header :: PandocMonad m => ParserT [Char] ParserState m Blocks
202header = try $ do
207header = try $ do
203 char 'h'
208 char 'h'
204 level <- digitToInt <$> oneOf "123456"
209 level <- digitToInt <$> oneOf "123456"
@@ -210,14 +215,14 @@ header = try $ do
210 return $ B.headerWith attr' level name
215 return $ B.headerWith attr' level name
211
216
212-- | Blockquote of the form "bq. content"
217-- | Blockquote of the form "bq. content"
213−blockQuote :: Parser [Char] ParserState Blocks
218+blockQuote :: PandocMonad m => ParserT [Char] ParserState m Blocks
214blockQuote = try $ do
219blockQuote = try $ do
215 string "bq" >> attributes >> char '.' >> whitespace
220 string "bq" >> attributes >> char '.' >> whitespace
216 B.blockQuote <$> para
221 B.blockQuote <$> para
217
222
218-- Horizontal rule
223-- Horizontal rule
219
224
220−hrule :: Parser [Char] st Blocks
225+hrule :: PandocMonad m => ParserT [Char] st m Blocks
221hrule = try $ do
226hrule = try $ do
222 skipSpaces
227 skipSpaces
223 start <- oneOf "-*"
228 start <- oneOf "-*"
@@ -232,39 +237,39 @@ hrule = try $ do
232-- | Can be a bullet list or an ordered list. This implementation is
237-- | Can be a bullet list or an ordered list. This implementation is
233-- strict in the nesting, sublist must start at exactly "parent depth
238-- strict in the nesting, sublist must start at exactly "parent depth
234-- plus one"
239-- plus one"
235−anyList :: Parser [Char] ParserState Blocks
240+anyList :: PandocMonad m => ParserT [Char] ParserState m Blocks
236anyList = try $ anyListAtDepth 1 <* blanklines
241anyList = try $ anyListAtDepth 1 <* blanklines
237
242
238-- | This allow one type of list to be nested into an other type,
243-- | This allow one type of list to be nested into an other type,
239-- provided correct nesting
244-- provided correct nesting
240−anyListAtDepth :: Int -> Parser [Char] ParserState Blocks
245+anyListAtDepth :: PandocMonad m => Int -> ParserT [Char] ParserState m Blocks
241anyListAtDepth depth = choice [ bulletListAtDepth depth,
246anyListAtDepth depth = choice [ bulletListAtDepth depth,
242 orderedListAtDepth depth,
247 orderedListAtDepth depth,
243 definitionList ]
248 definitionList ]
244
249
245-- | Bullet List of given depth, depth being the number of leading '*'
250-- | Bullet List of given depth, depth being the number of leading '*'
246−bulletListAtDepth :: Int -> Parser [Char] ParserState Blocks
251+bulletListAtDepth :: PandocMonad m => Int -> ParserT [Char] ParserState m Blocks
247bulletListAtDepth depth = try $ B.bulletList <$> many1 (bulletListItemAtDepth depth)
252bulletListAtDepth depth = try $ B.bulletList <$> many1 (bulletListItemAtDepth depth)
248
253
249-- | Bullet List Item of given depth, depth being the number of
254-- | Bullet List Item of given depth, depth being the number of
250-- leading '*'
255-- leading '*'
251−bulletListItemAtDepth :: Int -> Parser [Char] ParserState Blocks
256+bulletListItemAtDepth :: PandocMonad m => Int -> ParserT [Char] ParserState m Blocks
252bulletListItemAtDepth = genericListItemAtDepth '*'
257bulletListItemAtDepth = genericListItemAtDepth '*'
253
258
254-- | Ordered List of given depth, depth being the number of
259-- | Ordered List of given depth, depth being the number of
255-- leading '#'
260-- leading '#'
256−orderedListAtDepth :: Int -> Parser [Char] ParserState Blocks
261+orderedListAtDepth :: PandocMonad m => Int -> ParserT [Char] ParserState m Blocks
257orderedListAtDepth depth = try $ do
262orderedListAtDepth depth = try $ do
258 items <- many1 (orderedListItemAtDepth depth)
263 items <- many1 (orderedListItemAtDepth depth)
259 return $ B.orderedList items
264 return $ B.orderedList items
260
265
261-- | Ordered List Item of given depth, depth being the number of
266-- | Ordered List Item of given depth, depth being the number of
262-- leading '#'
267-- leading '#'
263−orderedListItemAtDepth :: Int -> Parser [Char] ParserState Blocks
268+orderedListItemAtDepth :: PandocMonad m => Int -> ParserT [Char] ParserState m Blocks
264orderedListItemAtDepth = genericListItemAtDepth '#'
269orderedListItemAtDepth = genericListItemAtDepth '#'
265
270
266-- | Common implementation of list items
271-- | Common implementation of list items
267−genericListItemAtDepth :: Char -> Int -> Parser [Char] ParserState Blocks
272+genericListItemAtDepth :: PandocMonad m => Char -> Int -> ParserT [Char] ParserState m Blocks
268genericListItemAtDepth c depth = try $ do
273genericListItemAtDepth c depth = try $ do
269 count depth (char c) >> attributes >> whitespace
274 count depth (char c) >> attributes >> whitespace
270 p <- mconcat <$> many listInline
275 p <- mconcat <$> many listInline
@@ -273,25 +278,25 @@ genericListItemAtDepth c depth = try $ do
273 return $ (B.plain p) <> sublist
278 return $ (B.plain p) <> sublist
274
279
275-- | A definition list is a set of consecutive definition items
280-- | A definition list is a set of consecutive definition items
276−definitionList :: Parser [Char] ParserState Blocks
281+definitionList :: PandocMonad m => ParserT [Char] ParserState m Blocks
277definitionList = try $ B.definitionList <$> many1 definitionListItem
282definitionList = try $ B.definitionList <$> many1 definitionListItem
278
283
279-- | List start character.
284-- | List start character.
280−listStart :: Parser [Char] ParserState ()
285+listStart :: PandocMonad m => ParserT [Char] ParserState m ()
281listStart = genericListStart '*'
286listStart = genericListStart '*'
282 <|> () <$ genericListStart '#'
287 <|> () <$ genericListStart '#'
283 <|> () <$ definitionListStart
288 <|> () <$ definitionListStart
284
289
285−genericListStart :: Char -> Parser [Char] st ()
290+genericListStart :: PandocMonad m => Char -> ParserT [Char] st m ()
286genericListStart c = () <$ try (many1 (char c) >> whitespace)
291genericListStart c = () <$ try (many1 (char c) >> whitespace)
287
292
288−basicDLStart :: Parser [Char] ParserState ()
293+basicDLStart :: PandocMonad m => ParserT [Char] ParserState m ()
289basicDLStart = do
294basicDLStart = do
290 char '-'
295 char '-'
291 whitespace
296 whitespace
292 notFollowedBy newline
297 notFollowedBy newline
293
298
294−definitionListStart :: Parser [Char] ParserState Inlines
299+definitionListStart :: PandocMonad m => ParserT [Char] ParserState m Inlines
295definitionListStart = try $ do
300definitionListStart = try $ do
296 basicDLStart
301 basicDLStart
297 trimInlines . mconcat <$>
302 trimInlines . mconcat <$>
@@ -300,7 +305,7 @@ definitionListStart = try $ do
300 <|> try (lookAhead (() <$ string ":="))
305 <|> try (lookAhead (() <$ string ":="))
301 )
306 )
302
307
303−listInline :: Parser [Char] ParserState Inlines
308+listInline :: PandocMonad m => ParserT [Char] ParserState m Inlines
304listInline = try (notFollowedBy newline >> inline)
309listInline = try (notFollowedBy newline >> inline)
305 <|> try (endline <* notFollowedBy listStart)
310 <|> try (endline <* notFollowedBy listStart)
306
311
@@ -308,15 +313,15 @@ listInline = try (notFollowedBy newline >> inline)
308-- the term defined, then spaces and ":=". The definition follows, on
313-- the term defined, then spaces and ":=". The definition follows, on
309-- the same single line, or spaned on multiple line, after a line
314-- the same single line, or spaned on multiple line, after a line
310-- break.
315-- break.
311−definitionListItem :: Parser [Char] ParserState (Inlines, [Blocks])
316+definitionListItem :: PandocMonad m => ParserT [Char] ParserState m (Inlines, [Blocks])
312definitionListItem = try $ do
317definitionListItem = try $ do
313 term <- (mconcat . intersperse B.linebreak) <$> many1 definitionListStart
318 term <- (mconcat . intersperse B.linebreak) <$> many1 definitionListStart
314 def' <- string ":=" *> optional whitespace *> (multilineDef <|> inlineDef)
319 def' <- string ":=" *> optional whitespace *> (multilineDef <|> inlineDef)
315 return (term, def')
320 return (term, def')
316− where inlineDef :: Parser [Char] ParserState [Blocks]
321+ where inlineDef :: PandocMonad m => ParserT [Char] ParserState m [Blocks]
317 inlineDef = liftM (\d -> [B.plain d])
322 inlineDef = liftM (\d -> [B.plain d])
318 $ optional whitespace >> (trimInlines . mconcat <$> many listInline) <* newline
323 $ optional whitespace >> (trimInlines . mconcat <$> many listInline) <* newline
319− multilineDef :: Parser [Char] ParserState [Blocks]
324+ multilineDef :: PandocMonad m => ParserT [Char] ParserState m [Blocks]
320 multilineDef = try $ do
325 multilineDef = try $ do
321 optional whitespace >> newline
326 optional whitespace >> newline
322 s <- many1Till anyChar (try (string "=:" >> newline))
327 s <- many1Till anyChar (try (string "=:" >> newline))
@@ -327,7 +332,7 @@ definitionListItem = try $ do
327-- raw content
332-- raw content
328
333
329-- | A raw Html Block, optionally followed by blanklines
334-- | A raw Html Block, optionally followed by blanklines
330−rawHtmlBlock :: Parser [Char] ParserState Blocks
335+rawHtmlBlock :: PandocMonad m => ParserT [Char] ParserState m Blocks
331rawHtmlBlock = try $ do
336rawHtmlBlock = try $ do
332 skipMany spaceChar
337 skipMany spaceChar
333 (_,b) <- htmlTag isBlockTag
338 (_,b) <- htmlTag isBlockTag
@@ -335,14 +340,14 @@ rawHtmlBlock = try $ do
335 return $ B.rawBlock "html" b
340 return $ B.rawBlock "html" b
336
341
337-- | Raw block of LaTeX content
342-- | Raw block of LaTeX content
338−rawLaTeXBlock' :: Parser [Char] ParserState Blocks
343+rawLaTeXBlock' :: PandocMonad m => ParserT [Char] ParserState m Blocks
339rawLaTeXBlock' = do
344rawLaTeXBlock' = do
340 guardEnabled Ext_raw_tex
345 guardEnabled Ext_raw_tex
341 B.rawBlock "latex" <$> (rawLaTeXBlock <* spaces)
346 B.rawBlock "latex" <$> (rawLaTeXBlock <* spaces)
342
347
343
348
344-- | In textile, paragraphs are separated by blank lines.
349-- | In textile, paragraphs are separated by blank lines.
345−para :: Parser [Char] ParserState Blocks
350+para :: PandocMonad m => ParserT [Char] ParserState m Blocks
346para = B.para . trimInlines . mconcat <$> many1 inline
351para = B.para . trimInlines . mconcat <$> many1 inline
347
352
348-- Tables
353-- Tables
@@ -353,7 +358,7 @@ toAlignment '>' = AlignRight
353toAlignment '=' = AlignCenter
358toAlignment '=' = AlignCenter
354toAlignment _ = AlignDefault
359toAlignment _ = AlignDefault
355
360
356−cellAttributes :: Parser [Char] ParserState (Bool, Alignment)
361+cellAttributes :: PandocMonad m => ParserT [Char] ParserState m (Bool, Alignment)
357cellAttributes = try $ do
362cellAttributes = try $ do
358 isHeader <- option False (True <$ char '_')
363 isHeader <- option False (True <$ char '_')
359 -- we just ignore colspan and rowspan markers:
364 -- we just ignore colspan and rowspan markers:
@@ -366,7 +371,7 @@ cellAttributes = try $ do
366 return (isHeader, alignment)
371 return (isHeader, alignment)
367
372
368-- | A table cell spans until a pipe |
373-- | A table cell spans until a pipe |
369−tableCell :: Parser [Char] ParserState ((Bool, Alignment), Blocks)
374+tableCell :: PandocMonad m => ParserT [Char] ParserState m ((Bool, Alignment), Blocks)
370tableCell = try $ do
375tableCell = try $ do
371 char '|'
376 char '|'
372 (isHeader, alignment) <- option (False, AlignDefault) $ cellAttributes
377 (isHeader, alignment) <- option (False, AlignDefault) $ cellAttributes
@@ -377,7 +382,7 @@ tableCell = try $ do
377 return ((isHeader, alignment), B.plain content)
382 return ((isHeader, alignment), B.plain content)
378
383
379-- | A table row is made of many table cells
384-- | A table row is made of many table cells
380−tableRow :: Parser [Char] ParserState [((Bool, Alignment), Blocks)]
385+tableRow :: PandocMonad m => ParserT [Char] ParserState m [((Bool, Alignment), Blocks)]
381tableRow = try $ do
386tableRow = try $ do
382 -- skip optional row attributes
387 -- skip optional row attributes
383 optional $ try $ do
388 optional $ try $ do
@@ -387,7 +392,7 @@ tableRow = try $ do
387 many1 tableCell <* char '|' <* blankline
392 many1 tableCell <* char '|' <* blankline
388
393
389-- | A table with an optional header.
394-- | A table with an optional header.
390−table :: Parser [Char] ParserState Blocks
395+table :: PandocMonad m => ParserT [Char] ParserState m Blocks
391table = try $ do
396table = try $ do
392 -- ignore table attributes
397 -- ignore table attributes
393 caption <- option mempty $ try $ do
398 caption <- option mempty $ try $ do
@@ -411,7 +416,7 @@ table = try $ do
411 (map (map snd) rows)
416 (map (map snd) rows)
412
417
413-- | Ignore markers for cols, thead, tfoot.
418-- | Ignore markers for cols, thead, tfoot.
414−ignorableRow :: Parser [Char] ParserState ()
419+ignorableRow :: PandocMonad m => ParserT [Char] ParserState m ()
415ignorableRow = try $ do
420ignorableRow = try $ do
416 char '|'
421 char '|'
417 oneOf ":^-~"
422 oneOf ":^-~"
@@ -420,7 +425,7 @@ ignorableRow = try $ do
420 _ <- anyLine
425 _ <- anyLine
421 return ()
426 return ()
422
427
423−explicitBlockStart :: String -> Parser [Char] ParserState ()
428+explicitBlockStart :: PandocMonad m => String -> ParserT [Char] ParserState m ()
424explicitBlockStart name = try $ do
429explicitBlockStart name = try $ do
425 string name
430 string name
426 attributes
431 attributes
@@ -430,9 +435,10 @@ explicitBlockStart name = try $ do
430
435
431-- | Blocks like 'p' and 'table' do not need explicit block tag.
436-- | Blocks like 'p' and 'table' do not need explicit block tag.
432-- However, they can be used to set HTML/CSS attributes when needed.
437-- However, they can be used to set HTML/CSS attributes when needed.
438+maybeExplicitBlock :: PandocMonad m
433−maybeExplicitBlock :: String -- ^ block tag name
439+ => String -- ^ block tag name
434− -> Parser [Char] ParserState Blocks -- ^ implicit block
440+ -> ParserT [Char] ParserState m Blocks -- ^ implicit block
435− -> Parser [Char] ParserState Blocks
441+ -> ParserT [Char] ParserState m Blocks
436maybeExplicitBlock name blk = try $ do
442maybeExplicitBlock name blk = try $ do
437 optional $ explicitBlockStart name
443 optional $ explicitBlockStart name
438 blk
444 blk
@@ -445,12 +451,12 @@ maybeExplicitBlock name blk = try $ do
445
451
446
452
447-- | Any inline element
453-- | Any inline element
448−inline :: Parser [Char] ParserState Inlines
454+inline :: PandocMonad m => ParserT [Char] ParserState m Inlines
449inline = do
455inline = do
450 choice inlineParsers <?> "inline"
456 choice inlineParsers <?> "inline"
451
457
452-- | Inline parsers tried in order
458-- | Inline parsers tried in order
453−inlineParsers :: [Parser [Char] ParserState Inlines]
459+inlineParsers :: PandocMonad m => [ParserT [Char] ParserState m Inlines]
454inlineParsers = [ str
460inlineParsers = [ str
455 , whitespace
461 , whitespace
456 , endline
462 , endline
@@ -470,7 +476,7 @@ inlineParsers = [ str
470 ]
476 ]
471
477
472-- | Inline markups
478-- | Inline markups
473−inlineMarkup :: Parser [Char] ParserState Inlines
479+inlineMarkup :: PandocMonad m => ParserT [Char] ParserState m Inlines
474inlineMarkup = choice [ simpleInline (string "??") (B.cite [])
480inlineMarkup = choice [ simpleInline (string "??") (B.cite [])
475 , simpleInline (string "**") B.strong
481 , simpleInline (string "**") B.strong
476 , simpleInline (string "__") B.emph
482 , simpleInline (string "__") B.emph
@@ -484,29 +490,29 @@ inlineMarkup = choice [ simpleInline (string "??") (B.cite [])
484 ]
490 ]
485
491
486-- | Trademark, registered, copyright
492-- | Trademark, registered, copyright
487−mark :: Parser [Char] st Inlines
493+mark :: PandocMonad m => ParserT [Char] st m Inlines
488mark = try $ char '(' >> (try tm <|> try reg <|> copy)
494mark = try $ char '(' >> (try tm <|> try reg <|> copy)
489
495
490−reg :: Parser [Char] st Inlines
496+reg :: PandocMonad m => ParserT [Char] st m Inlines
491reg = do
497reg = do
492 oneOf "Rr"
498 oneOf "Rr"
493 char ')'
499 char ')'
494 return $ B.str "\174"
500 return $ B.str "\174"
495
501
496−tm :: Parser [Char] st Inlines
502+tm :: PandocMonad m => ParserT [Char] st m Inlines
497tm = do
503tm = do
498 oneOf "Tt"
504 oneOf "Tt"
499 oneOf "Mm"
505 oneOf "Mm"
500 char ')'
506 char ')'
501 return $ B.str "\8482"
507 return $ B.str "\8482"
502
508
503−copy :: Parser [Char] st Inlines
509+copy :: PandocMonad m => ParserT [Char] st m Inlines
504copy = do
510copy = do
505 oneOf "Cc"
511 oneOf "Cc"
506 char ')'
512 char ')'
507 return $ B.str "\169"
513 return $ B.str "\169"
508
514
509−note :: Parser [Char] ParserState Inlines
515+note :: PandocMonad m => ParserT [Char] ParserState m Inlines
510note = try $ do
516note = try $ do
511 ref <- (char '[' *> many1 digit <* char ']')
517 ref <- (char '[' *> many1 digit <* char ']')
512 notes <- stateNotes <$> getState
518 notes <- stateNotes <$> getState
@@ -530,13 +536,13 @@ wordBoundaries :: [Char]
530wordBoundaries = markupChars ++ stringBreakers
536wordBoundaries = markupChars ++ stringBreakers
531
537
532-- | Parse a hyphened sequence of words
538-- | Parse a hyphened sequence of words
533−hyphenedWords :: Parser [Char] ParserState String
539+hyphenedWords :: PandocMonad m => ParserT [Char] ParserState m String
534hyphenedWords = do
540hyphenedWords = do
535 x <- wordChunk
541 x <- wordChunk
536 xs <- many (try $ char '-' >> wordChunk)
542 xs <- many (try $ char '-' >> wordChunk)
537 return $ intercalate "-" (x:xs)
543 return $ intercalate "-" (x:xs)
538
544
539−wordChunk :: Parser [Char] ParserState String
545+wordChunk :: PandocMonad m => ParserT [Char] ParserState m String
540wordChunk = try $ do
546wordChunk = try $ do
541 hd <- noneOf wordBoundaries
547 hd <- noneOf wordBoundaries
542 tl <- many ( (noneOf wordBoundaries) <|>
548 tl <- many ( (noneOf wordBoundaries) <|>
@@ -545,7 +551,7 @@ wordChunk = try $ do
545 return $ hd:tl
551 return $ hd:tl
546
552
547-- | Any string
553-- | Any string
548−str :: Parser [Char] ParserState Inlines
554+str :: PandocMonad m => ParserT [Char] ParserState m Inlines
549str = do
555str = do
550 baseStr <- hyphenedWords
556 baseStr <- hyphenedWords
551 -- RedCloth compliance : if parsed word is uppercase and immediatly
557 -- RedCloth compliance : if parsed word is uppercase and immediatly
@@ -558,11 +564,11 @@ str = do
558 return $ B.str fullStr
564 return $ B.str fullStr
559
565
560-- | Some number of space chars
566-- | Some number of space chars
561−whitespace :: Parser [Char] st Inlines
567+whitespace :: PandocMonad m => ParserT [Char] st m Inlines
562whitespace = many1 spaceChar >> return B.space <?> "whitespace"
568whitespace = many1 spaceChar >> return B.space <?> "whitespace"
563
569
564-- | In Textile, an isolated endline character is a line break
570-- | In Textile, an isolated endline character is a line break
565−endline :: Parser [Char] ParserState Inlines
571+endline :: PandocMonad m => ParserT [Char] ParserState m Inlines
566endline = try $ do
572endline = try $ do
567 newline
573 newline
568 notFollowedBy blankline
574 notFollowedBy blankline
@@ -570,18 +576,18 @@ endline = try $ do
570 notFollowedBy rawHtmlBlock
576 notFollowedBy rawHtmlBlock
571 return B.linebreak
577 return B.linebreak
572
578
573−rawHtmlInline :: Parser [Char] ParserState Inlines
579+rawHtmlInline :: PandocMonad m => ParserT [Char] ParserState m Inlines
574rawHtmlInline = B.rawInline "html" . snd <$> htmlTag isInlineTag
580rawHtmlInline = B.rawInline "html" . snd <$> htmlTag isInlineTag
575
581
576-- | Raw LaTeX Inline
582-- | Raw LaTeX Inline
577−rawLaTeXInline' :: Parser [Char] ParserState Inlines
583+rawLaTeXInline' :: PandocMonad m => ParserT [Char] ParserState m Inlines
578rawLaTeXInline' = try $ do
584rawLaTeXInline' = try $ do
579 guardEnabled Ext_raw_tex
585 guardEnabled Ext_raw_tex
580 B.singleton <$> rawLaTeXInline
586 B.singleton <$> rawLaTeXInline
581
587
582-- | Textile standard link syntax is "label":target. But we
588-- | Textile standard link syntax is "label":target. But we
583-- can also have ["label":target].
589-- can also have ["label":target].
584−link :: Parser [Char] ParserState Inlines
590+link :: PandocMonad m => ParserT [Char] ParserState m Inlines
585link = try $ do
591link = try $ do
586 bracketed <- (True <$ char '[') <|> return False
592 bracketed <- (True <$ char '[') <|> return False
587 char '"' *> notFollowedBy (oneOf " \t\n\r")
593 char '"' *> notFollowedBy (oneOf " \t\n\r")
@@ -600,7 +606,7 @@ link = try $ do
600 else B.spanWith attr $ B.link url "" name'
606 else B.spanWith attr $ B.link url "" name'
601
607
602-- | image embedding
608-- | image embedding
603−image :: Parser [Char] ParserState Inlines
609+image :: PandocMonad m => ParserT [Char] ParserState m Inlines
604image = try $ do
610image = try $ do
605 char '!' >> notFollowedBy space
611 char '!' >> notFollowedBy space
606 (ident, cls, kvs) <- attributes
612 (ident, cls, kvs) <- attributes
@@ -612,50 +618,50 @@ image = try $ do
612 char '!'
618 char '!'
613 return $ B.imageWith attr src alt (B.str alt)
619 return $ B.imageWith attr src alt (B.str alt)
614
620
615−escapedInline :: Parser [Char] ParserState Inlines
621+escapedInline :: PandocMonad m => ParserT [Char] ParserState m Inlines
616escapedInline = escapedEqs <|> escapedTag
622escapedInline = escapedEqs <|> escapedTag
617
623
618−escapedEqs :: Parser [Char] ParserState Inlines
624+escapedEqs :: PandocMonad m => ParserT [Char] ParserState m Inlines
619escapedEqs = B.str <$>
625escapedEqs = B.str <$>
620 (try $ string "==" *> manyTill anyChar' (try $ string "=="))
626 (try $ string "==" *> manyTill anyChar' (try $ string "=="))
621
627
622-- | literal text escaped btw <notextile> tags
628-- | literal text escaped btw <notextile> tags
623−escapedTag :: Parser [Char] ParserState Inlines
629+escapedTag :: PandocMonad m => ParserT [Char] ParserState m Inlines
624escapedTag = B.str <$>
630escapedTag = B.str <$>
625 (try $ string "<notextile>" *>
631 (try $ string "<notextile>" *>
626 manyTill anyChar' (try $ string "</notextile>"))
632 manyTill anyChar' (try $ string "</notextile>"))
627
633
628-- | Any special symbol defined in wordBoundaries
634-- | Any special symbol defined in wordBoundaries
629−symbol :: Parser [Char] ParserState Inlines
635+symbol :: PandocMonad m => ParserT [Char] ParserState m Inlines
630symbol = B.str . singleton <$> (notFollowedBy newline *>
636symbol = B.str . singleton <$> (notFollowedBy newline *>
631 notFollowedBy rawHtmlBlock *>
637 notFollowedBy rawHtmlBlock *>
632 oneOf wordBoundaries)
638 oneOf wordBoundaries)
633
639
634-- | Inline code
640-- | Inline code
635−code :: Parser [Char] ParserState Inlines
641+code :: PandocMonad m => ParserT [Char] ParserState m Inlines
636code = code1 <|> code2
642code = code1 <|> code2
637
643
638-- any character except a newline before a blank line
644-- any character except a newline before a blank line
639−anyChar' :: Parser [Char] ParserState Char
645+anyChar' :: PandocMonad m => ParserT [Char] ParserState m Char
640anyChar' =
646anyChar' =
641 satisfy (/='\n') <|> (try $ char '\n' <* notFollowedBy blankline)
647 satisfy (/='\n') <|> (try $ char '\n' <* notFollowedBy blankline)
642
648
643−code1 :: Parser [Char] ParserState Inlines
649+code1 :: PandocMonad m => ParserT [Char] ParserState m Inlines
644code1 = B.code <$> surrounded (char '@') anyChar'
650code1 = B.code <$> surrounded (char '@') anyChar'
645
651
646−code2 :: Parser [Char] ParserState Inlines
652+code2 :: PandocMonad m => ParserT [Char] ParserState m Inlines
647code2 = do
653code2 = do
648 htmlTag (tagOpen (=="tt") null)
654 htmlTag (tagOpen (=="tt") null)
649 B.code <$> manyTill anyChar' (try $ htmlTag $ tagClose (=="tt"))
655 B.code <$> manyTill anyChar' (try $ htmlTag $ tagClose (=="tt"))
650
656
651-- | Html / CSS attributes
657-- | Html / CSS attributes
652−attributes :: Parser [Char] ParserState Attr
658+attributes :: PandocMonad m => ParserT [Char] ParserState m Attr
653attributes = (foldl (flip ($)) ("",[],[])) <$>
659attributes = (foldl (flip ($)) ("",[],[])) <$>
654 try (do special <- option id specialAttribute
660 try (do special <- option id specialAttribute
655 attrs <- many attribute
661 attrs <- many attribute
656 return (special : attrs))
662 return (special : attrs))
657
663
658−specialAttribute :: Parser [Char] ParserState (Attr -> Attr)
664+specialAttribute :: PandocMonad m => ParserT [Char] ParserState m (Attr -> Attr)
659specialAttribute = do
665specialAttribute = do
660 alignStr <- ("center" <$ char '=') <|>
666 alignStr <- ("center" <$ char '=') <|>
661 ("justify" <$ try (string "<>")) <|>
667 ("justify" <$ try (string "<>")) <|>
@@ -664,11 +670,11 @@ specialAttribute = do
664 notFollowedBy spaceChar
670 notFollowedBy spaceChar
665 return $ addStyle ("text-align:" ++ alignStr)
671 return $ addStyle ("text-align:" ++ alignStr)
666
672
667−attribute :: Parser [Char] ParserState (Attr -> Attr)
673+attribute :: PandocMonad m => ParserT [Char] ParserState m (Attr -> Attr)
668attribute = try $
674attribute = try $
669 (classIdAttr <|> styleAttr <|> langAttr) <* notFollowedBy spaceChar
675 (classIdAttr <|> styleAttr <|> langAttr) <* notFollowedBy spaceChar
670
676
671−classIdAttr :: Parser [Char] ParserState (Attr -> Attr)
677+classIdAttr :: PandocMonad m => ParserT [Char] ParserState m (Attr -> Attr)
672classIdAttr = try $ do -- (class class #id)
678classIdAttr = try $ do -- (class class #id)
673 char '('
679 char '('
674 ws <- words `fmap` manyTill anyChar' (char ')')
680 ws <- words `fmap` manyTill anyChar' (char ')')
@@ -679,7 +685,7 @@ classIdAttr = try $ do -- (class class #id)
679 classes' -> return $ \(_,_,keyvals) ->
685 classes' -> return $ \(_,_,keyvals) ->
680 ("",classes',keyvals)
686 ("",classes',keyvals)
681
687
682−styleAttr :: Parser [Char] ParserState (Attr -> Attr)
688+styleAttr :: PandocMonad m => ParserT [Char] ParserState m (Attr -> Attr)
683styleAttr = do
689styleAttr = do
684 style <- try $ enclosed (char '{') (char '}') anyChar'
690 style <- try $ enclosed (char '{') (char '}') anyChar'
685 return $ addStyle style
691 return $ addStyle style
@@ -690,21 +696,23 @@ addStyle style (id',classes,keyvals) =
690 where keyvals' = ("style", style') : [(k,v) | (k,v) <- keyvals, k /= "style"]
696 where keyvals' = ("style", style') : [(k,v) | (k,v) <- keyvals, k /= "style"]
691 style' = style ++ ";" ++ concat [v | ("style",v) <- keyvals]
697 style' = style ++ ";" ++ concat [v | ("style",v) <- keyvals]
692
698
693−langAttr :: Parser [Char] ParserState (Attr -> Attr)
699+langAttr :: PandocMonad m => ParserT [Char] ParserState m (Attr -> Attr)
694langAttr = do
700langAttr = do
695 lang <- try $ enclosed (char '[') (char ']') alphaNum
701 lang <- try $ enclosed (char '[') (char ']') alphaNum
696 return $ \(id',classes,keyvals) -> (id',classes,("lang",lang):keyvals)
702 return $ \(id',classes,keyvals) -> (id',classes,("lang",lang):keyvals)
697
703
698-- | Parses material surrounded by a parser.
704-- | Parses material surrounded by a parser.
705+surrounded :: PandocMonad m
699−surrounded :: Parser [Char] st t -- ^ surrounding parser
706+ => ParserT [Char] st m t -- ^ surrounding parser
700− -> Parser [Char] st a -- ^ content parser (to be used repeatedly)
707+ -> ParserT [Char] st m a -- ^ content parser (to be used repeatedly)
701− -> Parser [Char] st [a]
708+ -> ParserT [Char] st m [a]
702surrounded border =
709surrounded border =
703 enclosed (border *> notFollowedBy (oneOf " \t\n\r")) (try border)
710 enclosed (border *> notFollowedBy (oneOf " \t\n\r")) (try border)
704
711
712+simpleInline :: PandocMonad m
705−simpleInline :: Parser [Char] ParserState t -- ^ surrounding parser
713+ => ParserT [Char] ParserState m t -- ^ surrounding parser
706− -> (Inlines -> Inlines) -- ^ Inline constructor
714+ -> (Inlines -> Inlines) -- ^ Inline constructor
707− -> Parser [Char] ParserState Inlines -- ^ content parser (to be used repeatedly)
715+ -> ParserT [Char] ParserState m Inlines -- ^ content parser (to be used repeatedly)
708simpleInline border construct = try $ do
716simpleInline border construct = try $ do
709 notAfterString
717 notAfterString
710 border *> notFollowedBy (oneOf " \t\n\r")
718 border *> notFollowedBy (oneOf " \t\n\r")
@@ -718,7 +726,7 @@ simpleInline border construct = try $ do
718 then body
726 then body
719 else B.spanWith attr body
727 else B.spanWith attr body
720
728
721−groupedInlineMarkup :: Parser [Char] ParserState Inlines
729+groupedInlineMarkup :: PandocMonad m => ParserT [Char] ParserState m Inlines
722groupedInlineMarkup = try $ do
730groupedInlineMarkup = try $ do
723 char '['
731 char '['
724 sp1 <- option mempty $ B.space <$ whitespace
732 sp1 <- option mempty $ B.space <$ whitespace
src/Text/Pandoc/Readers/Txt2Tags.hs+30−15
@@ -46,13 +46,12 @@ import Data.Maybe (fromMaybe)
46import Control.Monad (void, guard, when)
46import Control.Monad (void, guard, when)
47import Data.Default
47import Data.Default
48import Control.Monad.Reader (Reader, runReader, asks)
48import Control.Monad.Reader (Reader, runReader, asks)
49−import Text.Pandoc.Error
50
49
51−import Data.Time.LocalTime (getZonedTime)
52−import System.Directory(getModificationTime)
53import Data.Time.Format (formatTime)
50import Data.Time.Format (formatTime)
54import Text.Pandoc.Compat.Time (defaultTimeLocale)
51import Text.Pandoc.Compat.Time (defaultTimeLocale)
55−import System.IO.Error (catchIOError)
52+import Control.Monad.Except (throwError, catchError)
53+import Text.Pandoc.Class (PandocMonad, PandocExecutionError(..))
54+import qualified Text.Pandoc.Class as P
56
55
57type T2T = ParserT String ParserState (Reader T2TMeta)
56type T2T = ParserT String ParserState (Reader T2TMeta)
58
57
@@ -69,26 +68,42 @@ instance Default T2TMeta where
69 def = T2TMeta "" "" "" ""
68 def = T2TMeta "" "" "" ""
70
69
71-- | Get the meta information required by Txt2Tags macros
70-- | Get the meta information required by Txt2Tags macros
72−getT2TMeta :: [FilePath] -> FilePath -> IO T2TMeta
71+getT2TMeta :: PandocMonad m => m T2TMeta
73−getT2TMeta inps out = do
72+getT2TMeta = do
73+ mbInps <- P.getInputFiles
74+ let inps = case mbInps of
75+ Just x -> x
76+ Nothing -> []
77+ mbOutp <- P.getOutputFile
78+ let outp = case mbOutp of
79+ Just x -> x
80+ Nothing -> ""
74− curDate <- formatTime defaultTimeLocale "%F" <$> getZonedTime
81+ curDate <- formatTime defaultTimeLocale "%F" <$> P.getZonedTime
75 let getModTime = fmap (formatTime defaultTimeLocale "%T") .
82 let getModTime = fmap (formatTime defaultTimeLocale "%T") .
76− getModificationTime
83+ P.getModificationTime
77 curMtime <- case inps of
84 curMtime <- case inps of
78− [] -> formatTime defaultTimeLocale "%T" <$> getZonedTime
85+ [] -> formatTime defaultTimeLocale "%T" <$> P.getZonedTime
79− _ -> catchIOError
86+ _ -> catchError
80 (maximum <$> mapM getModTime inps)
87 (maximum <$> mapM getModTime inps)
81 (const (return ""))
88 (const (return ""))
82− return $ T2TMeta curDate curMtime (intercalate ", " inps) out
89+ return $ T2TMeta curDate curMtime (intercalate ", " inps) outp
83
90
84-- | Read Txt2Tags from an input string returning a Pandoc document
91-- | Read Txt2Tags from an input string returning a Pandoc document
85−readTxt2Tags :: T2TMeta -> ReaderOptions -> String -> Either PandocError Pandoc
92+readTxt2Tags :: PandocMonad m
93+ => ReaderOptions
94+ -> String
95+ -> m Pandoc
96+readTxt2Tags opts s = do
97+ meta <- getT2TMeta
86−readTxt2Tags t opts s = flip runReader t $ readWithM parseT2T (def {stateOptions = opts}) (s ++ "\n\n")
98+ let parsed = flip runReader meta $ readWithM parseT2T (def {stateOptions = opts}) (s ++ "\n\n")
99+ case parsed of
100+ Right result -> return $ result
101+ Left _ -> throwError $ PandocParseError "error parsing t2t"
87
102
88-- | Read Txt2Tags (ignoring all macros) from an input string returning
103-- | Read Txt2Tags (ignoring all macros) from an input string returning
89-- a Pandoc document
104-- a Pandoc document
90−readTxt2TagsNoMacros :: ReaderOptions -> String -> Either PandocError Pandoc
105+readTxt2TagsNoMacros :: PandocMonad m => ReaderOptions -> String -> m Pandoc
91−readTxt2TagsNoMacros = readTxt2Tags def
106+readTxt2TagsNoMacros = readTxt2Tags
92
107
93parseT2T :: T2T Pandoc
108parseT2T :: T2T Pandoc
94parseT2T = do
109parseT2T = do