git.iko.soy/typeable/pandoc
on master help sign in
Refactored SGML escaping functions and "in tag" functions to

Text/Shared/Pandoc. (escapeSGML, stringToSGML, inTag, inTagSimple, inTagIndented, selfClosingTag) These can be used by both the HTML and Docbook writers. git-svn-id: https://pandoc.googlecode.com/svn/trunk@417 788f1e2b-df1e-0410-8736-df70ead52e1b

commit030d94e1c3cd4be0ab9d7c16fccfa973cedb5d38 authorfiddlosopher <fiddlosopher@788f1e2b-df1e-0410-8736-df70ead52e1b> dateThu 4 Jan 2007, 22:52 (20 years ago) parent24f3710
10 files changed+252−249
debian/changelog+2 src/Text/Pandoc/Shared.hs+95−3 src/Text/Pandoc/Writers/Docbook.hs+81−115 src/Text/Pandoc/Writers/HTML.hs+10−68 tests/s5.basic.html+1−1 tests/s5.fragment.html+1−1 tests/s5.inserts.html+1−1 tests/writer.docbook+15−14 tests/writer.html+24−24 tests/writer.smart.html+22−22
debian/changelog+2
@@ -186,6 +186,8 @@ pandoc (0.3) unstable; urgency=low
186186 + Renamed 'Text/Pandoc/HtmlEntities' module to
187187 'Text/Pandoc/Entities'. Also changed function names so as
188188 not to be HTML-specific.
189+ + Refactored SGML string escaping functions from HTML and Docbook
190+ writers into Text/Pandoc/Shared. (escapeSGML, stringToSGML)
189191 + Removed 'BlockQuoteContext' from ParserContext, as it isn't
190192 used anywhere.
191193 + Removed splitBySpace and replaced it with a general, polymorphic
src/Text/Pandoc/Shared.hs+95−3
@@ -28,6 +28,8 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
2828Utility functions and definitions used by the various Pandoc modules.
2929-}
3030module Text.Pandoc.Shared (
31+ -- * List processing
32+ splitBy,
3133 -- * Text processing
3234 gsub,
3335 joinWithSep,
@@ -52,7 +54,6 @@ module Text.Pandoc.Shared (
5254 -- * Pandoc block list processing
5355 consolidateList,
5456 isNoteBlock,
55− splitBy,
5657 normalizeSpaces,
5758 compactify,
5859 generateReference,
@@ -62,12 +63,21 @@ module Text.Pandoc.Shared (
6263 lookupKeySrc,
6364 refsMatch,
6465 replaceReferenceLinks,
65− replaceRefLinksBlockList
66+ replaceRefLinksBlockList,
67+ -- * SGML
68+ escapeSGML,
69+ stringToSGML,
70+ inTags,
71+ selfClosingTag,
72+ inTagsSimple,
73+ inTagsIndented
6674 ) where
6775import Text.Pandoc.Definition
6876import Text.ParserCombinators.Parsec
69−import Text.Pandoc.Entities ( decodeEntities )
77+import Text.Pandoc.Entities ( decodeEntities, encodeEntities )
7078import Text.Regex ( matchRegexAll, mkRegex, subRegex, Regex )
79+import Text.PrettyPrint.HughesPJ as PP ( text, char, (<>), ($$), nest, Doc,
80+ isEmpty )
7181import Char ( toLower )
7282import List ( find, groupBy )
7383
@@ -507,3 +517,85 @@ replaceRefLinksInline keytable (Emph lst) =
507517replaceRefLinksInline keytable (Strong lst) =
508518 Strong (map (replaceRefLinksInline keytable) lst)
509519replaceRefLinksInline keytable other = other
520+
521+-- | Escape string, preserving character entities and quote, and adding
522+-- smart typography if specified.
523+stringToSGML :: WriterOptions -> String -> String
524+stringToSGML options =
525+ let escapeDoubleQuotes =
526+ gsub "(\"|&quot;)" "&rdquo;" . -- rest are right quotes
527+ gsub "(\"|&quot;)(&r[sd]quo;)" "&rdquo;\\2" .
528+ -- never left quo before right quo
529+ gsub "(&l[sd]quo;)(\"|&quot;)" "\\2&ldquo;" .
530+ -- never right quo after left quo
531+ gsub "([ \t])(\"|&quot;)" "\\1&ldquo;" .
532+ -- never right quo after space
533+ gsub "(\"|&quot;)([^,.;:!?^) \t-])" "&ldquo;\\2" . -- "word left
534+ gsub "(\"|&quot;)('|`|&lsquo;)" "&rdquo;&rsquo;" .
535+ -- right if it got through last filter
536+ gsub "(\"|&quot;)('|`|&lsquo;)([^,.;:!?^) \t-])" "&ldquo;&lsquo;\\3" .
537+ -- "'word left
538+ gsub "``" "&ldquo;" .
539+ gsub "''" "&rdquo;"
540+ escapeSingleQuotes =
541+ gsub "'" "&rsquo;" . -- otherwise right
542+ gsub "'(&r[sd]quo;)" "&rsquo;\\1" . -- never left quo before right quo
543+ gsub "(&l[sd]quo;)'" "\\1&lsquo;" . -- never right quo after left quo
544+ gsub "([ \t])'" "\\1&lsquo;" . -- never right quo after space
545+ gsub "`" "&lsquo;" . -- ` is left
546+ gsub "([^,.;:!?^) \t-])'" "\\1&rsquo;" . -- word' right
547+ gsub "^('|`)([^,.;:!?^) \t-])" "&lsquo;\\2" . -- 'word left
548+ gsub "('|`)(\"|&quot;|&ldquo;|``)" "&lsquo;&ldquo;" . -- '"word left
549+ gsub "([^,.;:!?^) \t-])'(s|S)" "\\1&rsquo;\\2" . -- possessive
550+ gsub "([[:space:]])'([^,.;:!?^) \t-])" "\\1&lsquo;\\2" . -- 'word left
551+ gsub "'([0-9][0-9](s|S))" "&rsquo;\\1" -- '80s - decade abbrevs.
552+ escapeDashes =
553+ gsub " ?-- ?" "&mdash;" .
554+ gsub " ?--- ?" "&mdash;" .
555+ gsub "([0-9])--?([0-9])" "\\1&ndash;\\2"
556+ escapeEllipses = gsub "\\.\\.\\.|\\. \\. \\." "&hellip;"
557+ smartFilter = escapeSingleQuotes . escapeDoubleQuotes . escapeDashes .
558+ escapeEllipses in
559+ encodeEntities . (if (writerSmart options) then smartFilter else id) .
560+ (escapePreservingRegex escapeSGML (mkRegex "&[[:alnum:]]*;"))
561+
562+-- | Escape string as needed for HTML. Entity references are not preserved.
563+escapeSGML :: String -> String
564+escapeSGML [] = []
565+escapeSGML (x:xs) = case x of
566+ '&' -> "&amp;" ++ escapeSGML xs
567+ '<' -> "&lt;" ++ escapeSGML xs
568+ '>' -> "&gt;" ++ escapeSGML xs
569+ '"' -> "&quot;" ++ escapeSGML xs
570+ _ -> x:(escapeSGML xs)
571+
572+-- | Return a text object with a string of formatted SGML attributes.
573+attributeList :: WriterOptions -> [(String, String)] -> Doc
574+attributeList options =
575+ text . concatMap (\(a, b) -> " " ++ stringToSGML options a ++ "=\"" ++
576+ stringToSGML options b ++ "\"")
577+
578+-- | Put the supplied contents between start and end tags of tagType,
579+-- with specified attributes and (if specified) indentation.
580+inTags:: Bool -> WriterOptions -> String -> [(String, String)] -> Doc -> Doc
581+inTags isIndented options tagType attribs contents =
582+ let openTag = PP.char '<' <> text tagType <> attributeList options attribs <>
583+ PP.char '>'
584+ closeTag = text "</" <> text tagType <> PP.char '>' in
585+ if isIndented
586+ then openTag $$ nest 2 contents $$ closeTag
587+ else openTag <> contents <> closeTag
588+
589+-- | Return a self-closing tag of tagType with specified attributes
590+selfClosingTag :: WriterOptions -> String -> [(String, String)] -> Doc
591+selfClosingTag options tagType attribs =
592+ PP.char '<' <> text tagType <> attributeList options attribs <> text " />"
593+
594+-- | Put the supplied contents between start and end tags of tagType.
595+inTagsSimple :: WriterOptions -> String -> Doc -> Doc
596+inTagsSimple options tagType = inTags False options tagType []
597+
598+-- | Put the supplied contents in indented block btw start and end tags.
599+inTagsIndented :: WriterOptions -> String -> Doc -> Doc
600+inTagsIndented options tagType = inTags True options tagType []
601+
src/Text/Pandoc/Writers/Docbook.hs+81−115
@@ -32,9 +32,7 @@ module Text.Pandoc.Writers.Docbook (
3232 ) where
3333import Text.Pandoc.Definition
3434import Text.Pandoc.Shared
35−import Text.Pandoc.Writers.HTML ( stringToSmartHtml, stringToHtml )
3635import Text.Pandoc.Entities ( encodeEntities )
37−import Text.Html ( stringToHtmlString )
3836import Text.Regex ( mkRegex, matchRegex )
3937import Data.Char ( toLower, ord )
4038import Data.List ( isPrefixOf, partition )
@@ -54,19 +52,21 @@ hierarchicalize :: [Block] -> [Element]
5452hierarchicalize [] = []
5553hierarchicalize (block:rest) =
5654 case block of
57− (Header level title) -> let (thisSection, rest') = break (headerAtLeast level) rest in
58− (Sec title (hierarchicalize thisSection)):(hierarchicalize rest')
55+ (Header level title) -> let (thisSection, rest') = break (headerAtLeast
56+ level) rest in
57+ (Sec title (hierarchicalize thisSection)):
58+ (hierarchicalize rest')
5959 x -> (Blk x):(hierarchicalize rest)
6060
6161-- | Convert list of authors to a docbook <author> section
6262authorToDocbook :: WriterOptions -> [Char] -> Doc
63−authorToDocbook options name = indentedInTags "author" $
63+authorToDocbook opts name = inTagsIndented opts "author" $
6464 if ',' `elem` name
6565 then -- last name first
6666 let (lastname, rest) = break (==',') name
6767 firstname = removeLeadingSpace rest in
68− inTags "firstname" (text $ stringToXML options firstname) <>
69− inTags "surname" (text $ stringToXML options lastname)
68+ inTagsSimple opts "firstname" (text $ stringToSGML opts firstname) <>
69+ inTagsSimple opts "surname" (text $ stringToSGML opts lastname)
7070 else -- last name last
7171 let namewords = words name
7272 lengthname = length namewords
@@ -74,101 +74,82 @@ authorToDocbook options name = indentedInTags "author" $
7474 0 -> ("","")
7575 1 -> ("", name)
7676 n -> (joinWithSep " " (take (n-1) namewords), last namewords) in
77− inTags "firstname" (text $ stringToXML options firstname) $$
78− inTags "surname" (text $ stringToXML options lastname)
77+ inTagsSimple opts "firstname" (text $ stringToSGML opts firstname) $$
78+ inTagsSimple opts "surname" (text $ stringToSGML opts lastname)
7979
8080-- | Convert Pandoc document to string in Docbook format.
8181writeDocbook :: WriterOptions -> Pandoc -> String
82−writeDocbook options (Pandoc (Meta title authors date) blocks) =
83− let head = if (writerStandalone options)
84− then text (writerHeader options)
82+writeDocbook opts (Pandoc (Meta title authors date) blocks) =
83+ let head = if (writerStandalone opts)
84+ then text (writerHeader opts)
8585 else empty
86− meta = if (writerStandalone options)
87− then indentedInTags "articleinfo" $
88− (inTags "title" (inlinesToDocbook options title)) $$
89− (vcat (map (authorToDocbook options) authors)) $$
90− (inTags "date" (text date))
86+ meta = if (writerStandalone opts)
87+ then inTagsIndented opts "articleinfo" $
88+ (inTagsSimple opts "title" (inlinesToDocbook opts title)) $$
89+ (vcat (map (authorToDocbook opts) authors)) $$
90+ (inTagsSimple opts "date" (text $ stringToSGML opts date))
9191 else empty
9292 blocks' = replaceReferenceLinks blocks
9393 (noteBlocks, blocks'') = partition isNoteBlock blocks'
94− options' = options {writerNotes = noteBlocks}
94+ opts' = opts {writerNotes = noteBlocks}
9595 elements = hierarchicalize blocks''
96− body = text (writerIncludeBefore options') <>
97− vcat (map (elementToDocbook options') elements) $$
98− text (writerIncludeAfter options')
99− body' = if writerStandalone options'
100− then indentedInTags "article" (meta $$ body)
96+ body = text (writerIncludeBefore opts') <>
97+ vcat (map (elementToDocbook opts') elements) $$
98+ text (writerIncludeAfter opts')
99+ body' = if writerStandalone opts'
100+ then inTagsIndented opts "article" (meta $$ body)
101101 else body in
102102 render $ head $$ body' <> text "\n"
103103
104−-- | Put the supplied contents between start and end tags of tagType,
105−-- with specified attributes.
106−inTagsWithAttrib :: String -> [(String, String)] -> Doc -> Doc
107−inTagsWithAttrib tagType attribs contents = text ("<" ++ tagType ++
108− (concatMap (\(a, b) -> " " ++ attributeStringToXML a ++
109− "=\"" ++ attributeStringToXML b ++ "\"") attribs)) <>
110− if isEmpty contents
111− then text " />" -- self-closing tag
112− else text ">" <> contents <> text ("</" ++ tagType ++ ">")
113−
114−-- | Put the supplied contents between start and end tags of tagType.
115−inTags :: String -> Doc -> Doc
116−inTags tagType contents = inTagsWithAttrib tagType [] contents
117−
118−-- | Put the supplied contents in indented block btw start and end tags.
119−indentedInTags :: [Char] -> Doc -> Doc
120−indentedInTags tagType contents = text ("<" ++ tagType ++ ">") $$
121− nest 2 contents $$ text ("</" ++ tagType ++ ">")
122−
123104-- | Convert an Element to Docbook.
124105elementToDocbook :: WriterOptions -> Element -> Doc
125−elementToDocbook options (Blk block) = blockToDocbook options block
126−elementToDocbook options (Sec title elements) =
106+elementToDocbook opts (Blk block) = blockToDocbook opts block
107+elementToDocbook opts (Sec title elements) =
127108 -- Docbook doesn't allow sections with no content, so insert some if needed
128109 let elements' = if null elements
129110 then [Blk (Para [])]
130111 else elements in
131− indentedInTags "section" $
132− inTags "title" (wrap options title) $$
133− vcat (map (elementToDocbook options) elements')
112+ inTagsIndented opts "section" $
113+ inTagsSimple opts "title" (wrap opts title) $$
114+ vcat (map (elementToDocbook opts) elements')
134115
135116-- | Convert a list of Pandoc blocks to Docbook.
136117blocksToDocbook :: WriterOptions -> [Block] -> Doc
137−blocksToDocbook options = vcat . map (blockToDocbook options)
118+blocksToDocbook opts = vcat . map (blockToDocbook opts)
138119
139120-- | Convert a list of lists of blocks to a list of Docbook list items.
140121listItemsToDocbook :: WriterOptions -> [[Block]] -> Doc
141−listItemsToDocbook options items =
142− vcat $ map (listItemToDocbook options) items
122+listItemsToDocbook opts items =
123+ vcat $ map (listItemToDocbook opts) items
143124
144125-- | Convert a list of blocks into a Docbook list item.
145126listItemToDocbook :: WriterOptions -> [Block] -> Doc
146−listItemToDocbook options item =
127+listItemToDocbook opts item =
147128 let plainToPara (Plain x) = Para x
148129 plainToPara y = y in
149130 let item' = map plainToPara item in
150− indentedInTags "listitem" (blocksToDocbook options item')
131+ inTagsIndented opts "listitem" (blocksToDocbook opts item')
151132
152133-- | Convert a Pandoc block element to Docbook.
153134blockToDocbook :: WriterOptions -> Block -> Doc
154−blockToDocbook options Blank = text ""
155−blockToDocbook options Null = empty
156−blockToDocbook options (Plain lst) = wrap options lst
157−blockToDocbook options (Para lst) =
158− indentedInTags "para" (wrap options lst)
159−blockToDocbook options (BlockQuote blocks) =
160− indentedInTags "blockquote" (blocksToDocbook options blocks)
161−blockToDocbook options (CodeBlock str) =
162− text "<screen>\n" <> text (codeStringToXML str) <> text "\n</screen>"
163−blockToDocbook options (BulletList lst) =
164− indentedInTags "itemizedlist" $ listItemsToDocbook options lst
165−blockToDocbook options (OrderedList lst) =
166− indentedInTags "orderedlist" $ listItemsToDocbook options lst
167−blockToDocbook options (RawHtml str) = text str -- raw XML block
168−blockToDocbook options HorizontalRule = empty -- not semantic
169−blockToDocbook options (Note _ _) = empty -- shouldn't occur
170−blockToDocbook options (Key _ _) = empty -- shouldn't occur
171−blockToDocbook options _ = indentedInTags "para" (text "Unknown block type")
135+blockToDocbook opts Blank = text ""
136+blockToDocbook opts Null = empty
137+blockToDocbook opts (Plain lst) = wrap opts lst
138+blockToDocbook opts (Para lst) =
139+ inTagsIndented opts "para" (wrap opts lst)
140+blockToDocbook opts (BlockQuote blocks) =
141+ inTagsIndented opts "blockquote" (blocksToDocbook opts blocks)
142+blockToDocbook opts (CodeBlock str) =
143+ text "<screen>\n" <> text (escapeSGML str) <> text "\n</screen>"
144+blockToDocbook opts (BulletList lst) =
145+ inTagsIndented opts "itemizedlist" $ listItemsToDocbook opts lst
146+blockToDocbook opts (OrderedList lst) =
147+ inTagsIndented opts "orderedlist" $ listItemsToDocbook opts lst
148+blockToDocbook opts (RawHtml str) = text str -- raw XML block
149+blockToDocbook opts HorizontalRule = empty -- not semantic
150+blockToDocbook opts (Note _ _) = empty -- shouldn't occur
151+blockToDocbook opts (Key _ _) = empty -- shouldn't occur
152+blockToDocbook opts _ = inTagsIndented opts "para" (text "Unknown block type")
172153
173154-- | Put string in CDATA section
174155cdata :: String -> Doc
@@ -176,62 +157,47 @@ cdata str = text $ "<![CDATA[" ++ str ++ "]]>"
176157
177158-- | Take list of inline elements and return wrapped doc.
178159wrap :: WriterOptions -> [Inline] -> Doc
179−wrap options lst = fsep $ map (inlinesToDocbook options) (splitBy Space lst)
180−
181−-- | Escape a string for XML (with "smart" option if specified).
182−stringToXML :: WriterOptions -> String -> String
183−stringToXML options = encodeEntities .
184− (if writerSmart options
185− then stringToSmartHtml
186− else stringToHtml)
187−
188−-- | Escape string to XML appropriate for attributes
189−attributeStringToXML :: String -> String
190−attributeStringToXML = gsub "\"" "&quot;" . codeStringToXML
191−
192−-- | Escape a literal string for XML.
193−codeStringToXML :: String -> String
194−codeStringToXML = encodeEntities . gsub "<" "&lt;" . gsub "&" "&amp;"
160+wrap opts lst = fsep $ map (inlinesToDocbook opts) (splitBy Space lst)
195161
196162-- | Convert a list of inline elements to Docbook.
197163inlinesToDocbook :: WriterOptions -> [Inline] -> Doc
198−inlinesToDocbook options lst = hcat (map (inlineToDocbook options) lst)
164+inlinesToDocbook opts lst = hcat (map (inlineToDocbook opts) lst)
199165
200166-- | Convert an inline element to Docbook.
201167inlineToDocbook :: WriterOptions -> Inline -> Doc
202−inlineToDocbook options (Str str) = text $ stringToXML options str
203−inlineToDocbook options (Emph lst) =
204− inTags "emphasis" (inlinesToDocbook options lst)
205−inlineToDocbook options (Strong lst) =
206− inTagsWithAttrib "emphasis" [("role", "strong")]
207− (inlinesToDocbook options lst)
208−inlineToDocbook options (Code str) =
209− inTags "literal" $ text (codeStringToXML str)
210−inlineToDocbook options (TeX str) = inlineToDocbook options (Code str)
211−inlineToDocbook options (HtmlInline str) = empty
212−inlineToDocbook options LineBreak =
168+inlineToDocbook opts (Str str) = text $ stringToSGML opts str
169+inlineToDocbook opts (Emph lst) =
170+ inTagsSimple opts "emphasis" (inlinesToDocbook opts lst)
171+inlineToDocbook opts (Strong lst) =
172+ inTags False opts "emphasis" [("role", "strong")]
173+ (inlinesToDocbook opts lst)
174+inlineToDocbook opts (Code str) =
175+ inTagsSimple opts "literal" $ text (escapeSGML str)
176+inlineToDocbook opts (TeX str) = inlineToDocbook opts (Code str)
177+inlineToDocbook opts (HtmlInline str) = empty
178+inlineToDocbook opts LineBreak =
213179 text $ "<literallayout></literallayout>"
214−inlineToDocbook options Space = char ' '
215−inlineToDocbook options (Link txt (Src src tit)) =
180+inlineToDocbook opts Space = char ' '
181+inlineToDocbook opts (Link txt (Src src tit)) =
216182 case (matchRegex (mkRegex "mailto:(.*)") src) of
217− Just [addr] -> inTags "email" $ text (codeStringToXML addr)
218− Nothing -> inTagsWithAttrib "ulink" [("url", src)] $
219− inlinesToDocbook options txt
220−inlineToDocbook options (Link text (Ref ref)) = empty -- shouldn't occur
221−inlineToDocbook options (Image alt (Src src tit)) =
183+ Just [addr] -> inTagsSimple opts "email" $ text (escapeSGML addr)
184+ Nothing -> inTags False opts "ulink" [("url", src)] $
185+ inlinesToDocbook opts txt
186+inlineToDocbook opts (Link text (Ref ref)) = empty -- shouldn't occur
187+inlineToDocbook opts (Image alt (Src src tit)) =
222188 let titleDoc = if null tit
223189 then empty
224− else indentedInTags "objectinfo" $
225− indentedInTags "title"
226− (text $ stringToXML options tit) in
227− indentedInTags "inlinemediaobject" $
228− indentedInTags "imageobject" $
229− titleDoc $$ inTagsWithAttrib "imagedata" [("fileref", src)] empty
230−inlineToDocbook options (Image alternate (Ref ref)) = empty --shouldn't occur
231−inlineToDocbook options (NoteRef ref) =
232− let notes = writerNotes options
190+ else inTagsIndented opts "objectinfo" $
191+ inTagsIndented opts "title"
192+ (text $ stringToSGML opts tit) in
193+ inTagsIndented opts "inlinemediaobject" $
194+ inTagsIndented opts "imageobject" $
195+ titleDoc $$ selfClosingTag opts "imagedata" [("fileref", src)]
196+inlineToDocbook opts (Image alternate (Ref ref)) = empty --shouldn't occur
197+inlineToDocbook opts (NoteRef ref) =
198+ let notes = writerNotes opts
233199 hits = filter (\(Note r _) -> r == ref) notes in
234200 if null hits
235201 then empty
236202 else let (Note _ contents) = head hits in
237− indentedInTags "footnote" $ blocksToDocbook options contents
203+ inTagsIndented opts "footnote" $ blocksToDocbook opts contents
src/Text/Pandoc/Writers/HTML.hs+10−68
@@ -29,12 +29,10 @@ Conversion of 'Pandoc' documents to HTML.
2929-}
3030module Text.Pandoc.Writers.HTML (
3131 writeHtml,
32− stringToSmartHtml,
33− stringToHtml
3432 ) where
3533import Text.Pandoc.Definition
3634import Text.Pandoc.Shared
37−import Text.Html ( stringToHtmlString )
35+import Text.Pandoc.Entities ( encodeEntities )
3836import Text.Regex ( mkRegex, matchRegex )
3937import Numeric ( showHex )
4038import Data.Char ( ord, toLower )
@@ -115,61 +113,6 @@ obfuscateChar char =
115113obfuscateString :: String -> String
116114obfuscateString = concatMap obfuscateChar
117115
118−-- | Escape string, preserving character entities and quote.
119−stringToHtml :: String -> String
120−stringToHtml str = escapePreservingRegex stringToHtmlString
121− (mkRegex "\"|(&[[:alnum:]]*;)") str
122−
123−-- | Escape string as in 'stringToHtml' but add smart typography filter.
124−stringToSmartHtml :: String -> String
125−stringToSmartHtml =
126− let escapeDoubleQuotes =
127− gsub "(\"|&quot;)" "&rdquo;" . -- rest are right quotes
128− gsub "(\"|&quot;)(&r[sd]quo;)" "&rdquo;\\2" .
129− -- never left quo before right quo
130− gsub "(&l[sd]quo;)(\"|&quot;)" "\\2&ldquo;" .
131− -- never right quo after left quo
132− gsub "([ \t])(\"|&quot;)" "\\1&ldquo;" .
133− -- never right quo after space
134− gsub "(\"|&quot;)([^,.;:!?^) \t-])" "&ldquo;\\2" . -- "word left
135− gsub "(\"|&quot;)('|`|&lsquo;)" "&rdquo;&rsquo;" .
136− -- right if it got through last filter
137− gsub "(\"|&quot;)('|`|&lsquo;)([^,.;:!?^) \t-])" "&ldquo;&lsquo;\\3" .
138− -- "'word left
139− gsub "``" "&ldquo;" .
140− gsub "''" "&rdquo;"
141− escapeSingleQuotes =
142− gsub "'" "&rsquo;" . -- otherwise right
143− gsub "'(&r[sd]quo;)" "&rsquo;\\1" . -- never left quo before right quo
144− gsub "(&l[sd]quo;)'" "\\1&lsquo;" . -- never right quo after left quo
145− gsub "([ \t])'" "\\1&lsquo;" . -- never right quo after space
146− gsub "`" "&lsquo;" . -- ` is left
147− gsub "([^,.;:!?^) \t-])'" "\\1&rsquo;" . -- word' right
148− gsub "^('|`)([^,.;:!?^) \t-])" "&lsquo;\\2" . -- 'word left
149− gsub "('|`)(\"|&quot;|&ldquo;|``)" "&lsquo;&ldquo;" . -- '"word left
150− gsub "([^,.;:!?^) \t-])'(s|S)" "\\1&rsquo;\\2" . -- possessive
151− gsub "([[:space:]])'([^,.;:!?^) \t-])" "\\1&lsquo;\\2" . -- 'word left
152− gsub "'([0-9][0-9](s|S))" "&rsquo;\\1" -- '80s - decade abbrevs.
153− escapeDashes =
154− gsub " ?-- ?" "&mdash;" .
155− gsub " ?--- ?" "&mdash;" .
156− gsub "([0-9])--?([0-9])" "\\1&ndash;\\2"
157− escapeEllipses = gsub "\\.\\.\\.|\\. \\. \\." "&hellip;" in
158− escapeSingleQuotes . escapeDoubleQuotes . escapeDashes .
159− escapeEllipses . stringToHtml
160−
161−-- | Escape code string as needed for HTML.
162−codeStringToHtml :: String -> String
163−codeStringToHtml [] = []
164−codeStringToHtml (x:xs) = case x of
165− '&' -> "&amp;" ++ codeStringToHtml xs
166− '<' -> "&lt;" ++ codeStringToHtml xs
167− _ -> x:(codeStringToHtml xs)
168−
169−-- | Escape string to HTML appropriate for attributes
170−attributeStringToHtml :: String -> String
171−attributeStringToHtml = gsub "\"" "&quot;"
172−
173116-- | Returns an HTML header with appropriate bibliographic information.
174117htmlHeader :: WriterOptions -> Meta -> String
175118htmlHeader options (Meta title authors date) =
@@ -178,12 +121,12 @@ htmlHeader options (Meta title authors date) =
178121 authortext = if (null authors)
179122 then ""
180123 else "<meta name=\"author\" content=\"" ++
181− (joinWithSep ", " (map stringToHtml authors)) ++
124+ (joinWithSep ", " (map (stringToSGML options) authors)) ++
182125 "\" />\n"
183126 datetext = if (date == "")
184127 then ""
185128 else "<meta name=\"date\" content=\"" ++
186− (stringToHtml date) ++ "\" />\n" in
129+ (stringToSGML options date) ++ "\" />\n" in
187130 (writerHeader options) ++ authortext ++ datetext ++ titletext ++
188131 "</head>\n<body>\n"
189132
@@ -216,7 +159,7 @@ blockToHtml options (Note ref lst) =
216159 "\">&#8617;</a></li>\n"
217160blockToHtml options (Key _ _) = ""
218161blockToHtml options (CodeBlock str) =
219− "<pre><code>" ++ (codeStringToHtml str) ++ "\n</code></pre>\n"
162+ "<pre><code>" ++ (escapeSGML str) ++ "\n</code></pre>\n"
220163blockToHtml options (RawHtml str) = str
221164blockToHtml options (BulletList lst) =
222165 let attribs = if (writerIncremental options)
@@ -255,18 +198,17 @@ inlineToHtml options (Emph lst) =
255198inlineToHtml options (Strong lst) =
256199 "<strong>" ++ (inlineListToHtml options lst) ++ "</strong>"
257200inlineToHtml options (Code str) =
258− "<code>" ++ (codeStringToHtml str) ++ "</code>"
259−inlineToHtml options (Str str) =
260− if (writerSmart options) then stringToSmartHtml str else stringToHtml str
261−inlineToHtml options (TeX str) = (codeStringToHtml str)
201+ "<code>" ++ (escapeSGML str) ++ "</code>"
202+inlineToHtml options (Str str) = stringToSGML options str
203+inlineToHtml options (TeX str) = (escapeSGML str)
262204inlineToHtml options (HtmlInline str) = str
263205inlineToHtml options (LineBreak) = "<br />\n"
264206inlineToHtml options Space = " "
265207inlineToHtml options (Link text (Src src tit)) =
266− let title = attributeStringToHtml tit in
208+ let title = stringToSGML options tit in
267209 if (isPrefixOf "mailto:" src)
268210 then obfuscateLink options text src
269− else "<a href=\"" ++ (codeStringToHtml src) ++ "\"" ++
211+ else "<a href=\"" ++ (escapeSGML src) ++ "\"" ++
270212 (if tit /= "" then " title=\"" ++ title ++ "\">" else ">") ++
271213 (inlineListToHtml options text) ++ "</a>"
272214inlineToHtml options (Link text (Ref ref)) =
@@ -274,7 +216,7 @@ inlineToHtml options (Link text (Ref ref)) =
274216 (inlineListToHtml options ref) ++ "]"
275217 -- this is what markdown does, for better or worse
276218inlineToHtml options (Image alt (Src source tit)) =
277− let title = attributeStringToHtml tit
219+ let title = stringToSGML options tit
278220 alternate = inlineListToHtml options alt in
279221 "<img src=\"" ++ source ++ "\"" ++
280222 (if tit /= "" then " title=\"" ++ title ++ "\"" else "") ++
tests/s5.basic.html+1−1
@@ -768,7 +768,7 @@ window.onresize = function(){setTimeout('fontScale()', 50);}</script>
768768<div class="slide">
769769<h1>Smarty</h1>
770770<ul class="incremental">
771−<li>"Hello there"</li>
771+<li>&quot;Hello there&quot;</li>
772772<li>Here's a -- dash</li>
773773<li>And 'ellipses'...</li>
774774</ul>
tests/s5.fragment.html+1−1
@@ -6,7 +6,7 @@
66<h1>Smarty</h1>
77<blockquote>
88<ul>
9−<li>"Hello there"</li>
9+<li>&quot;Hello there&quot;</li>
1010<li>Here's a -- dash</li>
1111<li>And 'ellipses'...</li>
1212</ul>
tests/s5.inserts.html+1−1
@@ -21,7 +21,7 @@ STUFF INSERTED
2121<h1>Smarty</h1>
2222<blockquote>
2323<ul>
24−<li>"Hello there"</li>
24+<li>&quot;Hello there&quot;</li>
2525<li>Here's a -- dash</li>
2626<li>And 'ellipses'...</li>
2727</ul>
tests/writer.docbook+15−14
@@ -89,7 +89,7 @@
8989 </para>
9090 <screen>
9191sub status {
92− print "working";
92+ print &quot;working&quot;;
9393}
9494</screen>
9595 <para>
@@ -133,7 +133,7 @@ sub status {
133133 </para>
134134 <screen>
135135sub status {
136− print "working";
136+ print &quot;working&quot;;
137137}
138138</screen>
139139 </blockquote>
@@ -177,7 +177,7 @@ sub status {
177177---- (should be four hyphens)
178178
179179sub status {
180− print "working";
180+ print &quot;working&quot;;
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: \$ \\ \> \[ \{
191+These should not be escaped: \$ \\ \&gt; \[ \{
192192</screen>
193193 </section>
194194 <section>
@@ -577,15 +577,16 @@ These should not be escaped: \$ \\ \> \[ \{
577577 word.
578578 </para>
579579 <para>
580− This is code: <literal>></literal>, <literal>$</literal>,
580+ This is code: <literal>&gt;</literal>, <literal>$</literal>,
581581 <literal>\</literal>, <literal>\$</literal>,
582− <literal>&lt;html></literal>.
582+ <literal>&lt;html&gt;</literal>.
583583 </para>
584584 </section>
585585 <section>
586586 <title>Smart quotes, ellipses, dashes</title>
587587 <para>
588− "Hello," said the spider. "'Shelob' is my name."
588+ &quot;Hello,&quot; said the spider. &quot;'Shelob' is my
589+ name.&quot;
589590 </para>
590591 <para>
591592 'A', 'B', and 'C' are letters.
@@ -594,11 +595,11 @@ These should not be escaped: \$ \\ \> \[ \{
594595 'Oak,' 'elm,' and 'beech' are names of trees. So is 'pine.'
595596 </para>
596597 <para>
597− 'He said, "I want to go."' Were you alive in the 70's?
598+ 'He said, &quot;I want to go.&quot;' Were you alive in the 70's?
598599 </para>
599600 <para>
600601 Here is some quoted '<literal>code</literal>' and a
601− "<ulink url="http://example.com/?foo=1&amp;bar=2">quoted link</ulink>".
602+ &quot;<ulink url="http://example.com/?foo=1&amp;bar=2">quoted link</ulink>&quot;.
602603 </para>
603604 <para>
604605 Some dashes: one---two --- three--four -- five.
@@ -672,7 +673,7 @@ These should not be escaped: \$ \\ \> \[ \{
672673 <listitem>
673674 <para>
674675 $22,000 is a <emphasis>lot</emphasis> of money. So is $34,000. (It
675− worked if "lot" is emphasized.)
676+ worked if &quot;lot&quot; is emphasized.)
676677 </para>
677678 </listitem>
678679 <listitem>
@@ -909,17 +910,17 @@ Cat &amp; 1 \\ \hline
909910 </blockquote>
910911 <para>
911912 Auto-links should not occur here:
912− <literal>&lt;http://example.com/></literal>
913+ <literal>&lt;http://example.com/&gt;</literal>
913914 </para>
914915 <screen>
915−or here: &lt;http://example.com/>
916+or here: &lt;http://example.com/&gt;
916917</screen>
917918 </section>
918919 </section>
919920 <section>
920921 <title>Images</title>
921922 <para>
922− From "Voyage dans la Lune" by Georges Melies (1902):
923+ From &quot;Voyage dans la Lune&quot; by Georges Melies (1902):
923924 </para>
924925 <para>
925926 <inlinemediaobject>
@@ -963,7 +964,7 @@ or here: &lt;http://example.com/>
963964 footnote (as with list items).
964965 </para>
965966 <screen>
966− { &lt;code> }
967+ { &lt;code&gt; }
967968</screen>
968969 <para>
969970 If you want, you can indent every line, but you can also be lazy
tests/writer.html+24−24
@@ -39,7 +39,7 @@ here.</p>
3939<blockquote>
4040<p>Code in a block quote:</p>
4141<pre><code>sub status {
42− print "working";
42+ print &quot;working&quot;;
4343}
4444</code></pre>
4545<p>A list:</p>
@@ -60,7 +60,7 @@ here.</p>
6060<blockquote>
6161<p>Example:</p>
6262<pre><code>sub status {
63− print "working";
63+ print &quot;working&quot;;
6464}
6565</code></pre>
6666</blockquote>
@@ -84,7 +84,7 @@ here.</p>
8484<pre><code>---- (should be four hyphens)
8585
8686sub status {
87− print "working";
87+ print &quot;working&quot;;
8888}
8989
9090this code block is indented by one tab
@@ -92,7 +92,7 @@ this code block is indented by one tab
9292<p>And:</p>
9393<pre><code> this code block is indented by two tabs
9494
95−These should not be escaped: \$ \\ \> \[ \{
95+These should not be escaped: \$ \\ \&gt; \[ \{
9696</code></pre>
9797<hr />
9898<h1>Lists</h1>
@@ -255,12 +255,12 @@ These should not be escaped: \$ \\ \> \[ \{
255255<div>
256256 foo</div>
257257<p>This should be a code block, though:</p>
258−<pre><code>&lt;div>
258+<pre><code>&lt;div&gt;
259259 foo
260−&lt;/div>
260+&lt;/div&gt;
261261</code></pre>
262262<p>As should this:</p>
263−<pre><code>&lt;div>foo&lt;/div>
263+<pre><code>&lt;div&gt;foo&lt;/div&gt;
264264</code></pre>
265265<p>Now, nested:</p>
266266<div>
@@ -281,12 +281,12 @@ Blah
281281 This is another comment.
282282-->
283283<p>Code block:</p>
284−<pre><code>&lt;!-- Comment -->
284+<pre><code>&lt;!-- Comment --&gt;
285285</code></pre>
286286<p>Just plain comment, with trailing spaces on the line:</p>
287287<!-- foo -->
288288<p>Code:</p>
289−<pre><code>&lt;hr />
289+<pre><code>&lt;hr /&gt;
290290</code></pre>
291291<p>Hr's:</p>
292292<hr>
@@ -315,14 +315,14 @@ Blah
315315<p>So is <strong><em>this</em></strong> word.</p>
316316<p><strong><em>This is strong and em.</em></strong></p>
317317<p>So is <strong><em>this</em></strong> word.</p>
318−<p>This is code: <code>></code>, <code>$</code>, <code>\</code>, <code>\$</code>, <code>&lt;html></code>.</p>
318+<p>This is code: <code>&gt;</code>, <code>$</code>, <code>\</code>, <code>\$</code>, <code>&lt;html&gt;</code>.</p>
319319<hr />
320320<h1>Smart quotes, ellipses, dashes</h1>
321−<p>"Hello," said the spider. "'Shelob' is my name."</p>
321+<p>&quot;Hello,&quot; said the spider. &quot;'Shelob' is my name.&quot;</p>
322322<p>'A', 'B', and 'C' are letters.</p>
323323<p>'Oak,' 'elm,' and 'beech' are names of trees. So is 'pine.'</p>
324−<p>'He said, "I want to go."' Were you alive in the 70's?</p>
325−<p>Here is some quoted '<code>code</code>' and a "<a href="http://example.com/?foo=1&amp;bar=2">quoted link</a>".</p>
324+<p>'He said, &quot;I want to go.&quot;' Were you alive in the 70's?</p>
325+<p>Here is some quoted '<code>code</code>' and a &quot;<a href="http://example.com/?foo=1&amp;bar=2">quoted link</a>&quot;.</p>
326326<p>Some dashes: one---two --- three--four -- five.</p>
327327<p>Dashes between numbers: 5-7, 255-66, 1987-1999.</p>
328328<p>Ellipses...and. . .and . . . .</p>
@@ -342,7 +342,7 @@ Blah
342342<p>These shouldn't be math:</p>
343343<ul>
344344<li>To get the famous equation, write <code>$e = mc^2$</code>.</li>
345−<li>$22,000 is a <em>lot</em> of money. So is $34,000. (It worked if "lot" is emphasized.)</li>
345+<li>$22,000 is a <em>lot</em> of money. So is $34,000. (It worked if &quot;lot&quot; is emphasized.)</li>
346346<li>Escaped <code>$</code>: $73 <em>this should be emphasized</em> 23$.</li>
347347</ul>
348348<p>Here's a LaTeX table:</p>
@@ -355,11 +355,11 @@ Cat &amp; 1 \\ \hline
355355<h1>Special Characters</h1>
356356<p>Here is some unicode:</p>
357357<ul>
358−<li>I hat: Î</li>
359−<li>o umlaut: ö</li>
360−<li>section: §</li>
361−<li>set membership: ∈</li>
362−<li>copyright: ©</li>
358+<li>I hat: &Icirc;</li>
359+<li>o umlaut: &ouml;</li>
360+<li>section: &sect;</li>
361+<li>set membership: &isin;</li>
362+<li>copyright: &copy;</li>
363363</ul>
364364<p>AT&amp;T has an ampersand in their name.</p>
365365<p>AT&amp;T is another way to write it.</p>
@@ -414,7 +414,7 @@ document.write('<a h'+'ref'+'="ma'+'ilto'+':'+e+'">'+'Email link'+'<\/'+'a'+'>')
414414<p>Foo <a href="/url/" title="Title with &quot;quote&quot; inside">biz</a>.</p>
415415<h2>With ampersands</h2>
416416<p>Here's a <a href="http://example.com/?foo=1&amp;bar=2">link with an ampersand in the URL</a>.</p>
417−<p>Here's a link with an amersand in the link text: <a href="http://att.com/" title="AT&T">AT&amp;T</a>.</p>
417+<p>Here's a link with an amersand in the link text: <a href="http://att.com/" title="AT&amp;T">AT&amp;T</a>.</p>
418418<p>Here's an <a href="/script?foo=1&amp;bar=2">inline link</a>.</p>
419419<p>Here's an <a href="/script?foo=1&amp;bar=2">inline link in pointy braces</a>.</p>
420420<h2>Autolinks</h2>
@@ -433,12 +433,12 @@ document.write('<a h'+'ref'+'="ma'+'ilto'+':'+e+'">'+e+'<\/'+'a'+'>');
433433<blockquote>
434434<p>Blockquoted: <a href="http://example.com/">http://example.com/</a></p>
435435</blockquote>
436−<p>Auto-links should not occur here: <code>&lt;http://example.com/></code></p>
437−<pre><code>or here: &lt;http://example.com/>
436+<p>Auto-links should not occur here: <code>&lt;http://example.com/&gt;</code></p>
437+<pre><code>or here: &lt;http://example.com/&gt;
438438</code></pre>
439439<hr />
440440<h1>Images</h1>
441−<p>From "Voyage dans la Lune" by Georges Melies (1902):</p>
441+<p>From &quot;Voyage dans la Lune&quot; by Georges Melies (1902):</p>
442442<p><img src="lalune.jpg" title="Voyage dans la Lune" alt="lalune"></p>
443443<p>Here is a movie <img src="movie.jpg" alt="movie"> icon.</p>
444444<hr />
@@ -458,7 +458,7 @@ document.write('<a h'+'ref'+'="ma'+'ilto'+':'+e+'">'+e+'<\/'+'a'+'>');
458458 <a href="#fnref1" class="footnoteBacklink" title="Jump back to footnote 1">&#8617;</a></li>
459459<li id="fn2"><p>Here's the long note. This one contains multiple blocks.</p>
460460<p>Subsequent blocks are indented to show that they belong to the footnote (as with list items).</p>
461−<pre><code> { &lt;code> }
461+<pre><code> { &lt;code&gt; }
462462</code></pre>
463463<p>If you want, you can indent every line, but you can also be lazy and just indent the first line of each block.</p>
464464 <a href="#fnref2" class="footnoteBacklink" title="Jump back to footnote 2">&#8617;</a></li>
tests/writer.smart.html+22−22
@@ -39,7 +39,7 @@ here.</p>
3939<blockquote>
4040<p>Code in a block quote:</p>
4141<pre><code>sub status {
42− print "working";
42+ print &quot;working&quot;;
4343}
4444</code></pre>
4545<p>A list:</p>
@@ -60,7 +60,7 @@ here.</p>
6060<blockquote>
6161<p>Example:</p>
6262<pre><code>sub status {
63− print "working";
63+ print &quot;working&quot;;
6464}
6565</code></pre>
6666</blockquote>
@@ -84,7 +84,7 @@ here.</p>
8484<pre><code>---- (should be four hyphens)
8585
8686sub status {
87− print "working";
87+ print &quot;working&quot;;
8888}
8989
9090this code block is indented by one tab
@@ -92,7 +92,7 @@ this code block is indented by one tab
9292<p>And:</p>
9393<pre><code> this code block is indented by two tabs
9494
95−These should not be escaped: \$ \\ \> \[ \{
95+These should not be escaped: \$ \\ \&gt; \[ \{
9696</code></pre>
9797<hr />
9898<h1>Lists</h1>
@@ -255,12 +255,12 @@ These should not be escaped: \$ \\ \> \[ \{
255255<div>
256256 foo</div>
257257<p>This should be a code block, though:</p>
258−<pre><code>&lt;div>
258+<pre><code>&lt;div&gt;
259259 foo
260−&lt;/div>
260+&lt;/div&gt;
261261</code></pre>
262262<p>As should this:</p>
263−<pre><code>&lt;div>foo&lt;/div>
263+<pre><code>&lt;div&gt;foo&lt;/div&gt;
264264</code></pre>
265265<p>Now, nested:</p>
266266<div>
@@ -281,12 +281,12 @@ Blah
281281 This is another comment.
282282-->
283283<p>Code block:</p>
284−<pre><code>&lt;!-- Comment -->
284+<pre><code>&lt;!-- Comment --&gt;
285285</code></pre>
286286<p>Just plain comment, with trailing spaces on the line:</p>
287287<!-- foo -->
288288<p>Code:</p>
289−<pre><code>&lt;hr />
289+<pre><code>&lt;hr /&gt;
290290</code></pre>
291291<p>Hr&rsquo;s:</p>
292292<hr>
@@ -315,7 +315,7 @@ Blah
315315<p>So is <strong><em>this</em></strong> word.</p>
316316<p><strong><em>This is strong and em.</em></strong></p>
317317<p>So is <strong><em>this</em></strong> word.</p>
318−<p>This is code: <code>></code>, <code>$</code>, <code>\</code>, <code>\$</code>, <code>&lt;html></code>.</p>
318+<p>This is code: <code>&gt;</code>, <code>$</code>, <code>\</code>, <code>\$</code>, <code>&lt;html&gt;</code>.</p>
319319<hr />
320320<h1>Smart quotes, ellipses, dashes</h1>
321321<p>&ldquo;Hello,&rdquo; said the spider. &ldquo;&lsquo;Shelob&rsquo; is my name.&rdquo;</p>
@@ -355,11 +355,11 @@ Cat &amp; 1 \\ \hline
355355<h1>Special Characters</h1>
356356<p>Here is some unicode:</p>
357357<ul>
358−<li>I hat: Î</li>
359−<li>o umlaut: ö</li>
360−<li>section: §</li>
361−<li>set membership: ∈</li>
362−<li>copyright: ©</li>
358+<li>I hat: &Icirc;</li>
359+<li>o umlaut: &ouml;</li>
360+<li>section: &sect;</li>
361+<li>set membership: &isin;</li>
362+<li>copyright: &copy;</li>
363363</ul>
364364<p>AT&amp;T has an ampersand in their name.</p>
365365<p>AT&amp;T is another way to write it.</p>
@@ -389,7 +389,7 @@ Cat &amp; 1 \\ \hline
389389<p><a href="/url/" title="title">URL and title</a>.</p>
390390<p><a href="/url/" title="title preceded by two spaces">URL and title</a>.</p>
391391<p><a href="/url/" title="title preceded by a tab">URL and title</a>.</p>
392−<p><a href="/url/" title="title with &quot;quotes&quot; in it">URL and title</a></p>
392+<p><a href="/url/" title="title with &ldquo;quotes&rdquo; in it">URL and title</a></p>
393393<p><a href="/url/" title="title with single quotes">URL and title</a></p>
394394<p><script type="text/javascript">
395395<!--
@@ -410,11 +410,11 @@ document.write('<a h'+'ref'+'="ma'+'ilto'+':'+e+'">'+'Email link'+'<\/'+'a'+'>')
410410<p>This should [not][] be a link.</p>
411411<pre><code>[not]: /url
412412</code></pre>
413−<p>Foo <a href="/url/" title="Title with &quot;quotes&quot; inside">bar</a>.</p>
414−<p>Foo <a href="/url/" title="Title with &quot;quote&quot; inside">biz</a>.</p>
413+<p>Foo <a href="/url/" title="Title with &ldquo;quotes&rdquo; inside">bar</a>.</p>
414+<p>Foo <a href="/url/" title="Title with &ldquo;quote&rdquo; inside">biz</a>.</p>
415415<h2>With ampersands</h2>
416416<p>Here&rsquo;s a <a href="http://example.com/?foo=1&amp;bar=2">link with an ampersand in the URL</a>.</p>
417−<p>Here&rsquo;s a link with an amersand in the link text: <a href="http://att.com/" title="AT&T">AT&amp;T</a>.</p>
417+<p>Here&rsquo;s a link with an amersand in the link text: <a href="http://att.com/" title="AT&amp;T">AT&amp;T</a>.</p>
418418<p>Here&rsquo;s an <a href="/script?foo=1&amp;bar=2">inline link</a>.</p>
419419<p>Here&rsquo;s an <a href="/script?foo=1&amp;bar=2">inline link in pointy braces</a>.</p>
420420<h2>Autolinks</h2>
@@ -433,8 +433,8 @@ document.write('<a h'+'ref'+'="ma'+'ilto'+':'+e+'">'+e+'<\/'+'a'+'>');
433433<blockquote>
434434<p>Blockquoted: <a href="http://example.com/">http://example.com/</a></p>
435435</blockquote>
436−<p>Auto-links should not occur here: <code>&lt;http://example.com/></code></p>
437−<pre><code>or here: &lt;http://example.com/>
436+<p>Auto-links should not occur here: <code>&lt;http://example.com/&gt;</code></p>
437+<pre><code>or here: &lt;http://example.com/&gt;
438438</code></pre>
439439<hr />
440440<h1>Images</h1>
@@ -458,7 +458,7 @@ document.write('<a h'+'ref'+'="ma'+'ilto'+':'+e+'">'+e+'<\/'+'a'+'>');
458458 <a href="#fnref1" class="footnoteBacklink" title="Jump back to footnote 1">&#8617;</a></li>
459459<li id="fn2"><p>Here&rsquo;s the long note. This one contains multiple blocks.</p>
460460<p>Subsequent blocks are indented to show that they belong to the footnote (as with list items).</p>
461−<pre><code> { &lt;code> }
461+<pre><code> { &lt;code&gt; }
462462</code></pre>
463463<p>If you want, you can indent every line, but you can also be lazy and just indent the first line of each block.</p>
464464 <a href="#fnref2" class="footnoteBacklink" title="Jump back to footnote 2">&#8617;</a></li>