@@ -52,7 +52,7 @@ import Data.Aeson (defaultOptions)
5252import Data.Aeson.TH (deriveJSON)
5353import qualified Data.ByteString as BS
5454import qualified Data.ByteString.Lazy as B
55−import Data.Char (toLower, toUpper)
55+import Data.Char (toLower, toUpper, isAscii, ord)
5656import Data.List (find, intercalate, isPrefixOf, isSuffixOf, sort)
5757import qualified Data.Map as M
5858import Data.Maybe (fromMaybe, isJust, isNothing)
@@ -513,16 +513,18 @@ convertWithOpts opts = do
513513 let htmlFormat = format `elem`
514514 ["html","html4","html5","s5","slidy",
515515 "slideous","dzslides","revealjs"]
516− handleEntities = if (htmlFormat ||
517− format == "docbook4" ||
518− format == "docbook5" ||
519− format == "docbook") && optAscii opts
520− then toEntities
521− else id
516+ escape
517+ | optAscii opts
518+ , htmlFormat || format == "docbook4" ||
519+ format == "docbook5" || format == "docbook" =
520+ toEntities
521+ | optAscii opts
522+ , format == "ms" || format == "man" = groffEscape
523+ | otherwise = id
522524 addNl = if standalone
523525 then id
524526 else (<> T.singleton '\n')
525− output <- (addNl . handleEntities) <$> f writerOptions doc
527+ output <- (addNl . escape) <$> f writerOptions doc
526528 writerFn eol outputFile =<<
527529 if optSelfContained opts && htmlFormat
528530 -- TODO not maximally efficient; change type
@@ -530,6 +532,12 @@ convertWithOpts opts = do
530532 then T.pack <$> makeSelfContained (T.unpack output)
531533 else return output
532534
535+groffEscape :: Text -> Text
536+groffEscape = T.concatMap toUchar
537+ where toUchar c
538+ | isAscii c = T.singleton c
539+ | otherwise = T.pack $ printf "\\[u%04X]" (ord c)
540+
533541type Transform = Pandoc -> Pandoc
534542
535543isTextFormat :: String -> Bool