git.iko.soy/typeable/pandoc
on master help sign in
Revised citation parsers for markdown reader.

Added a form for in-text citations: @doe99 [30; see also @smith99].

commit79bab2d210ffadaf4f3b6a2a7ebc33ea546dd5e0 authorJohn MacFarlane <jgm@berkeley.edu> dateFri 12 Nov 2010, 00:37 (16 years ago) parent5c6dc57
1 file changed+96−44
src/Text/Pandoc/Readers/Markdown.hs+96−44
src/Text/Pandoc/Readers/Markdown.hs+96−44
@@ -373,6 +373,7 @@ attributes = try $ do
373373attribute :: GenParser Char st ([Char], [[Char]], [([Char], [Char])])
374374attribute = identifierAttr <|> classAttr <|> keyValAttr
375375
376+
376377identifier :: GenParser Char st [Char]
377378identifier = do
378379 first <- letter
@@ -912,7 +913,7 @@ inlineParsers = [ str
912913 , note
913914 , inlineNote
914915 , link
915− , inlineCitation
916+ , cite
916917 , image
917918 , math
918919 , strikeout
@@ -1303,48 +1304,99 @@ rawHtmlInline' = do
13031304 else choice [htmlComment, anyHtmlInlineTag]
13041305 return $ HtmlInline result
13051306
1306−inlineCitation :: GenParser Char ParserState Inline
1307−inlineCitation = try $ do
1307+-- Citations
1308+
1309+cite :: GenParser Char ParserState Inline
1310+cite = do
13081311 failIfStrict
1309− cit <- citeMarker
1310− let citations = readWith parseCitation defaultParserState cit
1311− mr <- mapM chkCit citations
1312− if catMaybes mr /= []
1313− then return $ Cite citations []
1314− else fail "no citation found"
1315−
1316−chkCit :: Citation -> GenParser Char ParserState (Maybe Citation)
1317−chkCit t = do
1312+ textualCite <|> normalCite
1313+
1314+spnl :: GenParser Char st ()
1315+spnl = try $ skipSpaces >> optional newline >> skipSpaces >>
1316+ notFollowedBy (char '\n')
1317+
1318+textualCite :: GenParser Char ParserState Inline
1319+textualCite = try $ do
1320+ key <- citeKey
13181321 st <- getState
1319− case lookupKeySrc (stateKeys st) (Key [Str $ citationId t]) of
1320− Just _ -> fail "This is a link"
1321− Nothing -> if elem (citationId t) $ stateCitations st
1322− then return $ Just t
1323− else return $ Nothing
1324−
1325−citeMarker :: GenParser Char ParserState String
1326−citeMarker = char '[' >> manyTill ( noneOf "\n" <|> (newline >>~ notFollowedBy blankline) ) (char ']')
1327−
1328−parseCitation :: GenParser Char ParserState [Citation]
1329−parseCitation = try $ sepBy (parseLabel) (skipMany1 $ char ';')
1330−
1331−parseLabel :: GenParser Char ParserState Citation
1332−parseLabel = try $ do
1333− r <- many (noneOf ";")
1334− let t' s = if s /= [] then tail s else []
1335− trim = unwords . words
1336− pref = takeWhile (/= '@') r
1337− rest = t' $ dropWhile (/= '@') r
1338− cit = takeWhile (/= ',') rest
1339− loc = t' $ dropWhile (/= ',') rest
1340− (p,na) = if pref /= [] && last pref == '-'
1341− then (init pref, True )
1342− else (pref , False)
1343− (p',o) = if p /= [] && last p == '+'
1344− then (init p , True )
1345− else (p , False)
1346− mode = case (na,o) of
1347− (True, False) -> SuppressAuthor
1348− (False,True ) -> AuthorInText
1349− _ -> NormalCitation
1350− return $ Citation cit (trim p') (trim loc) mode 0 0
1322+ unless (key `elem` stateCitations st) $
1323+ fail "not a citation"
1324+ let first = Citation{ citationId = key
1325+ , citationPrefix = ""
1326+ , citationLocator = ""
1327+ , citationMode = AuthorInText
1328+ , citationNoteNum = 0
1329+ , citationHash = 0
1330+ }
1331+ option (Cite [first] []) $ try $ do
1332+ spnl
1333+ char '['
1334+ spnl
1335+ bareloc <- option "" locator
1336+ rest <- many $ try $ do
1337+ char ';'
1338+ spnl
1339+ citation
1340+ spnl
1341+ char ']'
1342+ let first' = if null bareloc
1343+ then first
1344+ else first{ citationLocator = bareloc
1345+ , citationMode = AuthorInText }
1346+ return $ Cite (first' : rest) []
1347+
1348+normalCite :: GenParser Char ParserState Inline
1349+normalCite = try $ do
1350+ cites <- citeList
1351+ return $ Cite cites []
1352+
1353+citeKey :: GenParser Char st String
1354+citeKey = try $ do
1355+ char '@'
1356+ first <- letter
1357+ rest <- many $ noneOf ",;]@ \t\n"
1358+ return (first:rest)
1359+
1360+locator :: GenParser Char st String
1361+locator = try $ do
1362+ optional $ char ','
1363+ spnl
1364+ -- TODO should eventually be list of inlines
1365+ many1 $ (char '\\' >> oneOf "];\n") <|> noneOf "];\n" <|>
1366+ (char '\n' >> notFollowedBy blankline >> return ' ')
1367+
1368+prefix :: GenParser Char st String
1369+prefix = try $ liftM removeLeadingTrailingSpace $
1370+ many $ (char '\\' >> anyChar) <|> noneOf "@]\n" <|>
1371+ (char '-' >> notFollowedBy (char '@') >> return '-') <|>
1372+ (char '\n' >> notFollowedBy blankline >> return ' ')
1373+
1374+citeList :: GenParser Char st [Citation]
1375+citeList = try $ do
1376+ char '['
1377+ spnl
1378+ first <- citation
1379+ spnl
1380+ rest <- many $ try $ do
1381+ char ';'
1382+ spnl
1383+ citation
1384+ spnl
1385+ char ']'
1386+ return (first:rest)
1387+
1388+citation :: GenParser Char st Citation
1389+citation = try $ do
1390+ suppress_auth <- option False (char '-' >> return True)
1391+ pref <- prefix
1392+ key <- citeKey
1393+ loc <- locator
1394+ return $ Citation{ citationId = key
1395+ , citationPrefix = pref
1396+ , citationLocator = loc
1397+ , citationMode = if suppress_auth
1398+ then SuppressAuthor
1399+ else NormalCitation
1400+ , citationNoteNum = 0
1401+ , citationHash = 0
1402+ }