@@ -34,10 +34,11 @@ import Text.Pandoc.Definition
3434import Text.Pandoc.Shared
3535import Text.Pandoc.Parsing
3636import Text.ParserCombinators.Parsec
37−import Control.Monad ( when, unless )
37+import Control.Monad ( when )
3838import Data.List ( findIndex, intercalate, transpose, sort, deleteFirstsBy )
3939import qualified Data.Map as M
4040import Text.Printf ( printf )
41+import Data.Maybe ( catMaybes )
4142
4243-- | Parse reStructuredText string and return Pandoc document.
4344readRST :: ParserState -- ^ Parser state, including options for parser
@@ -121,10 +122,9 @@ parseBlocks = manyTill block eof
121122
122123block :: GenParser Char ParserState Block
123124block = choice [ codeBlock
124− , rawHtmlBlock
125− , rawLaTeXBlock
126− , fieldList
125+ , rawBlock
127126 , blockQuote
127+ , fieldList
128128 , imageBlock
129129 , customCodeBlock
130130 , unknownDirective
@@ -142,48 +142,54 @@ block = choice [ codeBlock
142142-- field list
143143--
144144
145−fieldListItem :: String -> GenParser Char st ([Char], [Char])
146−fieldListItem indent = try $ do
145+rawFieldListItem :: String -> GenParser Char ParserState (String, String)
146+rawFieldListItem indent = try $ do
147147 string indent
148148 char ':'
149149 name <- many1 $ alphaNum <|> spaceChar
150150 string ": "
151151 skipSpaces
152152 first <- manyTill anyChar newline
153− rest <- option "" $ try $ lookAhead (string indent >> spaceChar) >>
154− indentedBlock
155− return (name, first ++ if null rest
156− then ""
157− else ("\n" ++ rest))
153+ rest <- option "" $ try $ do lookAhead (string indent >> spaceChar)
154+ indentedBlock
155+ let raw = first ++ "\n" ++ rest ++ "\n"
156+ return (name, raw)
157+
158+fieldListItem :: String
159+ -> GenParser Char ParserState (Maybe ([Inline], [[Block]]))
160+fieldListItem indent = try $ do
161+ (name, raw) <- rawFieldListItem indent
162+ let term = [Str name]
163+ contents <- parseFromString (many block) raw
164+ case (name, contents) of
165+ ("Author", x) -> do
166+ updateState $ \st ->
167+ st{ stateAuthors = stateAuthors st ++ [extractContents x] }
168+ return Nothing
169+ ("Authors", [BulletList auths]) -> do
170+ updateState $ \st -> st{ stateAuthors = map extractContents auths }
171+ return Nothing
172+ ("Date", x) -> do
173+ updateState $ \st -> st{ stateDate = extractContents x }
174+ return Nothing
175+ ("Title", x) -> do
176+ updateState $ \st -> st{ stateTitle = extractContents x }
177+ return Nothing
178+ _ -> return $ Just (term, [contents])
179+
180+extractContents :: [Block] -> [Inline]
181+extractContents [Plain auth] = auth
182+extractContents [Para auth] = auth
183+extractContents _ = []
158184
159185fieldList :: GenParser Char ParserState Block
160186fieldList = try $ do
161187 indent <- lookAhead $ many spaceChar
162188 items <- many1 $ fieldListItem indent
163189 blanklines
164− let authors = case lookup "Authors" items of
165− Just auth -> [auth]
166− Nothing -> map snd (filter (\(x,_) -> x == "Author") items)
167− unless (null authors) $ do
168− authors' <- mapM (parseFromString (many inline)) authors
169− updateState $ \st -> st {stateAuthors = map normalizeSpaces authors'}
170− case (lookup "Date" items) of
171− Just dat -> do
172− dat' <- parseFromString (many inline) dat
173− updateState $ \st -> st{ stateDate = normalizeSpaces dat' }
174− Nothing -> return ()
175− case (lookup "Title" items) of
176− Just tit -> parseFromString (many inline) tit >>=
177− \t -> updateState $ \st -> st {stateTitle = t}
178− Nothing -> return ()
179− let remaining = filter (\(x,_) -> (x /= "Authors") && (x /= "Author") &&
180− (x /= "Date") && (x /= "Title")) items
181− if null remaining
182− then return Null
183− else do terms <- mapM (return . (:[]) . Str . fst) remaining
184− defs <- mapM (parseFromString (many block) . snd)
185− remaining
186− return $ DefinitionList $ zip terms $ map (:[]) defs
190+ if null items
191+ then return Null
192+ else return $ DefinitionList $ catMaybes items
187193
188194--
189195-- line block
@@ -237,15 +243,16 @@ plain = many1 inline >>= return . Plain . normalizeSpaces
237243-- image block
238244--
239245
240−imageBlock :: GenParser Char st Block
246+imageBlock :: GenParser Char ParserState Block
241247imageBlock = try $ do
242248 string ".. image:: "
243249 src <- manyTill anyChar newline
244− fields <- option [] $ do indent <- lookAhead $ many (oneOf " /t")
245− many1 $ fieldListItem indent
250+ fields <- try $ do indent <- lookAhead $ many (oneOf " /t")
251+ many $ rawFieldListItem indent
246252 optional blanklines
247253 case lookup "alt" fields of
248− Just alt -> return $ Plain [Image [Str alt] (src, alt)]
254+ Just alt -> return $ Plain [Image [Str $ removeTrailingSpace alt]
255+ (src, "")]
249256 Nothing -> return $ Plain [Image [Str "image"] (src, "")]
250257--
251258-- header blocks
@@ -320,20 +327,19 @@ hrule = try $ do
320327indentedLine :: String -> GenParser Char st [Char]
321328indentedLine indents = try $ do
322329 string indents
323− result <- manyTill anyChar newline
324− return $ result ++ "\n"
330+ manyTill anyChar newline
325331
326332-- two or more indented lines, possibly separated by blank lines.
327333-- any amount of indentation will work.
328334indentedBlock :: GenParser Char st [Char]
329−indentedBlock = do
335+indentedBlock = try $ do
330336 indents <- lookAhead $ many1 spaceChar
331337 lns <- many $ choice $ [ indentedLine indents,
332338 try $ do b <- blanklines
333339 l <- indentedLine indents
334340 return (b ++ l) ]
335− optional blanklines
336− return $ concat lns
341+ optional blanklines
342+ return $ unlines lns
337343
338344codeBlock :: GenParser Char st Block
339345codeBlock = try $ do
@@ -371,25 +377,16 @@ birdTrackLine = do
371377 manyTill anyChar newline
372378
373379--
374−-- raw html
380+-- raw html/latex/etc
375381--
376382
377−rawHtmlBlock :: GenParser Char st Block
378−rawHtmlBlock = try $ do
379− string ".. raw:: html"
380− blanklines
381− indentedBlock >>= return . RawBlock "html"
382−
383−--
384−-- raw latex
385−--
386−
387−rawLaTeXBlock :: GenParser Char st Block
388−rawLaTeXBlock = try $ do
389− string ".. raw:: latex"
383+rawBlock :: GenParser Char st Block
384+rawBlock = try $ do
385+ string ".. raw:: "
386+ lang <- many1 (letter <|> digit)
390387 blanklines
391388 result <- indentedBlock
392− return $ RawBlock "latex" result
389+ return $ RawBlock lang result
393390
394391--
395392-- block quotes
@@ -416,7 +413,7 @@ definitionListItem = try $ do
416413 term <- many1Till inline endline
417414 raw <- indentedBlock
418415 -- parse the extracted block, which may contain various block elements:
419− contents <- parseFromString parseBlocks $ raw ++ "\n\n"
416+ contents <- parseFromString parseBlocks $ raw ++ "\n"
420417 return (normalizeSpaces term, [contents])
421418
422419definitionList :: GenParser Char ParserState Block