git.iko.soy/typeable/pandoc
on master help sign in
Markdown reader: properly escape URIs.
07ae5bcfiddlosopher
src/Text/Pandoc/Readers/Markdown.hs+10−2
@@ -45,6 +45,7 @@ import Text.Pandoc.Readers.HTML ( rawHtmlBlock, anyHtmlBlockTag,
45import Text.Pandoc.CharacterReferences ( decodeCharacterReferences )
45import Text.Pandoc.CharacterReferences ( decodeCharacterReferences )
46import Text.ParserCombinators.Parsec
46import Text.ParserCombinators.Parsec
47import Control.Monad (when, liftM, unless)
47import Control.Monad (when, liftM, unless)
48+import Network.URI ( unEscapeString, escapeURIString, isUnescapedInURI )
48
49
49-- | Read markdown from an input string and return a Pandoc document.
50-- | Read markdown from an input string and return a Pandoc document.
50readMarkdown :: ParserState -- ^ Parser state, including options for parser
51readMarkdown :: ParserState -- ^ Parser state, including options for parser
@@ -73,6 +74,13 @@ specialChars = "\\[]*_~`<>$!^-.&'\"\8216\8217\8220\8221;"
73-- auxiliary functions
74-- auxiliary functions
74--
75--
75
76
77+-- | Escape a URI in a markdown-appropriate way. First,
78+-- we unescape the string, since we don't want to screw things
79+-- up if they've entered a properly encoded URI. Then, we
80+-- escape the result.
81+escapeURI :: String -> String
82+escapeURI = escapeURIString isUnescapedInURI . unEscapeString
83+
76indentSpaces :: GenParser Char ParserState [Char]
84indentSpaces :: GenParser Char ParserState [Char]
77indentSpaces = try $ do
85indentSpaces = try $ do
78 state <- getState
86 state <- getState
@@ -194,7 +202,7 @@ referenceKey = try $ do
194 tit <- option "" referenceTitle
202 tit <- option "" referenceTitle
195 blanklines
203 blanklines
196 endPos <- getPosition
204 endPos <- getPosition
197− let newkey = (lab, (intercalate "+" $ words $ removeTrailingSpace src, tit))
205+ let newkey = (lab, (escapeURI $ removeTrailingSpace src, tit))
198 st <- getState
206 st <- getState
199 let oldkeys = stateKeys st
207 let oldkeys = stateKeys st
200 updateState $ \s -> s { stateKeys = newkey : oldkeys }
208 updateState $ \s -> s { stateKeys = newkey : oldkeys }
@@ -1173,7 +1181,7 @@ source' = do
1173 tit <- option "" linkTitle
1181 tit <- option "" linkTitle
1174 skipSpaces
1182 skipSpaces
1175 eof
1183 eof
1176− return (intercalate "+" $ words $ removeTrailingSpace src, tit)
1184+ return (escapeURI $ removeTrailingSpace src, tit)
1177
1185
1178linkTitle :: GenParser Char st String
1186linkTitle :: GenParser Char st String
1179linkTitle = try $ do
1187linkTitle = try $ do
tests/markdown-reader-more.native+2−2
@@ -6,8 +6,8 @@ Pandoc (Meta [] [] [])
6, Para [TeX "\\placeformula",Space,TeX "\\startformula\n L_{1} = L_{2}\n \\stopformula"]
6, Para [TeX "\\placeformula",Space,TeX "\\startformula\n L_{1} = L_{2}\n \\stopformula"]
7, Para [TeX "\\start[a2]\n\\start[a2]\n\\stop[a2]\n\\stop[a2]"]
7, Para [TeX "\\start[a2]\n\\start[a2]\n\\stop[a2]\n\\stop[a2]"]
8, Header 2 [Str "URLs",Space,Str "with",Space,Str "spaces"]
8, Header 2 [Str "URLs",Space,Str "with",Space,Str "spaces"]
9−, Para [Link [Str "foo"] ("/bar+and+baz",""),Space,Link [Str "foo"] ("/bar+and+baz",""),Space,Link [Str "foo"] ("/bar+and+baz",""),Space,Link [Str "foo"] ("bar+baz","title")]
9+, Para [Link [Str "foo"] ("/bar%20and%20baz",""),Space,Link [Str "foo"] ("/bar%20and%20baz",""),Space,Link [Str "foo"] ("/bar%20%20and%20%20baz",""),Space,Link [Str "foo"] ("bar%20baz","title")]
10−, Para [Link [Str "baz"] ("/foo+foo",""),Space,Link [Str "bam"] ("/foo+fee",""),Space,Link [Str "bork"] ("/foo/zee+zob","title")]
10+, Para [Link [Str "baz"] ("/foo%20foo",""),Space,Link [Str "bam"] ("/foo%20fee",""),Space,Link [Str "bork"] ("/foo/zee%20zob","title")]
11, Header 2 [Str "Horizontal",Space,Str "rules",Space,Str "with",Space,Str "spaces",Space,Str "at",Space,Str "end"]
11, Header 2 [Str "Horizontal",Space,Str "rules",Space,Str "with",Space,Str "spaces",Space,Str "at",Space,Str "end"]
12, HorizontalRule
12, HorizontalRule
13, HorizontalRule
13, HorizontalRule