@@ -115,7 +115,7 @@ import Text.ParserCombinators.Parsec
115115import Text.PrettyPrint.HughesPJ ( Doc, fsep, ($$), (<>), empty, isEmpty, text, nest )
116116import qualified Text.PrettyPrint.HughesPJ as PP
117117import Text.Pandoc.CharacterReferences ( characterReference )
118−import Data.Char ( toLower, toUpper, ord, isLower, isUpper, isAlpha,
118+import Data.Char ( toLower, toUpper, ord, isLower, isUpper, isAlpha, isAscii,
119119 isPunctuation )
120120import Data.List ( find, isPrefixOf, intercalate )
121121import Network.URI ( parseURI, URI (..), isAllowedInURI, escapeURIString )
@@ -487,25 +487,30 @@ domain = do
487487 dom <- many1 $ try (char '.' >> many1 domainChar )
488488 return $ intercalate "." (first:dom)
489489
490−-- | Parses an email address; returns string.
491−emailAddress :: GenParser Char st [Char]
490+-- | Parses an email address; returns original and corresponding
491+-- escaped mailto: URI.
492+emailAddress :: GenParser Char st (String, String)
492493emailAddress = try $ do
493494 firstLetter <- alphaNum
494495 restAddr <- many emailChar
495496 let addr = firstLetter:restAddr
496497 char '@'
497498 dom <- domain
498− return $ addr ++ '@':dom
499+ let full = addr ++ '@':dom
500+ return (full, escapeURI $ "mailto:" ++ full)
499501
500−-- | Parses a URI.
501−uri :: GenParser Char st String
502+-- | Parses a URI. Returns pair of original and URI-escaped version.
503+uri :: GenParser Char st (String, String)
502504uri = try $ do
503− str <- many1 $ satisfy isAllowedInURI
504− case parseURI str of
505− Just uri' -> if uriScheme uri' `elem` [ "http:", "https:", "ftp:",
506− "file:", "mailto:",
507− "news:", "telnet:" ]
508− then return $ show uri'
505+ let protocols = [ "http:", "https:", "ftp:", "file:", "mailto:",
506+ "news:", "telnet:" ]
507+ lookAhead $ oneOfStrings protocols
508+ -- scan non-ascii characters and ascii characters allowed in a URI
509+ str <- many1 $ satisfy (\c -> not (isAscii c) || isAllowedInURI c)
510+ -- now see if they amount to an absolute URI
511+ case parseURI (escapeURI str) of
512+ Just uri' -> if uriScheme uri' `elem` protocols
513+ then return (str, show uri')
509514 else fail "not a URI"
510515 Nothing -> fail "not a URI"
511516