@@ -36,6 +36,7 @@ module Text.Pandoc.Writers.CommonMark (writeCommonMark) where
3636import Prelude
3737import CMarkGFM
3838import Control.Monad.State.Strict (State, get, modify, runState)
39+import Data.Char (isAscii)
3940import Data.Foldable (foldrM)
4041import Data.List (transpose)
4142import Data.Monoid (Any (..))
@@ -50,6 +51,7 @@ import Text.Pandoc.Templates (renderTemplate')
5051import Text.Pandoc.Walk (query, walk, walkM)
5152import Text.Pandoc.Writers.HTML (writeHtml5String, tagWithAttributes)
5253import Text.Pandoc.Writers.Shared
54+import Text.Pandoc.XML (toHtml5Entities)
5355
5456-- | Convert Pandoc to CommonMark.
5557writeCommonMark :: PandocMonad m => WriterOptions -> Pandoc -> m Text
@@ -238,7 +240,7 @@ inlinesToNodes :: WriterOptions -> [Inline] -> [Node]
238240inlinesToNodes opts = foldr (inlineToNodes opts) []
239241
240242inlineToNodes :: WriterOptions -> Inline -> [Node] -> [Node]
241−inlineToNodes opts (Str s) = (node (TEXT (T.pack s')) [] :)
243+inlineToNodes opts (Str s) = stringToNodes opts s'
242244 where s' = if isEnabled Ext_smart opts
243245 then unsmartify opts s
244246 else s
@@ -336,6 +338,21 @@ inlineToNodes opts (Cite _ ils) = (inlinesToNodes opts ils ++)
336338inlineToNodes _ (Note _) = id -- should not occur
337339-- we remove Note elements in preprocessing
338340
341+stringToNodes :: WriterOptions -> String -> [Node] -> [Node]
342+stringToNodes opts s
343+ | not (writerPreferAscii opts) = (node (TEXT (T.pack s)) [] :)
344+ | otherwise = step s
345+ where
346+ step input =
347+ let (ascii, rest) = span isAscii input
348+ this = node (TEXT (T.pack ascii)) []
349+ nodes = case rest of
350+ [] -> id
351+ (nonAscii : rest') ->
352+ let escaped = toHtml5Entities (T.singleton nonAscii)
353+ in (node (HTML_INLINE escaped) [] :) . step rest'
354+ in (this :) . nodes
355+
339356toSubscriptInline :: Inline -> Maybe Inline
340357toSubscriptInline Space = Just Space
341358toSubscriptInline (Span attr ils) = Span attr <$> traverse toSubscriptInline ils