git.iko.soy/typeable/pandoc
on master help sign in
Groff escaping changes.
efbb329John MacFarlane
MANUAL.txt+4−3
@@ -860,10 +860,11 @@ Options affecting specific writers {.options}
860
860
861: Use only ASCII characters in output. Currently supported for
861: Use only ASCII characters in output. Currently supported for
862 XML and HTML formats (which use numerical entities instead of
862 XML and HTML formats (which use numerical entities instead of
863− UTF-8 when this option is selected), groff ms and man
863+ UTF-8 when this option is selected), groff ms
864 (which use hexadecimal escapes), and to a limited degree
864 (which use hexadecimal escapes), and to a limited degree
865− for LaTeX (which uses standard commands for accented
865+ LaTeX (which uses standard commands for accented
866− characters when possible).
866+ characters when possible). Groff man output uses ASCII
867+ by default.
867
868
868`--reference-links`
869`--reference-links`
869
870
src/Text/Pandoc/GroffChar.hs+16−15
@@ -1,4 +1,5 @@
1{-# LANGUAGE NoImplicitPrelude #-}
1{-# LANGUAGE NoImplicitPrelude #-}
2+{-# LANGUAGE OverloadedStrings #-}
2{-
3{-
3Copyright (C) 2018 John MacFarlane <jgm@berkeley.edu>
4Copyright (C) 2018 John MacFarlane <jgm@berkeley.edu>
4
5
@@ -400,19 +401,19 @@ characterCodes =
400-- use like: \\[E a^ aa]
401-- use like: \\[E a^ aa]
401combiningAccents :: [(Char, String)]
402combiningAccents :: [(Char, String)]
402combiningAccents =
403combiningAccents =
403− [ ('˝' , "\\[a\"]")
404+ [ ('˝' , "a\"")
404− , ('¯', "\\[a-]")
405+ , ('¯', "a-")
405− , ('˙', "\\[a.]")
406+ , ('˙', "a.")
406− , ('^', "\\[a^]")
407+ , ('^', "a^")
407− , ('´', "\\[aa]")
408+ , ('´', "aa")
408− , ('`', "\\[ga]")
409+ , ('`', "ga")
409− , ('˘', "\\[ab]")
410+ , ('˘', "ab")
410− , ('¸', "\\[ac]")
411+ , ('¸', "ac")
411− , ('¨', "\\[ad]")
412+ , ('¨', "ad")
412− , ('ˇ', "\\[ah]")
413+ , ('ˇ', "ah")
413− , ('˚', "\\[ao]")
414+ , ('˚', "ao")
414− , ('~', "\\[a~]")
415+ , ('~', "a~")
415− , ('˛', "\\[ho]")
416+ , ('˛', "ho")
416− , ('^', "\\[ha]")
417+ , ('^', "ha")
417− , ('~', "\\[ti]")
418+ , ('~', "ti")
418 ]
419 ]
src/Text/Pandoc/Writers/Groff.hs+20−18
@@ -37,12 +37,10 @@ module Text.Pandoc.Writers.Groff (
37 , escapeChar
37 , escapeChar
38 , escapeString
38 , escapeString
39 , escapeCode
39 , escapeCode
40− , groffEscape
41 , withFontFeature
40 , withFontFeature
42 ) where
41 ) where
43import Prelude
42import Prelude
44−import qualified Data.Text as T
43+import Data.Char (ord, isAscii)
45−import Data.Char (isAscii, ord)
46import Control.Monad.State.Strict
44import Control.Monad.State.Strict
47import Data.List (intercalate)
45import Data.List (intercalate)
48import qualified Data.Map as Map
46import qualified Data.Map as Map
@@ -51,7 +49,7 @@ import Text.Pandoc.Class (PandocMonad)
51import Text.Pandoc.Definition
49import Text.Pandoc.Definition
52import Text.Pandoc.Pretty
50import Text.Pandoc.Pretty
53import Text.Printf (printf)
51import Text.Printf (printf)
54−import Text.Pandoc.GroffChar (essentialEscapes)
52+import Text.Pandoc.GroffChar (essentialEscapes, characterCodes)
55
53
56data WriterState = WriterState { stHasInlineMath :: Bool
54data WriterState = WriterState { stHasInlineMath :: Bool
57 , stFirstPara :: Bool
55 , stFirstPara :: Bool
@@ -82,31 +80,35 @@ type Note = [Block]
82
80
83type MS = StateT WriterState
81type MS = StateT WriterState
84
82
85−
86−escapeChar :: Char -> String
83+escapeChar :: Bool -> Char -> String
84+escapeChar useAscii c =
87−escapeChar c = fromMaybe [c] (Map.lookup c essentialEscapes)
85+ case Map.lookup c essentialEscapes of
86+ Just s -> s
87+ Nothing
88+ | useAscii
89+ , not (isAscii c) ->
90+ case Map.lookup c characterCodeMap of
91+ Just t -> "\\[" <> t <> "]"
92+ Nothing -> printf "\\[u%04X]" (ord c)
93+ | otherwise -> [c]
88
94
89-- | Escape special characters for groff.
95-- | Escape special characters for groff.
90−escapeString :: String -> String
96+escapeString :: Bool -> String -> String
91−escapeString = concatMap escapeChar
97+escapeString useAscii = concatMap (escapeChar useAscii)
92
98
93-- | Escape a literal (code) section for groff.
99-- | Escape a literal (code) section for groff.
94−escapeCode :: String -> String
100+escapeCode :: Bool -> String -> String
95−escapeCode = intercalate "\n" . map escapeLine . lines
101+escapeCode useAScii = intercalate "\n" . map escapeLine . lines
96 where escapeCodeChar ' ' = "\\ "
102 where escapeCodeChar ' ' = "\\ "
97 escapeCodeChar '\t' = "\\\t"
103 escapeCodeChar '\t' = "\\\t"
98− escapeCodeChar c = escapeChar c
104+ escapeCodeChar c = escapeChar useAScii c
99 escapeLine codeline =
105 escapeLine codeline =
100 case concatMap escapeCodeChar codeline of
106 case concatMap escapeCodeChar codeline of
101 a@('.':_) -> "\\&" ++ a
107 a@('.':_) -> "\\&" ++ a
102 b -> b
108 b -> b
103
109
104−-- | Escape non-ASCII characters using groff \u[..] sequences.
110+characterCodeMap :: Map.Map Char String
105−groffEscape :: T.Text -> T.Text
111+characterCodeMap = Map.fromList characterCodes
106−groffEscape = T.concatMap toUchar
107− where toUchar c
108− | isAscii c = T.singleton c
109− | otherwise = T.pack $ printf "\\[u%04X]" (ord c)
110
112
111fontChange :: PandocMonad m => MS m Doc
113fontChange :: PandocMonad m => MS m Doc
112fontChange = do
114fontChange = do
src/Text/Pandoc/Writers/Man.hs+6−6
@@ -33,6 +33,7 @@ Conversion of 'Pandoc' documents to groff man page format.
33module Text.Pandoc.Writers.Man ( writeMan) where
33module Text.Pandoc.Writers.Man ( writeMan) where
34import Prelude
34import Prelude
35import Control.Monad.State.Strict
35import Control.Monad.State.Strict
36+import Data.Char (isAscii)
36import Data.List (intersperse, stripPrefix)
37import Data.List (intersperse, stripPrefix)
37import Data.Maybe (fromMaybe)
38import Data.Maybe (fromMaybe)
38import Data.Text (Text)
39import Data.Text (Text)
@@ -93,8 +94,7 @@ pandocToMan opts (Pandoc meta blocks) = do
93 $ defField "has-tables" hasTables
94 $ defField "has-tables" hasTables
94 $ defField "hyphenate" True
95 $ defField "hyphenate" True
95 $ defField "pandoc-version" pandocVersion metadata
96 $ defField "pandoc-version" pandocVersion metadata
96− (if writerPreferAscii opts then groffEscape else id) <$>
97− case writerTemplate opts of
97+ case writerTemplate opts of
98 Nothing -> return main
98 Nothing -> return main
99 Just tpl -> renderTemplate' tpl context
99 Just tpl -> renderTemplate' tpl context
100
100
@@ -148,7 +148,7 @@ blockToMan _ (CodeBlock _ str) = return $
148 text ".IP" $$
148 text ".IP" $$
149 text ".nf" $$
149 text ".nf" $$
150 text "\\f[C]" $$
150 text "\\f[C]" $$
151− text (escapeCode str) $$
151+ text (escapeCode True str) $$
152 text "\\f[R]" $$
152 text "\\f[R]" $$
153 text ".fi"
153 text ".fi"
154blockToMan opts (BlockQuote blocks) = do
154blockToMan opts (BlockQuote blocks) = do
@@ -296,10 +296,10 @@ inlineToMan opts (Quoted DoubleQuote lst) = do
296inlineToMan opts (Cite _ lst) =
296inlineToMan opts (Cite _ lst) =
297 inlineListToMan opts lst
297 inlineListToMan opts lst
298inlineToMan _ (Code _ str) =
298inlineToMan _ (Code _ str) =
299− withFontFeature 'C' (return (text $ escapeCode str))
299+ withFontFeature 'C' (return (text $ escapeCode True str))
300inlineToMan _ (Str str@('.':_)) =
300inlineToMan _ (Str str@('.':_)) =
301− return $ afterBreak "\\&" <> text (escapeString str)
301+ return $ afterBreak "\\&" <> text (escapeString True str)
302−inlineToMan _ (Str str) = return $ text $ escapeString str
302+inlineToMan _ (Str str) = return $ text $ escapeString True str
303inlineToMan opts (Math InlineMath str) =
303inlineToMan opts (Math InlineMath str) =
304 lift (texMathToInlines InlineMath str) >>= inlineListToMan opts
304 lift (texMathToInlines InlineMath str) >>= inlineListToMan opts
305inlineToMan opts (Math DisplayMath str) = do
305inlineToMan opts (Math DisplayMath str) = do
src/Text/Pandoc/Writers/Ms.hs+28−24
@@ -69,6 +69,9 @@ writeMs :: PandocMonad m => WriterOptions -> Pandoc -> m Text
69writeMs opts document =
69writeMs opts document =
70 evalStateT (pandocToMs opts document) defaultWriterState
70 evalStateT (pandocToMs opts document) defaultWriterState
71
71
72+escString :: WriterOptions -> String -> String
73+escString opts = escapeString (writerPreferAscii opts)
74+
72-- | Return groff ms representation of document.
75-- | Return groff ms representation of document.
73pandocToMs :: PandocMonad m => WriterOptions -> Pandoc -> MS m Text
76pandocToMs :: PandocMonad m => WriterOptions -> Pandoc -> MS m Text
74pandocToMs opts (Pandoc meta blocks) = do
77pandocToMs opts (Pandoc meta blocks) = do
@@ -84,8 +87,8 @@ pandocToMs opts (Pandoc meta blocks) = do
84 body <- blockListToMs opts blocks
87 body <- blockListToMs opts blocks
85 let main = render' body
88 let main = render' body
86 hasInlineMath <- gets stHasInlineMath
89 hasInlineMath <- gets stHasInlineMath
87− let titleMeta = (escapeString . stringify) $ docTitle meta
90+ let titleMeta = (escString opts . stringify) $ docTitle meta
88− let authorsMeta = map (escapeString . stringify) $ docAuthors meta
91+ let authorsMeta = map (escString opts . stringify) $ docAuthors meta
89 hasHighlighting <- gets stHighlighting
92 hasHighlighting <- gets stHighlighting
90 let highlightingMacros = if hasHighlighting
93 let highlightingMacros = if hasHighlighting
91 then case writerHighlightStyle opts of
94 then case writerHighlightStyle opts of
@@ -101,8 +104,7 @@ pandocToMs opts (Pandoc meta blocks) = do
101 $ defField "title-meta" titleMeta
104 $ defField "title-meta" titleMeta
102 $ defField "author-meta" (intercalate "; " authorsMeta)
105 $ defField "author-meta" (intercalate "; " authorsMeta)
103 $ defField "highlighting-macros" highlightingMacros metadata
106 $ defField "highlighting-macros" highlightingMacros metadata
104− (if writerPreferAscii opts then groffEscape else id) <$>
105− case writerTemplate opts of
107+ case writerTemplate opts of
106 Nothing -> return main
108 Nothing -> return main
107 Just tpl -> renderTemplate' tpl context
109 Just tpl -> renderTemplate' tpl context
108
110
@@ -112,18 +114,18 @@ escapeUri = escapeURIString (\c -> c /= '@' && isAllowedInURI c)
112-- | Escape | character, used to mark inline math, inside math.
114-- | Escape | character, used to mark inline math, inside math.
113escapeBar :: String -> String
115escapeBar :: String -> String
114escapeBar = concatMap go
116escapeBar = concatMap go
115− where go '|' = "\\[u007C]"
117+ where go '|' = "\\[ba]"
116 go c = [c]
118 go c = [c]
117
119
118−toSmallCaps :: String -> String
120+toSmallCaps :: WriterOptions -> String -> String
119−toSmallCaps [] = []
121+toSmallCaps _ [] = []
120−toSmallCaps (c:cs)
122+toSmallCaps opts (c:cs)
121 | isLower c = let (lowers,rest) = span isLower (c:cs)
123 | isLower c = let (lowers,rest) = span isLower (c:cs)
122− in "\\s-2" ++ escapeString (map toUpper lowers) ++
124+ in "\\s-2" ++ escString opts (map toUpper lowers) ++
123− "\\s0" ++ toSmallCaps rest
125+ "\\s0" ++ toSmallCaps opts rest
124 | isUpper c = let (uppers,rest) = span isUpper (c:cs)
126 | isUpper c = let (uppers,rest) = span isUpper (c:cs)
125− in escapeString uppers ++ toSmallCaps rest
127+ in escString opts uppers ++ toSmallCaps opts rest
126− | otherwise = escapeChar c ++ toSmallCaps cs
128+ | otherwise = escapeChar (writerPreferAscii opts) c ++ toSmallCaps opts cs
127
129
128-- We split inline lists into sentences, and print one sentence per
130-- We split inline lists into sentences, and print one sentence per
129-- line. groff/troff treats the line-ending period differently.
131-- line. groff/troff treats the line-ending period differently.
@@ -160,7 +162,7 @@ blockToMs opts (Para [Image attr alt (src,_tit)])
160 _ -> empty
162 _ -> empty
161 capt <- inlineListToMs' opts alt
163 capt <- inlineListToMs' opts alt
162 return $ nowrap (text ".PSPIC -C " <>
164 return $ nowrap (text ".PSPIC -C " <>
163− doubleQuotes (text (escapeString src)) <>
165+ doubleQuotes (text (escString opts src)) <>
164 sizeAttrs) $$
166 sizeAttrs) $$
165 text ".ce 1000" $$
167 text ".ce 1000" $$
166 capt $$
168 capt $$
@@ -198,7 +200,7 @@ blockToMs opts (Header level (ident,classes,_) inlines) = do
198 (if null secnum
200 (if null secnum
199 then ""
201 then ""
200 else " ") ++
202 else " ") ++
201− escapeString (stringify inlines))
203+ escString opts (stringify inlines))
202 let backlink = nowrap (text ".pdfhref L -D " <>
204 let backlink = nowrap (text ".pdfhref L -D " <>
203 doubleQuotes (text (toAscii ident)) <> space <> text "\\") <> cr <>
205 doubleQuotes (text (toAscii ident)) <> space <> text "\\") <> cr <>
204 text " -- "
206 text " -- "
@@ -400,14 +402,14 @@ inlineToMs opts (Cite _ lst) =
400inlineToMs opts (Code attr str) = do
402inlineToMs opts (Code attr str) = do
401 hlCode <- highlightCode opts attr str
403 hlCode <- highlightCode opts attr str
402 withFontFeature 'C' (return hlCode)
404 withFontFeature 'C' (return hlCode)
403−inlineToMs _ (Str str) = do
405+inlineToMs opts (Str str) = do
404 let shim = case str of
406 let shim = case str of
405 '.':_ -> afterBreak "\\&"
407 '.':_ -> afterBreak "\\&"
406 _ -> empty
408 _ -> empty
407 smallcaps <- gets stSmallCaps
409 smallcaps <- gets stSmallCaps
408 if smallcaps
410 if smallcaps
409− then return $ shim <> text (toSmallCaps str)
411+ then return $ shim <> text (toSmallCaps opts str)
410− else return $ shim <> text (escapeString str)
412+ else return $ shim <> text (escString opts str)
411inlineToMs opts (Math InlineMath str) = do
413inlineToMs opts (Math InlineMath str) = do
412 modify $ \st -> st{ stHasInlineMath = True }
414 modify $ \st -> st{ stHasInlineMath = True }
413 res <- convertMath writeEqn InlineMath str
415 res <- convertMath writeEqn InlineMath str
@@ -449,9 +451,10 @@ inlineToMs opts (Link _ txt (src, _)) = do
449 doubleQuotes (text (escapeUri src)) <> text " -A " <>
451 doubleQuotes (text (escapeUri src)) <> text " -A " <>
450 doubleQuotes (text "\\c") <> space <> text "\\") <> cr <>
452 doubleQuotes (text "\\c") <> space <> text "\\") <> cr <>
451 text " -- " <> doubleQuotes (nowrap contents) <> cr <> text "\\&"
453 text " -- " <> doubleQuotes (nowrap contents) <> cr <> text "\\&"
452−inlineToMs _ (Image _ alternate (_, _)) =
454+inlineToMs opts (Image _ alternate (_, _)) =
453 return $ char '[' <> text "IMAGE: " <>
455 return $ char '[' <> text "IMAGE: " <>
454− text (escapeString (stringify alternate)) <> char ']'
456+ text (escString opts (stringify alternate))
457+ <> char ']'
455inlineToMs _ (Note contents) = do
458inlineToMs _ (Note contents) = do
456 modify $ \st -> st{ stNotes = contents : stNotes st }
459 modify $ \st -> st{ stNotes = contents : stNotes st }
457 return $ text "\\**"
460 return $ text "\\**"
@@ -531,20 +534,21 @@ toMacro sty toktype =
531 -- lnColor = lineNumberColor sty
534 -- lnColor = lineNumberColor sty
532 -- lnBkgColor = lineNumberBackgroundColor sty
535 -- lnBkgColor = lineNumberBackgroundColor sty
533
536
534−msFormatter :: FormatOptions -> [SourceLine] -> Doc
537+msFormatter :: WriterOptions -> FormatOptions -> [SourceLine] -> Doc
535−msFormatter _fmtopts =
538+msFormatter opts _fmtopts =
536 vcat . map fmtLine
539 vcat . map fmtLine
537 where fmtLine = hcat . map fmtToken
540 where fmtLine = hcat . map fmtToken
538 fmtToken (toktype, tok) = text "\\*" <>
541 fmtToken (toktype, tok) = text "\\*" <>
539 brackets (text (show toktype) <> text " \""
542 brackets (text (show toktype) <> text " \""
543+ <> text (escapeCode (writerPreferAscii opts)
540− <> text (escapeCode (T.unpack tok)) <> text "\"")
544+ (T.unpack tok)) <> text "\"")
541
545
542highlightCode :: PandocMonad m => WriterOptions -> Attr -> String -> MS m Doc
546highlightCode :: PandocMonad m => WriterOptions -> Attr -> String -> MS m Doc
543highlightCode opts attr str =
547highlightCode opts attr str =
544− case highlight (writerSyntaxMap opts) msFormatter attr str of
548+ case highlight (writerSyntaxMap opts) (msFormatter opts) attr str of
545 Left msg -> do
549 Left msg -> do
546 unless (null msg) $ report $ CouldNotHighlight msg
550 unless (null msg) $ report $ CouldNotHighlight msg
547− return $ text (escapeCode str)
551+ return $ text (escapeCode (writerPreferAscii opts) str)
548 Right h -> do
552 Right h -> do
549 modify (\st -> st{ stHighlighting = True })
553 modify (\st -> st{ stHighlighting = True })
550 return h
554 return h
test/command/4550.md+1−1
@@ -3,5 +3,5 @@
3A ‘simple’ example
3A ‘simple’ example
4^D
4^D
5.LP
5.LP
6−A \[oq]simple\[cq] example
6+A ‘simple’ example
7```
7```
test/command/ascii.md+2−2
@@ -17,7 +17,7 @@ pandoc -t man --ascii
17äéıå
17äéıå
18^D
18^D
19.PP
19.PP
20−\[u00E4]\[u00E9]\[u0131]\[u00E5]
20+\[:a]\['e]\[.i]\[oa]
21```
21```
22
22
23```
23```
@@ -25,7 +25,7 @@ pandoc -t ms --ascii
25äéıå
25äéıå
26^D
26^D
27.LP
27.LP
28−\[u00E4]\[u00E9]\[u0131]\[u00E5]
28+\[:a]\['e]\[.i]\[oa]
29```
29```
30
30
31```
31```
test/tables.ms+4−4
@@ -135,7 +135,7 @@ T}
135.LP
135.LP
136Multiline table with caption:
136Multiline table with caption:
137.PP
137.PP
138−Here\[cq]s the caption. It may span multiple lines.
138+Here’s the caption. It may span multiple lines.
139.TS
139.TS
140delim(@@) tab( );
140delim(@@) tab( );
141cw(10.5n) lw(9.6n) rw(11.4n) lw(24.5n).
141cw(10.5n) lw(9.6n) rw(11.4n) lw(24.5n).
@@ -165,7 +165,7 @@ row
165T} T{
165T} T{
1665.0
1665.0
167T} T{
167T} T{
168−Here\[cq]s another one.
168+Here’s another one.
169Note the blank line between rows.
169Note the blank line between rows.
170T}
170T}
171.TE
171.TE
@@ -201,7 +201,7 @@ row
201T} T{
201T} T{
2025.0
2025.0
203T} T{
203T} T{
204−Here\[cq]s another one.
204+Here’s another one.
205Note the blank line between rows.
205Note the blank line between rows.
206T}
206T}
207.TE
207.TE
@@ -261,7 +261,7 @@ row
261T} T{
261T} T{
2625.0
2625.0
263T} T{
263T} T{
264−Here\[cq]s another one.
264+Here’s another one.
265Note the blank line between rows.
265Note the blank line between rows.
266T}
266T}
267.TE
267.TE
test/writer.man+14−14
@@ -104,7 +104,7 @@ And:
104\f[C]
104\f[C]
105\ \ \ \ this\ code\ block\ is\ indented\ by\ two\ tabs
105\ \ \ \ this\ code\ block\ is\ indented\ by\ two\ tabs
106
106
107−These\ should\ not\ be\ escaped:\ \ \\$\ \\\\\ \\>\ \\[\ \\{
107+These\ should\ not\ be\ escaped:\ \ \[rs]$\ \[rs]\[rs]\ \[rs]>\ \[rs][\ \[rs]{
108\f[R]
108\f[R]
109.fi
109.fi
110.PP
110.PP
@@ -525,7 +525,7 @@ So is \f[B]\f[BI]this\f[B]\f[R] word.
525.PP
525.PP
526So is \f[B]\f[BI]this\f[B]\f[R] word.
526So is \f[B]\f[BI]this\f[B]\f[R] word.
527.PP
527.PP
528−This is code: \f[C]>\f[R], \f[C]$\f[R], \f[C]\\\f[R], \f[C]\\$\f[R],
528+This is code: \f[C]>\f[R], \f[C]$\f[R], \f[C]\[rs]\f[R], \f[C]\[rs]$\f[R],
529\f[C]<html>\f[R].
529\f[C]<html>\f[R].
530.PP
530.PP
531[STRIKEOUT:This is \f[I]strikeout\f[R].]
531[STRIKEOUT:This is \f[I]strikeout\f[R].]
@@ -563,11 +563,11 @@ Ellipses\&...and\&...and\&....
563.SH LaTeX
563.SH LaTeX
564.IP \[bu] 2
564.IP \[bu] 2
565.IP \[bu] 2
565.IP \[bu] 2
566−2 + 2 = 4
566+2\[u2005]+\[u2005]2\[u2004]=\[u2004]4
567.IP \[bu] 2
567.IP \[bu] 2
568−\f[I]x\f[R] ∈ \f[I]y\f[R]
568+\f[I]x\f[R]\[u2004]\[mo]\[u2004]\f[I]y\f[R]
569.IP \[bu] 2
569.IP \[bu] 2
570−\f[I]α\f[R] ∧ \f[I]ω\f[R]
570+\f[I]\[*a]\f[R]\[u2005]\[AN]\[u2005]\f[I]\[*w]\f[R]
571.IP \[bu] 2
571.IP \[bu] 2
572223
572223
573.IP \[bu] 2
573.IP \[bu] 2
@@ -575,11 +575,11 @@ Ellipses\&...and\&...and\&....
575.IP \[bu] 2
575.IP \[bu] 2
576Here\[cq]s some display math:
576Here\[cq]s some display math:
577.RS
577.RS
578−$$\\frac{d}{dx}f(x)=\\lim_{h\\to 0}\\frac{f(x+h)-f(x)}{h}$$
578+$$\[rs]frac{d}{dx}f(x)=\[rs]lim_{h\[rs]to 0}\[rs]frac{f(x+h)-f(x)}{h}$$
579.RE
579.RE
580.IP \[bu] 2
580.IP \[bu] 2
581Here\[cq]s one that has a line break in it:
581Here\[cq]s one that has a line break in it:
582−\f[I]α\f[R] + \f[I]ω\f[R] × \f[I]x\f[R]^2^.
582+\f[I]\[*a]\f[R]\[u2005]+\[u2005]\f[I]\[*w]\f[R]\[u2005]\[tmu]\[u2005]\f[I]x\f[R]^2^.
583.PP
583.PP
584These shouldn\[cq]t be math:
584These shouldn\[cq]t be math:
585.IP \[bu] 2
585.IP \[bu] 2
@@ -600,15 +600,15 @@ Here\[cq]s a LaTeX table:
600.PP
600.PP
601Here is some unicode:
601Here is some unicode:
602.IP \[bu] 2
602.IP \[bu] 2
603−I hat: Î
603+I hat: \[^I]
604.IP \[bu] 2
604.IP \[bu] 2
605−o umlaut: ö
605+o umlaut: \[:o]
606.IP \[bu] 2
606.IP \[bu] 2
607−section: §
607+section: \[sc]
608.IP \[bu] 2
608.IP \[bu] 2
609−set membership: ∈
609+set membership: \[mo]
610.IP \[bu] 2
610.IP \[bu] 2
611−copyright: ©
611+copyright: \[co]
612.PP
612.PP
613AT&T has an ampersand in their name.
613AT&T has an ampersand in their name.
614.PP
614.PP
@@ -620,9 +620,9 @@ This & that.
620.PP
620.PP
6216 > 5.
6216 > 5.
622.PP
622.PP
623−Backslash: \\
623+Backslash: \[rs]
624.PP
624.PP
625−Backtick: \`
625+Backtick: \[ga]
626.PP
626.PP
627Asterisk: *
627Asterisk: *
628.PP
628.PP
test/writer.ms+23−23
@@ -75,7 +75,7 @@ July 17, 2006
75.1C
75.1C
76.LP
76.LP
77This is a set of tests for pandoc.
77This is a set of tests for pandoc.
78−Most of them are adapted from John Gruber\[cq]s markdown test suite.
78+Most of them are adapted from John Gruber’s markdown test suite.
79.HLINE
79.HLINE
80.SH 1
80.SH 1
81Headers
81Headers
@@ -126,7 +126,7 @@ Paragraphs
126.pdfhref O 1 "Paragraphs"
126.pdfhref O 1 "Paragraphs"
127.pdfhref M "paragraphs"
127.pdfhref M "paragraphs"
128.LP
128.LP
129−Here\[cq]s a regular paragraph.
129+Here’s a regular paragraph.
130.PP
130.PP
131In Markdown 1.0.0 and earlier.
131In Markdown 1.0.0 and earlier.
132Version 8.
132Version 8.
@@ -134,7 +134,7 @@ This line turns into a list item.
134Because a hard-wrapped line in the middle of a paragraph looked like a list
134Because a hard-wrapped line in the middle of a paragraph looked like a list
135item.
135item.
136.PP
136.PP
137−Here\[cq]s one with a bullet.
137+Here’s one with a bullet.
138* criminey.
138* criminey.
139.PP
139.PP
140There should be a hard line break
140There should be a hard line break
@@ -210,7 +210,7 @@ And:
210\f[C]
210\f[C]
211\ \ \ \ this\ code\ block\ is\ indented\ by\ two\ tabs
211\ \ \ \ this\ code\ block\ is\ indented\ by\ two\ tabs
212
212
213−These\ should\ not\ be\ escaped:\ \ \\$\ \\\\\ \\>\ \\[\ \\{
213+These\ should\ not\ be\ escaped:\ \ \[rs]$\ \[rs]\[rs]\ \[rs]>\ \[rs][\ \[rs]{
214\f[]
214\f[]
215.fi
215.fi
216.HLINE
216.HLINE
@@ -314,7 +314,7 @@ Item 1, graf one.
314.PP
314.PP
315Item 1.
315Item 1.
316graf two.
316graf two.
317−The quick brown fox jumped over the lazy dog\[cq]s back.
317+The quick brown fox jumped over the lazy dog’s back.
318.RE
318.RE
319.IP " 2." 4
319.IP " 2." 4
320Item 2.
320Item 2.
@@ -335,7 +335,7 @@ Tab
335.RE
335.RE
336.RE
336.RE
337.LP
337.LP
338−Here\[cq]s another:
338+Here’s another:
339.IP " 1." 4
339.IP " 1." 4
340First
340First
341.IP " 2." 4
341.IP " 2." 4
@@ -570,7 +570,7 @@ Interpreted markdown in a table:
570This is \f[I]emphasized\f[R]
570This is \f[I]emphasized\f[R]
571And this is \f[B]strong\f[R]
571And this is \f[B]strong\f[R]
572.PP
572.PP
573−Here\[cq]s a simple block:
573+Here’s a simple block:
574.LP
574.LP
575foo
575foo
576.LP
576.LP
@@ -617,7 +617,7 @@ Code:
617\f[]
617\f[]
618.fi
618.fi
619.LP
619.LP
620−Hr\[cq]s:
620+Hr’s:
621.HLINE
621.HLINE
622.SH 1
622.SH 1
623Inline Markup
623Inline Markup
@@ -641,7 +641,7 @@ So is \f[B]\f[BI]this\f[B]\f[R] word.
641.PP
641.PP
642So is \f[B]\f[BI]this\f[B]\f[R] word.
642So is \f[B]\f[BI]this\f[B]\f[R] word.
643.PP
643.PP
644−This is code: \f[C]>\f[R], \f[C]$\f[R], \f[C]\\\f[R], \f[C]\\$\f[R],
644+This is code: \f[C]>\f[R], \f[C]$\f[R], \f[C]\[rs]\f[R], \f[C]\[rs]$\f[R],
645\f[C]<html>\f[R].
645\f[C]<html>\f[R].
646.PP
646.PP
647\m[strikecolor]This is \f[I]strikeout\f[R].\m[]
647\m[strikecolor]This is \f[I]strikeout\f[R].\m[]
@@ -666,16 +666,16 @@ Smart quotes, ellipses, dashes
666`Oak,' `elm,' and `beech' are names of trees.
666`Oak,' `elm,' and `beech' are names of trees.
667So is `pine.'
667So is `pine.'
668.PP
668.PP
669−`He said, \[lq]I want to go.\[rq]' Were you alive in the 70\[cq]s?
669+`He said, \[lq]I want to go.\[rq]' Were you alive in the 70’s?
670.PP
670.PP
671Here is some quoted `\f[C]code\f[R]' and a \[lq]\c
671Here is some quoted `\f[C]code\f[R]' and a \[lq]\c
672.pdfhref W -D "http://example.com/?foo=1&bar=2" -A "\c" \
672.pdfhref W -D "http://example.com/?foo=1&bar=2" -A "\c" \
673 -- "quoted link"
673 -- "quoted link"
674\&\[rq].
674\&\[rq].
675.PP
675.PP
676−Some dashes: one\[em]two \[em] three\[em]four \[em] five.
676+Some dashes: one—two — three—four — five.
677.PP
677.PP
678−Dashes between numbers: 5\[en]7, 255\[en]66, 1987\[en]1999.
678+Dashes between numbers: 5–7, 255–66, 1987–1999.
679.PP
679.PP
680Ellipses\&...and\&...and\&....
680Ellipses\&...and\&...and\&....
681.HLINE
681.HLINE
@@ -695,14 +695,14 @@ LaTeX
695.IP \[bu] 3
695.IP \[bu] 3
696@p@-Tree
696@p@-Tree
697.IP \[bu] 3
697.IP \[bu] 3
698−Here\[cq]s some display math:
698+Here’s some display math:
699.EQ
699.EQ
700d over {d x} f ( x ) = lim sub {h -> 0} {f ( x + h ) \[u2212] f ( x )} over h
700d over {d x} f ( x ) = lim sub {h -> 0} {f ( x + h ) \[u2212] f ( x )} over h
701.EN
701.EN
702.IP \[bu] 3
702.IP \[bu] 3
703−Here\[cq]s one that has a line break in it: @alpha + omega times x sup 2@.
703+Here’s one that has a line break in it: @alpha + omega times x sup 2@.
704.LP
704.LP
705−These shouldn\[cq]t be math:
705+These shouldn’t be math:
706.IP \[bu] 3
706.IP \[bu] 3
707To get the famous equation, write \f[C]$e\ =\ mc\[ha]2$\f[R].
707To get the famous equation, write \f[C]$e\ =\ mc\[ha]2$\f[R].
708.IP \[bu] 3
708.IP \[bu] 3
@@ -714,7 +714,7 @@ Shoes ($20) and socks ($5).
714.IP \[bu] 3
714.IP \[bu] 3
715Escaped \f[C]$\f[R]: $73 \f[I]this should be emphasized\f[R] 23$.
715Escaped \f[C]$\f[R]: $73 \f[I]this should be emphasized\f[R] 23$.
716.LP
716.LP
717−Here\[cq]s a LaTeX table:
717+Here’s a LaTeX table:
718.HLINE
718.HLINE
719.SH 1
719.SH 1
720Special Characters
720Special Characters
@@ -743,9 +743,9 @@ This & that.
743.PP
743.PP
7446 > 5.
7446 > 5.
745.PP
745.PP
746−Backslash: \\
746+Backslash: \[rs]
747.PP
747.PP
748−Backtick: \`
748+Backtick: \[ga]
749.PP
749.PP
750Asterisk: *
750Asterisk: *
751.PP
751.PP
@@ -885,22 +885,22 @@ With ampersands
885.pdfhref O 2 "With ampersands"
885.pdfhref O 2 "With ampersands"
886.pdfhref M "with-ampersands"
886.pdfhref M "with-ampersands"
887.LP
887.LP
888−Here\[cq]s a \c
888+Here’s a \c
889.pdfhref W -D "http://example.com/?foo=1&bar=2" -A "\c" \
889.pdfhref W -D "http://example.com/?foo=1&bar=2" -A "\c" \
890 -- "link with an ampersand in the URL"
890 -- "link with an ampersand in the URL"
891\&.
891\&.
892.PP
892.PP
893−Here\[cq]s a link with an amersand in the link text: \c
893+Here’s a link with an amersand in the link text: \c
894.pdfhref W -D "http://att.com/" -A "\c" \
894.pdfhref W -D "http://att.com/" -A "\c" \
895 -- "AT&T"
895 -- "AT&T"
896\&.
896\&.
897.PP
897.PP
898−Here\[cq]s an \c
898+Here’s an \c
899.pdfhref W -D "/script?foo=1&bar=2" -A "\c" \
899.pdfhref W -D "/script?foo=1&bar=2" -A "\c" \
900 -- "inline link"
900 -- "inline link"
901\&.
901\&.
902.PP
902.PP
903−Here\[cq]s an \c
903+Here’s an \c
904.pdfhref W -D "/script?foo=1&bar=2" -A "\c" \
904.pdfhref W -D "/script?foo=1&bar=2" -A "\c" \
905 -- "inline link in pointy braces"
905 -- "inline link in pointy braces"
906\&.
906\&.
@@ -967,7 +967,7 @@ It need not be placed at the end of the document.
967.FE
967.FE
968and another.\**
968and another.\**
969.FS
969.FS
970−Here\[cq]s the long note.
970+Here’s the long note.
971This one contains multiple blocks.
971This one contains multiple blocks.
972.PP
972.PP
973Subsequent blocks are indented to show that they belong to the footnote (as
973Subsequent blocks are indented to show that they belong to the footnote (as