git.iko.soy/typeable/pandoc
on master help sign in
Changes in entity handling:

+ Entities are parsed (and unicode characters returned) in both Markdown and HTML readers. + Parsers characterEntity, namedEntity, decimalEntity, hexEntity added to Entities.hs; these parse a string and return a unicode character. + Changed 'entity' parser in HTML reader to use the 'characterEntity' parser from Entities.hs. + Added new 'entity' parser to Markdown reader, and added '&' as a special character. Adjusted test suite accordingly since now we get 'Str "AT",Str "&",Str "T"' instead of 'Str "AT&T".. + stringToSGML moved to Entities.hs. escapeSGML removed as redundant, given encodeEntities. + stringToSGML, encodeEntities, and specialCharToEntity are given a boolean parameter that causes only numerical entities to be used. This is used in the docbook writer. The HTML writer uses named entities where possible, but not all docbook-consumers know about the named entities without special instructions, so it seems safer to use numerical entities there. + decodeEntities is rewritten in a way that avoids Text.Regex, using the new parsers. + charToEntity and charToNumericalEntity added to Entities.hs. + Moved specialCharToEntity from Shared.hs to Entities.hs. + Removed unneeded 'decodeEntities' from 'str' parser in HTML and Markdown readers. + Removed sgmlHexEntity, sgmlDecimalEntity, sgmlNamedEntity, and sgmlCharacterEntity from Shared.hs. + Modified Docbook writer so that it doesn't rely on Text.Regex for detecting "mailto" links. git-svn-id: https://pandoc.googlecode.com/svn/trunk@515 788f1e2b-df1e-0410-8736-df70ead52e1b

