git.iko.soy/typeable/pandoc
on master help sign in
RST reader: more accurate parsing of references.
b94f1e2John MacFarlane
src/Text/Pandoc/Readers/RST.hs+24−36
@@ -1030,7 +1030,7 @@ noteBlock' marker = try $ do
1030citationMarker :: Monad m => RSTParser m [Char]
1030citationMarker :: Monad m => RSTParser m [Char]
1031citationMarker = do
1031citationMarker = do
1032 char '['
1032 char '['
1033− res <- simpleReferenceName'
1033+ res <- simpleReferenceName
1034 char ']'
1034 char ']'
1035 return res
1035 return res
1036
1036
@@ -1039,7 +1039,7 @@ noteMarker = do
1039 char '['
1039 char '['
1040 res <- many1 digit
1040 res <- many1 digit
1041 <|>
1041 <|>
1042− try (char '#' >> liftM ('#':) simpleReferenceName')
1042+ try (char '#' >> liftM ('#':) simpleReferenceName)
1043 <|> count 1 (oneOf "#*")
1043 <|> count 1 (oneOf "#*")
1044 char ']'
1044 char ']'
1045 return res
1045 return res
@@ -1048,34 +1048,24 @@ noteMarker = do
1048-- reference key
1048-- reference key
1049--
1049--
1050
1050
1051−quotedReferenceName :: PandocMonad m => RSTParser m Inlines
1051+quotedReferenceName :: PandocMonad m => RSTParser m String
1052quotedReferenceName = try $ do
1052quotedReferenceName = try $ do
1053 char '`' >> notFollowedBy (char '`') -- `` means inline code!
1053 char '`' >> notFollowedBy (char '`') -- `` means inline code!
1054− trimInlines . mconcat <$> many1Till inline (char '`')
1054+ manyTill anyChar (char '`')
1055−
1056−unquotedReferenceName :: PandocMonad m => RSTParser m Inlines
1057−unquotedReferenceName = try $ do -- `` means inline code!
1058− trimInlines . mconcat <$> many1Till inline (lookAhead $ char ':')
1059
1055
1060-- Simple reference names are single words consisting of alphanumerics
1056-- Simple reference names are single words consisting of alphanumerics
1061-- plus isolated (no two adjacent) internal hyphens, underscores,
1057-- plus isolated (no two adjacent) internal hyphens, underscores,
1062-- periods, colons and plus signs; no whitespace or other characters
1058-- periods, colons and plus signs; no whitespace or other characters
1063-- are allowed.
1059-- are allowed.
1064−simpleReferenceName' :: Monad m => ParserT [Char] st m String
1060+simpleReferenceName :: Monad m => ParserT [Char] st m String
1065−simpleReferenceName' = do
1061+simpleReferenceName = do
1066 x <- alphaNum
1062 x <- alphaNum
1067 xs <- many $ alphaNum
1063 xs <- many $ alphaNum
1068− <|>
1069− try (oneOf "-_:+." <* lookAhead alphaNum)
1064+ <|> try (oneOf "-_:+." <* lookAhead alphaNum)
1070 return (x:xs)
1065 return (x:xs)
1071
1066
1072−simpleReferenceName :: Monad m => ParserT [Char] st m Inlines
1073−simpleReferenceName = B.str <$> simpleReferenceName'
1074−
1075−referenceName :: PandocMonad m => RSTParser m Inlines
1067+referenceName :: PandocMonad m => RSTParser m String
1076−referenceName = quotedReferenceName <|>
1068+referenceName = quotedReferenceName <|> simpleReferenceName
1077− try (simpleReferenceName <* lookAhead (char ':')) <|>
1078− unquotedReferenceName
1079
1069
1080referenceKey :: PandocMonad m => RSTParser m [Char]
1070referenceKey :: PandocMonad m => RSTParser m [Char]
1081referenceKey = do
1071referenceKey = do
@@ -1123,16 +1113,17 @@ anonymousKey = try $ do
1123 updateState $ \s -> s { stateKeys = M.insert key ((src,""), nullAttr) $
1113 updateState $ \s -> s { stateKeys = M.insert key ((src,""), nullAttr) $
1124 stateKeys s }
1114 stateKeys s }
1125
1115
1126−stripTicks :: String -> String
1127−stripTicks = reverse . stripTick . reverse . stripTick
1128− where stripTick ('`':xs) = xs
1129− stripTick xs = xs
1130−
1131referenceNames :: PandocMonad m => RSTParser m [String]
1116referenceNames :: PandocMonad m => RSTParser m [String]
1132referenceNames = do
1117referenceNames = do
1133 let rn = try $ do
1118 let rn = try $ do
1134 string ".. _"
1119 string ".. _"
1135− (_, ref) <- withRaw referenceName
1120+ ref <- quotedReferenceName
1121+ <|> many ( noneOf ":\n"
1122+ <|> try (char '\n' <*
1123+ string " " <*
1124+ notFollowedBy blankline)
1125+ <|> try (char ':' <* lookAhead alphaNum)
1126+ )
1136 char ':'
1127 char ':'
1137 return ref
1128 return ref
1138 first <- rn
1129 first <- rn
@@ -1147,16 +1138,15 @@ regularKey = try $ do
1147 refs <- referenceNames
1138 refs <- referenceNames
1148 src <- targetURI
1139 src <- targetURI
1149 guard $ not (null src)
1140 guard $ not (null src)
1150− let keys = map (toKey . stripTicks) refs
1141+ let keys = map toKey refs
1151 forM_ keys $ \key ->
1142 forM_ keys $ \key ->
1152 updateState $ \s -> s { stateKeys = M.insert key ((src,""), nullAttr) $
1143 updateState $ \s -> s { stateKeys = M.insert key ((src,""), nullAttr) $
1153 stateKeys s }
1144 stateKeys s }
1154
1145
1155anchorDef :: PandocMonad m => RSTParser m [Char]
1146anchorDef :: PandocMonad m => RSTParser m [Char]
1156anchorDef = try $ do
1147anchorDef = try $ do
1157− (refs, raw) <- withRaw (try (referenceNames <* blanklines))
1148+ (refs, raw) <- withRaw $ try (referenceNames <* blanklines)
1158− let keys = map stripTicks refs
1159− forM_ keys $ \rawkey ->
1149+ forM_ refs $ \rawkey ->
1160 updateState $ \s -> s { stateKeys =
1150 updateState $ \s -> s { stateKeys =
1161 M.insert (toKey rawkey) (('#':rawkey,""), nullAttr) $ stateKeys s }
1151 M.insert (toKey rawkey) (('#':rawkey,""), nullAttr) $ stateKeys s }
1162 -- keep this for 2nd round of parsing, where we'll add the divs (anchor)
1152 -- keep this for 2nd round of parsing, where we'll add the divs (anchor)
@@ -1479,22 +1469,20 @@ explicitLink = try $ do
1479 _ -> return ((src, ""), nullAttr)
1469 _ -> return ((src, ""), nullAttr)
1480 return $ B.linkWith attr (escapeURI src') tit label''
1470 return $ B.linkWith attr (escapeURI src') tit label''
1481
1471
1482−citationName :: PandocMonad m => RSTParser m Inlines
1472+citationName :: PandocMonad m => RSTParser m String
1483citationName = do
1473citationName = do
1484 raw <- citationMarker
1474 raw <- citationMarker
1485− return $ B.str $ "[" ++ raw ++ "]"
1475+ return $ "[" ++ raw ++ "]"
1486
1476
1487referenceLink :: PandocMonad m => RSTParser m Inlines
1477referenceLink :: PandocMonad m => RSTParser m Inlines
1488referenceLink = try $ do
1478referenceLink = try $ do
1489− (label',ref) <- withRaw (quotedReferenceName
1490− <|> simpleReferenceName
1491− <|> citationName) <*
1479+ ref <- (referenceName <|> citationName) <* char '_'
1492− char '_'
1480+ let label' = B.text ref
1493 let isAnonKey (Key ('_':_)) = True
1481 let isAnonKey (Key ('_':_)) = True
1494 isAnonKey _ = False
1482 isAnonKey _ = False
1495 state <- getState
1483 state <- getState
1496 let keyTable = stateKeys state
1484 let keyTable = stateKeys state
1497− key <- option (toKey $ stripTicks ref) $
1485+ key <- option (toKey ref) $
1498 do char '_'
1486 do char '_'
1499 let anonKeys = sort $ filter isAnonKey $ M.keys keyTable
1487 let anonKeys = sort $ filter isAnonKey $ M.keys keyTable
1500 case anonKeys of
1488 case anonKeys of
test/command/4156.mdnew file+10
@@ -0,0 +1,10 @@
1+```
2+% pandoc -f rst
3+.. _`SOMEID`:
4+
5+foo
6+^D
7+<div id="SOMEID">
8+<p>foo</p>
9+</div>
10+```
test/command/rst-links.mdnew file+18
@@ -0,0 +1,18 @@
1+```
2+% pandoc -f rst
3+`*ab*`_
4+
5+.. _`*ab*`: foo
6+^D
7+<p><a href="foo">*ab*</a></p>
8+```
9+
10+```
11+% pandoc -f rst
12+`A B
13+c`_
14+
15+.. _A B C: foo
16+^D
17+<p><a href="foo">A B c</a></p>
18+```