commitd06417125dd4d8cb177abd2d472c0c1cad4c49be authorfiddlosopher <fiddlosopher@788f1e2b-df1e-0410-8736-df70ead52e1b> dateSat 27 Jan 2007, 03:04 (20 years ago) parentf2de088
10 files changed+169−177
src/Text/Pandoc/Entities.hs+92−45 src/Text/Pandoc/Readers/HTML.hs+5−10 src/Text/Pandoc/Readers/Markdown.hs+9−4 src/Text/Pandoc/Shared.hs+3−55 src/Text/Pandoc/Writers/Docbook.hs+14−16 src/Text/Pandoc/Writers/HTML.hs+10−10 src/Text/Pandoc/Writers/Markdown.hs−1 tests/testsuite.native+3−3 tests/writer.docbook+30−30 tests/writer.native+3−3
src/Text/Pandoc/Entities.hs+92−45
@@ -29,62 +29,109 @@ Functions for encoding unicode characters as entity references,
2929and vice versa.
3030-}
3131module Text.Pandoc.Entities (
32− entityToChar,
3332 charToEntity,
34− decodeEntities,
33+ charToNumericalEntity,
34+ specialCharToEntity,
3535 encodeEntities,
36+ decodeEntities,
37+ stringToSGML,
3638 characterEntity
3739 ) where
3840import Data.Char ( chr, ord )
39−import Text.Regex ( mkRegex, matchRegexAll, Regex )
40−import Maybe ( fromMaybe )
41+import Text.ParserCombinators.Parsec
42+import Data.Maybe ( fromMaybe )
4143
42−-- | Regular expression for numerical coded entity.
43−numericalEntity :: Text.Regex.Regex
44−numericalEntity = mkRegex "&#([0-9]+|[xX][0-9A-Fa-f]+);"
44+-- | Returns a string containing an entity reference for the character.
45+charToEntity :: Char -> String
46+charToEntity char =
47+ let matches = filter (\(entity, character) -> (character == char))
48+ entityTable in
49+ if (length matches) == 0
50+ then charToNumericalEntity char
51+ else fst (head matches)
4552
46−-- | Regular expression for character entity.
47−characterEntity :: Text.Regex.Regex
48−characterEntity = mkRegex "&#[0-9]+;|&#[xX][0-9A-Fa-f]+;|&[A-Za-z0-9]+;"
53+-- | Returns a string containing a numerical entity reference for the char.
54+charToNumericalEntity :: Char -> String
55+charToNumericalEntity ch = "&#" ++ show (ord ch) ++ ";"
4956
50−-- | Return a string with all entity references decoded to unicode characters
51−-- where possible.
52−decodeEntities :: String -> String
53−decodeEntities str =
54− case (matchRegexAll characterEntity str) of
55− Nothing -> str
56− Just (before, match, rest, _) -> before ++ replacement ++
57− (decodeEntities rest)
58− where replacement = case (entityToChar match) of
59− Just ch -> [ch]
60− Nothing -> match
57+-- | Escape special character to SGML entity.
58+specialCharToEntity :: Bool -- ^ Use numerical entities only.
59+ -> Char -- ^ Character to convert.
60+ -> [Char]
61+specialCharToEntity numericalEntities c =
62+ if (c `elem` "&<>\"") || (ord c > 127)
63+ then if numericalEntities
64+ then charToNumericalEntity c
65+ else charToEntity c
66+ else [c]
6167
62−-- | Returns a string with characters replaced with entity references where
63−-- possible.
64−encodeEntities :: String -> String
65−encodeEntities [] = []
66−encodeEntities (c:cs) = if ord c < 128
67− then c:(encodeEntities cs)
68− else (charToEntity c) ++ (encodeEntities cs)
68+-- | Parse SGML character entity.
69+characterEntity :: GenParser Char st Char
70+characterEntity = namedEntity <|> hexEntity <|> decimalEntity <?> "SGML entity"
6971
70−-- | If the string is a valid entity reference, returns @Just@ the character,
71−-- otherwise @Nothing@.
72−entityToChar :: String -> Maybe Char
73−entityToChar entity =
74− case (lookup entity entityTable) of
75− Just ch -> Just ch
76− Nothing -> case (matchRegexAll numericalEntity entity) of
77− Just (_, _, _, [sub]) -> Just (chr (read ('0':sub)))
78− Nothing -> Nothing
72+-- | Parse SGML character entity.
73+namedEntity :: GenParser Char st Char
74+namedEntity = try $ do
75+ st <- char '&'
76+ body <- many1 alphaNum
77+ end <- char ';'
78+ let entity = "&" ++ body ++ ";"
79+ return $ case (lookup entity entityTable) of
80+ Just ch -> ch
81+ Nothing -> '?'
82+
83+-- | Parse SGML hexadecimal entity.
84+hexEntity :: GenParser Char st Char
85+hexEntity = try $ do
86+ st <- string "&#"
87+ hex <- oneOf "Xx"
88+ body <- many1 (oneOf "0123456789ABCDEFabcdef")
89+ end <- char ';'
90+ return $ chr $ read ('0':'x':body)
7991
80−-- | Returns a string containing an entity reference for the character.
81−charToEntity :: Char -> String
82−charToEntity char =
83− let matches = filter (\(entity, character) -> (character == char))
84− entityTable in
85− if (length matches) == 0
86− then "&#" ++ show (ord char) ++ ";"
87− else fst (head matches)
92+-- | Parse SGML decimal entity.
93+decimalEntity :: GenParser Char st Char
94+decimalEntity = try $ do
95+ st <- string "&#"
96+ body <- many1 digit
97+ end <- char ';'
98+ return $ chr $ read body
99+
100+-- | Escape string as needed for SGML. Entity references are not preserved.
101+encodeEntities :: Bool -- ^ Use only numerical entities.
102+ -> String -- ^ String to convert.
103+ -> String
104+encodeEntities numericalEntities =
105+ concatMap (specialCharToEntity numericalEntities)
106+
107+-- | Escape string as needed for SGML, using only numerical entities.
108+-- Entity references are not preserved.
109+encodeEntitiesNumerical :: String -> String
110+encodeEntitiesNumerical =
111+ concatMap (\c -> "&#" ++ show (ord c) ++ ";")
112+
113+-- | Convert entities in a string to characters.
114+decodeEntities :: String -> String
115+decodeEntities str =
116+ case parse (many (characterEntity <|> anyChar)) str str of
117+ Left err -> error $ "\nError: " ++ show err
118+ Right result -> result
119+
120+-- | Escape string for SGML, preserving entity references.
121+stringToSGML :: Bool -- ^ Use only numerical entities.
122+ -> String -- ^ String to convert.
123+ -> String
124+stringToSGML numericalEntities str =
125+ let nonentity = do
126+ notFollowedBy characterEntity
127+ c <- anyChar
128+ return $ specialCharToEntity numericalEntities c
129+ entity = do
130+ ent <- manyTill anyChar (char ';')
131+ return (ent ++ ";") in
132+ case parse (many (nonentity <|> entity)) str str of
133+ Left err -> error $ "\nError: " ++ show err
134+ Right result -> concat result
88135
89136entityTable :: [(String, Char)]
90137entityTable = [
src/Text/Pandoc/Readers/HTML.hs+5−10
@@ -44,7 +44,7 @@ import Text.ParserCombinators.Parsec
4444import Text.ParserCombinators.Pandoc
4545import Text.Pandoc.Definition
4646import Text.Pandoc.Shared
47−import Text.Pandoc.Entities ( decodeEntities, entityToChar )
47+import Text.Pandoc.Entities ( characterEntity, decodeEntities )
4848import Maybe ( fromMaybe )
4949import Data.List ( intersect, takeWhile, dropWhile )
5050import Data.Char ( toUpper, toLower, isAlphaNum )
@@ -391,14 +391,9 @@ text = choice [ entity, strong, emph, code, str, linebreak, whitespace ] <?> "t
391391special = choice [ link, image, rawHtmlInline ] <?>
392392 "link, inline html, or image"
393393
394−entity = try (do
395− char '&'
396− body <- choice [(many1 letter), (try (do
397− char '#'
398− num <- many1 digit
399− return ("#" ++ num)))]
400− char ';'
401− return (Str [fromMaybe '?' (entityToChar ("&" ++ body ++ ";"))]))
394+entity = do
395+ ent <- characterEntity
396+ return $ Str [ent]
402397
403398code = try (do
404399 htmlTag "code"
@@ -439,7 +434,7 @@ linebreak = do
439434
440435str = do
441436 result <- many1 (noneOf "<& \t\n")
442− return (Str (decodeEntities result))
437+ return (Str result)
443438
444439--
445440-- links and images
src/Text/Pandoc/Readers/Markdown.hs+9−4
@@ -42,7 +42,7 @@ import Text.Pandoc.Readers.HTML ( rawHtmlBlock,
4242 anyHtmlTag, anyHtmlEndTag,
4343 htmlEndTag, extractTagType,
4444 htmlBlockElement )
45−import Text.Pandoc.Entities ( decodeEntities )
45+import Text.Pandoc.Entities ( characterEntity )
4646import Text.ParserCombinators.Parsec
4747
4848-- | Read markdown from an input string and return a Pandoc document.
@@ -88,12 +88,13 @@ blockQuoteChar = '>'
8888hyphenChar = '-'
8989ellipsesChar = '.'
9090listColSepChar = '|'
91+entityStart = '&'
9192
9293-- treat these as potentially non-text when parsing inline:
9394specialChars = [escapeChar, labelStart, labelEnd, emphStart, emphEnd,
9495 emphStartAlt, emphEndAlt, codeStart, codeEnd, autoLinkEnd,
9596 autoLinkStart, mathStart, mathEnd, imageStart, noteStart,
96− hyphenChar, ellipsesChar] ++ quoteChars
97+ hyphenChar, ellipsesChar, entityStart] ++ quoteChars
9798
9899--
99100-- auxiliary functions
@@ -674,7 +675,7 @@ text = choice [ escapedChar, math, strong, emph, smartPunctuation,
674675 code, ltSign, symbol,
675676 str, linebreak, tabchar, whitespace, endline ] <?> "text"
676677
677−inline = choice [ rawLaTeXInline', escapedChar, special, text ] <?> "inline"
678+inline = choice [ rawLaTeXInline', escapedChar, entity, special, text ] <?> "inline"
678679
679680special = choice [ noteRef, inlineNote, link, referenceLink, rawHtmlInline',
680681 autoLink, image ] <?> "link, inline html, note, or image"
@@ -827,9 +828,13 @@ linebreak = try (do
827828
828829nonEndline = noneOf endLineChars
829830
831+entity = do
832+ ent <- characterEntity
833+ return $ Str [ent]
834+
830835str = do
831836 result <- many1 ((noneOf (specialChars ++ spaceChars ++ endLineChars)))
832− return (Str (decodeEntities result))
837+ return (Str result)
833838
834839-- an endline character that can be treated as a space, not a structural break
835840endline = try (do
src/Text/Pandoc/Shared.hs+3−55
@@ -65,8 +65,6 @@ module Text.Pandoc.Shared (
6565 replaceReferenceLinks,
6666 replaceRefLinksBlockList,
6767 -- * SGML
68− escapeSGML,
69− stringToSGML,
7068 inTags,
7169 selfClosingTag,
7270 inTagsSimple,
@@ -74,7 +72,7 @@ module Text.Pandoc.Shared (
7472 ) where
7573import Text.Pandoc.Definition
7674import Text.ParserCombinators.Parsec as Parsec
77−import Text.Pandoc.Entities ( decodeEntities, charToEntity )
75+import Text.Pandoc.Entities ( decodeEntities, encodeEntities, stringToSGML )
7876import Text.PrettyPrint.HughesPJ as PP ( text, char, (<>),
7977 ($$), nest, Doc, isEmpty )
8078import Data.Char ( toLower, ord )
@@ -523,61 +521,11 @@ replaceRefLinksInline keytable (Quoted t lst) =
523521 Quoted t (map (replaceRefLinksInline keytable) lst)
524522replaceRefLinksInline keytable other = other
525523
526−-- | Parse SGML character entity.
527−sgmlCharacterEntity :: GenParser Char st [Char]
528−sgmlCharacterEntity = sgmlNamedEntity <|> sgmlDecimalEntity <|>
529− sgmlHexEntity <?> "SGML entity"
530−
531−-- | Parse SGML character entity.
532−sgmlNamedEntity :: GenParser Char st [Char]
533−sgmlNamedEntity = try $ do
534− st <- Parsec.char '&'
535− body <- many1 alphaNum
536− end <- Parsec.char ';'
537− return $ (st:body) ++ [end]
538−
539−-- | Parse SGML decimal entity.
540−sgmlDecimalEntity :: GenParser Char st [Char]
541−sgmlDecimalEntity = try $ do
542− st <- string "&#"
543− body <- many1 (oneOf "0123456789")
544− end <- Parsec.char ';'
545− return $ st ++ body ++ [end]
546−
547−-- | Parse SGML hexadecimal entity.
548−sgmlHexEntity :: GenParser Char st [Char]
549−sgmlHexEntity = try $ do
550− st <- string "&#"
551− hex <- oneOf "Xx"
552− body <- many1 (oneOf "0123456789ABCDEFabcdef")
553− end <- Parsec.char ';'
554− return $ st ++ (hex:body) ++ [end]
555−
556−-- | Escape special character to SGML entity.
557−specialCharToEntity :: Char -> [Char]
558−specialCharToEntity c = if (c `elem` "&<>\"") || (ord c > 127)
559− then charToEntity c
560− else [c]
561−
562−-- | Escape string, preserving character entities.
563−stringToSGML :: String -> String
564−stringToSGML str =
565− let segment = sgmlCharacterEntity <|>
566− (do{c <- anyChar;
567− return $ specialCharToEntity c})
568− sgmlString = (do{segs <- many segment; return $ concat segs}) in
569− case parse sgmlString str str of
570− Left err -> error $ "\nError:\n" ++ show err
571− Right result -> result
572−
573−-- | Escape string as needed for SGML. Entity references are not preserved.
574−escapeSGML :: String -> String
575−escapeSGML = concatMap specialCharToEntity
576−
577524-- | Return a text object with a string of formatted SGML attributes.
578525attributeList :: [(String, String)] -> Doc
579526attributeList = text . concatMap
580− (\(a, b) -> " " ++ stringToSGML a ++ "=\"" ++ stringToSGML b ++ "\"")
527+ (\(a, b) -> " " ++ stringToSGML True a ++ "=\"" ++
528+ stringToSGML True b ++ "\"")
581529
582530-- | Put the supplied contents between start and end tags of tagType,
583531-- with specified attributes and (if specified) indentation.
src/Text/Pandoc/Writers/Docbook.hs+14−16
@@ -32,10 +32,9 @@ module Text.Pandoc.Writers.Docbook (
3232 ) where
3333import Text.Pandoc.Definition
3434import Text.Pandoc.Shared
35−import Text.Pandoc.Entities ( encodeEntities )
36−import Text.Regex ( mkRegex, matchRegex )
35+import Text.Pandoc.Entities ( encodeEntities, stringToSGML )
3736import Data.Char ( toLower, ord )
38−import Data.List ( isPrefixOf, partition )
37+import Data.List ( isPrefixOf, partition, drop )
3938import Text.PrettyPrint.HughesPJ hiding ( Str )
4039
4140-- | Data structure for defining hierarchical Pandoc documents
@@ -65,8 +64,8 @@ authorToDocbook name = inTagsIndented "author" $
6564 then -- last name first
6665 let (lastname, rest) = break (==',') name
6766 firstname = removeLeadingSpace rest in
68− inTagsSimple "firstname" (text $ stringToSGML firstname) <>
69− inTagsSimple "surname" (text $ stringToSGML lastname)
67+ inTagsSimple "firstname" (text $ stringToSGML True firstname) <>
68+ inTagsSimple "surname" (text $ stringToSGML True lastname)
7069 else -- last name last
7170 let namewords = words name
7271 lengthname = length namewords
@@ -74,8 +73,8 @@ authorToDocbook name = inTagsIndented "author" $
7473 0 -> ("","")
7574 1 -> ("", name)
7675 n -> (joinWithSep " " (take (n-1) namewords), last namewords) in
77− inTagsSimple "firstname" (text $ stringToSGML firstname) $$
78− inTagsSimple "surname" (text $ stringToSGML lastname)
76+ inTagsSimple "firstname" (text $ stringToSGML True firstname) $$
77+ inTagsSimple "surname" (text $ stringToSGML True lastname)
7978
8079-- | Convert Pandoc document to string in Docbook format.
8180writeDocbook :: WriterOptions -> Pandoc -> String
@@ -87,7 +86,7 @@ writeDocbook opts (Pandoc (Meta title authors date) blocks) =
8786 then inTagsIndented "articleinfo" $
8887 (inTagsSimple "title" (wrap opts title)) $$
8988 (vcat (map authorToDocbook authors)) $$
90− (inTagsSimple "date" (text $ stringToSGML date))
89+ (inTagsSimple "date" (text $ stringToSGML True date))
9190 else empty
9291 blocks' = replaceReferenceLinks blocks
9392 (noteBlocks, blocks'') = partition isNoteBlock blocks'
@@ -142,7 +141,7 @@ blockToDocbook opts (Para lst) =
142141blockToDocbook opts (BlockQuote blocks) =
143142 inTagsIndented "blockquote" (blocksToDocbook opts blocks)
144143blockToDocbook opts (CodeBlock str) =
145− text "<screen>\n" <> text (escapeSGML str) <> text "\n</screen>"
144+ text "<screen>\n" <> text (encodeEntities True str) <> text "\n</screen>"
146145blockToDocbook opts (BulletList lst) =
147146 inTagsIndented "itemizedlist" $ listItemsToDocbook opts lst
148147blockToDocbook opts (OrderedList lst) =
@@ -199,7 +198,7 @@ inlinesToDocbook opts lst = hcat (map (inlineToDocbook opts) lst)
199198
200199-- | Convert an inline element to Docbook.
201200inlineToDocbook :: WriterOptions -> Inline -> Doc
202−inlineToDocbook opts (Str str) = text $ stringToSGML str
201+inlineToDocbook opts (Str str) = text $ stringToSGML True str
203202inlineToDocbook opts (Emph lst) =
204203 inTagsSimple "emphasis" (inlinesToDocbook opts lst)
205204inlineToDocbook opts (Strong lst) =
@@ -212,24 +211,23 @@ inlineToDocbook opts Ellipses = text "&#8230;"
212211inlineToDocbook opts EmDash = text "&#8212;"
213212inlineToDocbook opts EnDash = text "&#8211;"
214213inlineToDocbook opts (Code str) =
215− inTagsSimple "literal" $ text (escapeSGML str)
214+ inTagsSimple "literal" $ text (encodeEntities True str)
216215inlineToDocbook opts (TeX str) = inlineToDocbook opts (Code str)
217216inlineToDocbook opts (HtmlInline str) = empty
218217inlineToDocbook opts LineBreak =
219218 text $ "<literallayout></literallayout>"
220219inlineToDocbook opts Space = char ' '
221220inlineToDocbook opts (Link txt (Src src tit)) =
222− case (matchRegex (mkRegex "mailto:(.*)") src) of
223− Just [addr] -> inTagsSimple "email" $ text (escapeSGML addr)
224− Nothing -> inTags False "ulink" [("url", src)] $
225− inlinesToDocbook opts txt
221+ if isPrefixOf "mailto:" src
222+ then inTagsSimple "email" $ text (encodeEntities True $ drop 7 src)
223+ else inTags False "ulink" [("url", src)] $ inlinesToDocbook opts txt
226224inlineToDocbook opts (Link text (Ref ref)) = empty -- shouldn't occur
227225inlineToDocbook opts (Image alt (Src src tit)) =
228226 let titleDoc = if null tit
229227 then empty
230228 else inTagsIndented "objectinfo" $
231229 inTagsIndented "title"
232− (text $ stringToSGML tit) in
230+ (text $ stringToSGML True tit) in
233231 inTagsIndented "inlinemediaobject" $
234232 inTagsIndented "imageobject" $
235233 titleDoc $$ selfClosingTag "imagedata" [("fileref", src)]
src/Text/Pandoc/Writers/HTML.hs+10−10
@@ -32,7 +32,7 @@ module Text.Pandoc.Writers.HTML (
3232 ) where
3333import Text.Pandoc.Definition
3434import Text.Pandoc.Shared
35−import Text.Pandoc.Entities ( encodeEntities )
35+import Text.Pandoc.Entities ( encodeEntities, stringToSGML )
3636import Text.Regex ( mkRegex, matchRegex )
3737import Numeric ( showHex )
3838import Data.Char ( ord, toLower )
@@ -127,11 +127,11 @@ htmlHeader opts (Meta title authors date) =
127127 then empty
128128 else selfClosingTag "meta" [("name", "author"),
129129 ("content",
130− joinWithSep ", " (map stringToSGML authors))]
130+ joinWithSep ", " (map (stringToSGML False) authors))]
131131 datetext = if (date == "")
132132 then empty
133133 else selfClosingTag "meta" [("name", "date"),
134− ("content", stringToSGML date)] in
134+ ("content", stringToSGML False date)] in
135135 text (writerHeader opts) $$ authortext $$ datetext $$ titletext $$
136136 text "</head>\n<body>"
137137
@@ -168,7 +168,7 @@ blockToHtml opts (Note ref lst) =
168168 (text "&#8617;")
169169blockToHtml opts (Key _ _) = empty
170170blockToHtml opts (CodeBlock str) =
171− text "<pre><code>" <> text (escapeSGML str) <> text "\n</code></pre>"
171+ text "<pre><code>" <> text (encodeEntities False str) <> text "\n</code></pre>"
172172blockToHtml opts (RawHtml str) = text str
173173blockToHtml opts (BulletList lst) =
174174 let attribs = if (writerIncremental opts)
@@ -234,7 +234,7 @@ inlineToHtml opts (Emph lst) =
234234inlineToHtml opts (Strong lst) =
235235 inTagsSimple "strong" (inlineListToHtml opts lst)
236236inlineToHtml opts (Code str) =
237− inTagsSimple "code" $ text (escapeSGML str)
237+ inTagsSimple "code" $ text (encodeEntities False str)
238238inlineToHtml opts (Quoted SingleQuote lst) =
239239 text "&lsquo;" <> (inlineListToHtml opts lst) <> text "&rsquo;"
240240inlineToHtml opts (Quoted DoubleQuote lst) =
@@ -243,16 +243,16 @@ inlineToHtml opts EmDash = text "&mdash;"
243243inlineToHtml opts EnDash = text "&ndash;"
244244inlineToHtml opts Ellipses = text "&hellip;"
245245inlineToHtml opts Apostrophe = text "&rsquo;"
246−inlineToHtml opts (Str str) = text $ stringToSGML str
247−inlineToHtml opts (TeX str) = text $ escapeSGML str
246+inlineToHtml opts (Str str) = text $ stringToSGML False str
247+inlineToHtml opts (TeX str) = text $ encodeEntities False str
248248inlineToHtml opts (HtmlInline str) = text str
249249inlineToHtml opts (LineBreak) = selfClosingTag "br" []
250250inlineToHtml opts Space = space
251251inlineToHtml opts (Link txt (Src src tit)) =
252− let title = stringToSGML tit in
252+ let title = stringToSGML False tit in
253253 if (isPrefixOf "mailto:" src)
254254 then obfuscateLink opts txt src
255− else inTags False "a" ([("href", escapeSGML src)] ++
255+ else inTags False "a" ([("href", encodeEntities False src)] ++
256256 if null tit then [] else [("title", title)])
257257 (inlineListToHtml opts txt)
258258inlineToHtml opts (Link txt (Ref ref)) =
@@ -260,7 +260,7 @@ inlineToHtml opts (Link txt (Ref ref)) =
260260 (inlineListToHtml opts ref) <> char ']'
261261 -- this is what markdown does, for better or worse
262262inlineToHtml opts (Image alt (Src source tit)) =
263− let title = stringToSGML tit
263+ let title = stringToSGML False tit
264264 alternate = render $ inlineListToHtml opts alt in
265265 selfClosingTag "img" $ [("src", source)] ++
266266 (if null alternate then [] else [("alt", alternate)]) ++
src/Text/Pandoc/Writers/Markdown.hs−1
@@ -32,7 +32,6 @@ Markdown: <http://daringfireball.net/projects/markdown/>
3232module Text.Pandoc.Writers.Markdown (
3333 writeMarkdown
3434 ) where
35−import Text.Regex ( matchRegex, mkRegex )
3635import Text.Pandoc.Definition
3736import Text.Pandoc.Shared
3837import Data.List ( group, isPrefixOf, drop )
tests/testsuite.native+3−3
@@ -240,8 +240,8 @@ Pandoc (Meta [Str "Pandoc",Space,Str "Test",Space,Str "Suite"] ["John MacFarlane
240240 , [ Plain [Str "section:",Space,Str "\167"] ]
241241 , [ Plain [Str "set",Space,Str "membership:",Space,Str "\8712"] ]
242242 , [ Plain [Str "copyright:",Space,Str "\169"] ] ]
243−, Para [Str "AT&T",Space,Str "has",Space,Str "an",Space,Str "ampersand",Space,Str "in",Space,Str "their",Space,Str "name",Str "."]
244−, Para [Str "AT&T",Space,Str "is",Space,Str "another",Space,Str "way",Space,Str "to",Space,Str "write",Space,Str "it",Str "."]
243+, Para [Str "AT",Str "&",Str "T",Space,Str "has",Space,Str "an",Space,Str "ampersand",Space,Str "in",Space,Str "their",Space,Str "name",Str "."]
244+, Para [Str "AT",Str "&",Str "T",Space,Str "is",Space,Str "another",Space,Str "way",Space,Str "to",Space,Str "write",Space,Str "it",Str "."]
245245, Para [Str "This",Space,Str "&",Space,Str "that",Str "."]
246246, Para [Str "4",Space,Str "<",Space,Str "5",Str "."]
247247, Para [Str "6",Space,Str ">",Space,Str "5",Str "."]
@@ -294,7 +294,7 @@ Pandoc (Meta [Str "Pandoc",Space,Str "Test",Space,Str "Suite"] ["John MacFarlane
294294, Key [Str "bar"] (Src "/url/" "Title with &quot;quotes&quot; inside")
295295, Header 2 [Str "With",Space,Str "ampersands"]
296296, Para [Str "Here",Apostrophe,Str "s",Space,Str "a",Space,Link [Str "link",Space,Str "with",Space,Str "an",Space,Str "ampersand",Space,Str "in",Space,Str "the",Space,Str "URL"] (Ref [Str "1"]),Str "."]
297−, Para [Str "Here",Apostrophe,Str "s",Space,Str "a",Space,Str "link",Space,Str "with",Space,Str "an",Space,Str "amersand",Space,Str "in",Space,Str "the",Space,Str "link",Space,Str "text:",Space,Link [Str "AT&T"] (Ref [Str "2"]),Str "."]
297+, Para [Str "Here",Apostrophe,Str "s",Space,Str "a",Space,Str "link",Space,Str "with",Space,Str "an",Space,Str "amersand",Space,Str "in",Space,Str "the",Space,Str "link",Space,Str "text:",Space,Link [Str "AT",Str "&",Str "T"] (Ref [Str "2"]),Str "."]
298298, Para [Str "Here",Apostrophe,Str "s",Space,Str "an",Space,Link [Str "inline",Space,Str "link"] (Src "/script?foo=1&bar=2" ""),Str "."]
299299, Para [Str "Here",Apostrophe,Str "s",Space,Str "an",Space,Link [Str "inline",Space,Str "link",Space,Str "in",Space,Str "pointy",Space,Str "braces"] (Src "/script?foo=1&bar=2" ""),Str "."]
300300, Key [Str "1"] (Src "http://example.com/?foo=1&bar=2" "")
tests/writer.docbook+30−30
@@ -89,7 +89,7 @@
8989 </para>
9090 <screen>
9191sub status {
92− print &quot;working&quot;;
92+ print &#34;working&#34;;
9393}
9494</screen>
9595 <para>
@@ -122,7 +122,7 @@ sub status {
122122 </blockquote>
123123 </blockquote>
124124 <para>
125− This should not be a block quote: 2 &gt; 1.
125+ This should not be a block quote: 2 &#62; 1.
126126 </para>
127127 <para>
128128 Box-style:
@@ -133,7 +133,7 @@ sub status {
133133 </para>
134134 <screen>
135135sub status {
136− print &quot;working&quot;;
136+ print &#34;working&#34;;
137137}
138138</screen>
139139 </blockquote>
@@ -177,7 +177,7 @@ sub status {
177177---- (should be four hyphens)
178178
179179sub status {
180− print &quot;working&quot;;
180+ print &#34;working&#34;;
181181}
182182
183183this code block is indented by one tab
@@ -188,7 +188,7 @@ this code block is indented by one tab
188188 <screen>
189189 this code block is indented by two tabs
190190
191−These should not be escaped: \$ \\ \&gt; \[ \{
191+These should not be escaped: \$ \\ \&#62; \[ \{
192192</screen>
193193 </section>
194194 <section>
@@ -577,9 +577,9 @@ These should not be escaped: \$ \\ \&gt; \[ \{
577577 word.
578578 </para>
579579 <para>
580− This is code: <literal>&gt;</literal>, <literal>$</literal>,
580+ This is code: <literal>&#62;</literal>, <literal>$</literal>,
581581 <literal>\</literal>, <literal>\$</literal>,
582− <literal>&lt;html&gt;</literal>.
582+ <literal>&#60;html&#62;</literal>.
583583 </para>
584584 </section>
585585 <section>
@@ -602,7 +602,7 @@ These should not be escaped: \$ \\ \&gt; \[ \{
602602 </para>
603603 <para>
604604 Here is some quoted <quote><literal>code</literal></quote> and a
605− <quote><ulink url="http://example.com/?foo=1&amp;bar=2">quoted link</ulink></quote>.
605+ <quote><ulink url="http://example.com/?foo=1&#38;bar=2">quoted link</ulink></quote>.
606606 </para>
607607 <para>
608608 Some dashes: one&#8212;two&#8212;three&#8212;four&#8212;five.
@@ -691,9 +691,9 @@ These should not be escaped: \$ \\ \&gt; \[ \{
691691 </para>
692692 <para>
693693 <literal>\begin{tabular}{|l|l|}\hline
694−Animal &amp; Number \\ \hline
695−Dog &amp; 2 \\
696−Cat &amp; 1 \\ \hline
694+Animal &#38; Number \\ \hline
695+Dog &#38; 2 \\
696+Cat &#38; 1 \\ \hline
697697\end{tabular}</literal>
698698 </para>
699699 </section>
@@ -705,44 +705,44 @@ Cat &amp; 1 \\ \hline
705705 <itemizedlist>
706706 <listitem>
707707 <para>
708− I hat: &Icirc;
708+ I hat: &#206;
709709 </para>
710710 </listitem>
711711 <listitem>
712712 <para>
713− o umlaut: &ouml;
713+ o umlaut: &#246;
714714 </para>
715715 </listitem>
716716 <listitem>
717717 <para>
718− section: &sect;
718+ section: &#167;
719719 </para>
720720 </listitem>
721721 <listitem>
722722 <para>
723− set membership: &isin;
723+ set membership: &#8712;
724724 </para>
725725 </listitem>
726726 <listitem>
727727 <para>
728− copyright: &copy;
728+ copyright: &#169;
729729 </para>
730730 </listitem>
731731 </itemizedlist>
732732 <para>
733− AT&amp;T has an ampersand in their name.
733+ AT&#38;T has an ampersand in their name.
734734 </para>
735735 <para>
736− AT&amp;T is another way to write it.
736+ AT&#38;T is another way to write it.
737737 </para>
738738 <para>
739− This &amp; that.
739+ This &#38; that.
740740 </para>
741741 <para>
742− 4 &lt; 5.
742+ 4 &#60; 5.
743743 </para>
744744 <para>
745− 6 &gt; 5.
745+ 6 &#62; 5.
746746 </para>
747747 <para>
748748 Backslash: \
@@ -775,7 +775,7 @@ Cat &amp; 1 \\ \hline
775775 Right paren: )
776776 </para>
777777 <para>
778− Greater-than: &gt;
778+ Greater-than: &#62;
779779 </para>
780780 <para>
781781 Hash: #
@@ -868,25 +868,25 @@ Cat &amp; 1 \\ \hline
868868 <title>With ampersands</title>
869869 <para>
870870 Here's a
871− <ulink url="http://example.com/?foo=1&amp;bar=2">link with an ampersand in the URL</ulink>.
871+ <ulink url="http://example.com/?foo=1&#38;bar=2">link with an ampersand in the URL</ulink>.
872872 </para>
873873 <para>
874874 Here's a link with an amersand in the link text:
875− <ulink url="http://att.com/">AT&amp;T</ulink>.
875+ <ulink url="http://att.com/">AT&#38;T</ulink>.
876876 </para>
877877 <para>
878− Here's an <ulink url="/script?foo=1&amp;bar=2">inline link</ulink>.
878+ Here's an <ulink url="/script?foo=1&#38;bar=2">inline link</ulink>.
879879 </para>
880880 <para>
881881 Here's an
882− <ulink url="/script?foo=1&amp;bar=2">inline link in pointy braces</ulink>.
882+ <ulink url="/script?foo=1&#38;bar=2">inline link in pointy braces</ulink>.
883883 </para>
884884 </section>
885885 <section>
886886 <title>Autolinks</title>
887887 <para>
888888 With an ampersand:
889− <ulink url="http://example.com/?foo=1&amp;bar=2">http://example.com/?foo=1&amp;bar=2</ulink>
889+ <ulink url="http://example.com/?foo=1&#38;bar=2">http://example.com/?foo=1&#38;bar=2</ulink>
890890 </para>
891891 <itemizedlist>
892892 <listitem>
@@ -916,10 +916,10 @@ Cat &amp; 1 \\ \hline
916916 </blockquote>
917917 <para>
918918 Auto-links should not occur here:
919− <literal>&lt;http://example.com/&gt;</literal>
919+ <literal>&#60;http://example.com/&#62;</literal>
920920 </para>
921921 <screen>
922−or here: &lt;http://example.com/&gt;
922+or here: &#60;http://example.com/&#62;
923923</screen>
924924 </section>
925925 </section>
@@ -970,7 +970,7 @@ or here: &lt;http://example.com/&gt;
970970 footnote (as with list items).
971971 </para>
972972 <screen>
973− { &lt;code&gt; }
973+ { &#60;code&#62; }
974974</screen>
975975 <para>
976976 If you want, you can indent every line, but you can also be lazy
tests/writer.native+3−3
@@ -240,8 +240,8 @@ Pandoc (Meta [Str "Pandoc",Space,Str "Test",Space,Str "Suite"] ["John MacFarlane
240240 , [ Plain [Str "section:",Space,Str "\167"] ]
241241 , [ Plain [Str "set",Space,Str "membership:",Space,Str "\8712"] ]
242242 , [ Plain [Str "copyright:",Space,Str "\169"] ] ]
243−, Para [Str "AT&T",Space,Str "has",Space,Str "an",Space,Str "ampersand",Space,Str "in",Space,Str "their",Space,Str "name",Str "."]
244−, Para [Str "AT&T",Space,Str "is",Space,Str "another",Space,Str "way",Space,Str "to",Space,Str "write",Space,Str "it",Str "."]
243+, Para [Str "AT",Str "&",Str "T",Space,Str "has",Space,Str "an",Space,Str "ampersand",Space,Str "in",Space,Str "their",Space,Str "name",Str "."]
244+, Para [Str "AT",Str "&",Str "T",Space,Str "is",Space,Str "another",Space,Str "way",Space,Str "to",Space,Str "write",Space,Str "it",Str "."]
245245, Para [Str "This",Space,Str "&",Space,Str "that",Str "."]
246246, Para [Str "4",Space,Str "<",Space,Str "5",Str "."]
247247, Para [Str "6",Space,Str ">",Space,Str "5",Str "."]
@@ -294,7 +294,7 @@ Pandoc (Meta [Str "Pandoc",Space,Str "Test",Space,Str "Suite"] ["John MacFarlane
294294, Key [Str "bar"] (Src "/url/" "Title with &quot;quotes&quot; inside")
295295, Header 2 [Str "With",Space,Str "ampersands"]
296296, Para [Str "Here",Apostrophe,Str "s",Space,Str "a",Space,Link [Str "link",Space,Str "with",Space,Str "an",Space,Str "ampersand",Space,Str "in",Space,Str "the",Space,Str "URL"] (Ref [Str "1"]),Str "."]
297−, Para [Str "Here",Apostrophe,Str "s",Space,Str "a",Space,Str "link",Space,Str "with",Space,Str "an",Space,Str "amersand",Space,Str "in",Space,Str "the",Space,Str "link",Space,Str "text:",Space,Link [Str "AT&T"] (Ref [Str "2"]),Str "."]
297+, Para [Str "Here",Apostrophe,Str "s",Space,Str "a",Space,Str "link",Space,Str "with",Space,Str "an",Space,Str "amersand",Space,Str "in",Space,Str "the",Space,Str "link",Space,Str "text:",Space,Link [Str "AT",Str "&",Str "T"] (Ref [Str "2"]),Str "."]
298298, Para [Str "Here",Apostrophe,Str "s",Space,Str "an",Space,Link [Str "inline",Space,Str "link"] (Src "/script?foo=1&bar=2" ""),Str "."]
299299, Para [Str "Here",Apostrophe,Str "s",Space,Str "an",Space,Link [Str "inline",Space,Str "link",Space,Str "in",Space,Str "pointy",Space,Str "braces"] (Src "/script?foo=1&bar=2" ""),Str "."]
300300, Key [Str "1"] (Src "http://example.com/?foo=1&bar=2" "")