@@ -16,7 +16,10 @@ Conversion of 'Pandoc' documents to markdown-formatted plain text.
17Markdown: <http://daringfireball.net/projects/markdown/>
17Markdown: <http://daringfireball.net/projects/markdown/>
19−module Text.Pandoc.Writers.Markdown (writeMarkdown, writePlain) where
19+module Text.Pandoc.Writers.Markdown (
20import Control.Monad.Reader
23import Control.Monad.Reader
21import Control.Monad.State.Strict
24import Control.Monad.State.Strict
22import Data.Char (isAlphaNum)
25import Data.Char (isAlphaNum)
@@ -55,15 +58,21 @@ evalMD :: PandocMonad m => MD m a -> WriterEnv -> WriterState -> m a
55evalMD md env st = evalStateT (runReaderT md env) st
58evalMD md env st = evalStateT (runReaderT md env) st
57data WriterEnv = WriterEnv { envInList :: Bool
60data WriterEnv = WriterEnv { envInList :: Bool
58− , envPlain :: Bool
61+ , envVariant :: MarkdownVariant
59 , envRefShortcutable :: Bool
62 , envRefShortcutable :: Bool
60 , envBlockLevel :: Int
63 , envBlockLevel :: Int
61 , envEscapeSpaces :: Bool
64 , envEscapeSpaces :: Bool
67+data MarkdownVariant =
64instance Default WriterEnv
73instance Default WriterEnv
65− where def = WriterEnv { envInList = False
74+ where def = WriterEnv { envInList = False
66− , envPlain = False
75+ , envVariant = Markdown
67 , envRefShortcutable = True
76 , envRefShortcutable = True
68 , envBlockLevel = 0
77 , envBlockLevel = 0
69 , envEscapeSpaces = False
78 , envEscapeSpaces = False
@@ -102,7 +111,12 @@ writeMarkdown opts document =
102-- pictures, or inline formatting).
111-- pictures, or inline formatting).
103writePlain :: PandocMonad m => WriterOptions -> Pandoc -> m Text
112writePlain :: PandocMonad m => WriterOptions -> Pandoc -> m Text
104writePlain opts document =
113writePlain opts document =
105− evalMD (pandocToMarkdown opts document) def{ envPlain = True } def
114+ evalMD (pandocToMarkdown opts document) def{ envVariant = PlainText } def
116+-- | Convert Pandoc to Commonmark.
117+writeCommonMark :: PandocMonad m => WriterOptions -> Pandoc -> m Text
118+writeCommonMark opts document =
119+ evalMD (pandocToMarkdown opts document) def{ envVariant = Commonmark } def
107pandocTitleBlock :: Doc Text -> [Doc Text] -> Doc Text -> Doc Text
121pandocTitleBlock :: Doc Text -> [Doc Text] -> Doc Text -> Doc Text
108pandocTitleBlock tit auths dat =
122pandocTitleBlock tit auths dat =
@@ -187,7 +201,7 @@ pandocToMarkdown opts (Pandoc meta blocks) = do
187 let colwidth = if writerWrapText opts == WrapAuto
201 let colwidth = if writerWrapText opts == WrapAuto
188 then Just $ writerColumns opts
202 then Just $ writerColumns opts
189 else Nothing
203 else Nothing
190− isPlain <- asks envPlain
204+ variant <- asks envVariant
191 metadata <- metaToContext'
205 metadata <- metaToContext'
192 (blockListToMarkdown opts)
206 (blockListToMarkdown opts)
193 (inlineListToMarkdown opts)
207 (inlineListToMarkdown opts)
@@ -196,7 +210,7 @@ pandocToMarkdown opts (Pandoc meta blocks) = do
196 let authors' = fromMaybe [] $ getField "author" metadata
210 let authors' = fromMaybe [] $ getField "author" metadata
197 let date' = fromMaybe empty $ getField "date" metadata
211 let date' = fromMaybe empty $ getField "date" metadata
198 let titleblock = case writerTemplate opts of
212 let titleblock = case writerTemplate opts of
199− Just _ | isPlain ->
213+ Just _ | variant == PlainText ->
200 plainTitleBlock title' authors' date'
214 plainTitleBlock title' authors' date'
201 | isEnabled Ext_yaml_metadata_block opts ->
215 | isEnabled Ext_yaml_metadata_block opts ->
202 yamlMetadataBlock metadata
216 yamlMetadataBlock metadata
@@ -422,7 +436,7 @@ blockToMarkdown' opts (Div attrs ils) = do
422 attrs' = (id',classes',("markdown","1"):kvs')
436 attrs' = (id',classes',("markdown","1"):kvs')
423blockToMarkdown' opts (Plain inlines) = do
437blockToMarkdown' opts (Plain inlines) = do
424 -- escape if para starts with ordered list marker
438 -- escape if para starts with ordered list marker
425− isPlain <- asks envPlain
439+ variant <- asks envVariant
426 let escapeMarker = T.concatMap $ \x -> if x `elemText` ".()"
440 let escapeMarker = T.concatMap $ \x -> if x `elemText` ".()"
427 then T.pack ['\\', x]
441 then T.pack ['\\', x]
428 else T.singleton x
442 else T.singleton x
@@ -430,17 +444,15 @@ blockToMarkdown' opts (Plain inlines) = do
430 startsWithSpace (SoftBreak:_) = True
444 startsWithSpace (SoftBreak:_) = True
431 startsWithSpace _ = False
445 startsWithSpace _ = False
432 let inlines' =
446 let inlines' =
433− if isPlain
447+ if variant == PlainText
434 then inlines
448 then inlines
435 else case inlines of
449 else case inlines of
436 (Str t:ys)
450 (Str t:ys)
438− , (null ys || startsWithSpace ys)
451+ | (null ys || startsWithSpace ys)
439 , beginsWithOrderedListMarker t
452 , beginsWithOrderedListMarker t
440 -> RawInline (Format "markdown") (escapeMarker t):ys
453 -> RawInline (Format "markdown") (escapeMarker t):ys
441 (Str t:_)
454 (Str t:_)
443− , t == "+" || t == "-" ||
455+ | t == "+" || t == "-" ||
444 (t == "%" && isEnabled Ext_pandoc_title_block opts &&
456 (t == "%" && isEnabled Ext_pandoc_title_block opts &&
445 isEnabled Ext_all_symbols_escapable opts)
457 isEnabled Ext_all_symbols_escapable opts)
446 -> RawInline (Format "markdown") "\\" : inlines
458 -> RawInline (Format "markdown") "\\" : inlines
@@ -465,16 +477,16 @@ blockToMarkdown' opts (LineBlock lns) =
465 return $ (vcat $ map (hang 2 (literal "| ")) mdLines) <> blankline
477 return $ (vcat $ map (hang 2 (literal "| ")) mdLines) <> blankline
466 else blockToMarkdown opts $ linesToPara lns
478 else blockToMarkdown opts $ linesToPara lns
467blockToMarkdown' opts b@(RawBlock f str) = do
479blockToMarkdown' opts b@(RawBlock f str) = do
468− plain <- asks envPlain
480+ variant <- asks envVariant
469 let Format fmt = f
481 let Format fmt = f
470 let rawAttribBlock = return $
482 let rawAttribBlock = return $
471 (literal "```{=" <> literal fmt <> "}") $$
483 (literal "```{=" <> literal fmt <> "}") $$
472 literal str $$
484 literal str $$
473 (literal "```" <> literal "\n")
485 (literal "```" <> literal "\n")
474 let renderEmpty = mempty <$ report (BlockNotRendered b)
486 let renderEmpty = mempty <$ report (BlockNotRendered b)
475− case () of
487+ case variant of
476− _ | plain -> renderEmpty
488+ PlainText -> renderEmpty
477− | isEnabled Ext_raw_attribute opts -> rawAttribBlock
489+ _ | isEnabled Ext_raw_attribute opts -> rawAttribBlock
478 | f `elem` ["markdown", "markdown_github", "markdown_phpextra",
490 | f `elem` ["markdown", "markdown_github", "markdown_phpextra",
479 "markdown_mmd", "markdown_strict"] ->
491 "markdown_mmd", "markdown_strict"] ->
480 return $ literal str <> literal "\n"
492 return $ literal str <> literal "\n"
@@ -503,7 +515,7 @@ blockToMarkdown' opts (Header level attr inlines) = do
503 then notesAndRefs opts
515 then notesAndRefs opts
504 else return empty
516 else return empty
506− plain <- asks envPlain
518+ variant <- asks envVariant
507 -- we calculate the id that would be used by auto_identifiers
519 -- we calculate the id that would be used by auto_identifiers
508 -- so we know whether to print an explicit identifier
520 -- so we know whether to print an explicit identifier
509 ids <- gets stIds
521 ids <- gets stIds
@@ -521,19 +533,20 @@ blockToMarkdown' opts (Header level attr inlines) = do
521 contents <- inlineListToMarkdown opts $
533 contents <- inlineListToMarkdown opts $
522 -- ensure no newlines; see #3736
534 -- ensure no newlines; see #3736
523 walk lineBreakToSpace $
535 walk lineBreakToSpace $
536+ if level == 1 && variant == PlainText &&
524− if level == 1 && plain && isEnabled Ext_gutenberg opts
537+ isEnabled Ext_gutenberg opts
525− then capitalize inlines
538+ then capitalize inlines
526− else inlines
539+ else inlines
527 let setext = writerSetextHeaders opts
540 let setext = writerSetextHeaders opts
528 hdr = nowrap $ case level of
541 hdr = nowrap $ case level of
529− 1 | plain ->
542+ 1 | variant == PlainText ->
530 if isEnabled Ext_gutenberg opts
543 if isEnabled Ext_gutenberg opts
531 then blanklines 3 <> contents <> blanklines 2
544 then blanklines 3 <> contents <> blanklines 2
532 else contents <> blankline
545 else contents <> blankline
533 | setext ->
546 | setext ->
534 contents <> attr' <> cr <> literal (T.replicate (offset contents) "=") <>
547 contents <> attr' <> cr <> literal (T.replicate (offset contents) "=") <>
535 blankline
548 blankline
536− 2 | plain ->
549+ 2 | variant == PlainText ->
537 if isEnabled Ext_gutenberg opts
550 if isEnabled Ext_gutenberg opts
538 then blanklines 2 <> contents <> blankline
551 then blanklines 2 <> contents <> blankline
539 else contents <> blankline
552 else contents <> blankline
@@ -541,7 +554,7 @@ blockToMarkdown' opts (Header level attr inlines) = do
541 contents <> attr' <> cr <> literal (T.replicate (offset contents) "-") <>
554 contents <> attr' <> cr <> literal (T.replicate (offset contents) "-") <>
542 blankline
555 blankline
543 -- ghc interprets '#' characters in column 1 as linenum specifiers.
556 -- ghc interprets '#' characters in column 1 as linenum specifiers.
544− _ | plain || isEnabled Ext_literate_haskell opts ->
557+ _ | variant == PlainText || isEnabled Ext_literate_haskell opts ->
545 contents <> blankline
558 contents <> blankline
546 _ -> literal (T.replicate level "#") <> space <> contents <> attr' <> blankline
559 _ -> literal (T.replicate level "#") <> space <> contents <> attr' <> blankline
@@ -571,12 +584,12 @@ blockToMarkdown' opts (CodeBlock attribs str) = return $
571 (_,(cls:_),_) -> " " <> literal cls
584 (_,(cls:_),_) -> " " <> literal cls
572 _ -> empty
585 _ -> empty
573blockToMarkdown' opts (BlockQuote blocks) = do
586blockToMarkdown' opts (BlockQuote blocks) = do
574− plain <- asks envPlain
587+ variant <- asks envVariant
575 -- if we're writing literate haskell, put a space before the bird tracks
588 -- if we're writing literate haskell, put a space before the bird tracks
576 -- so they won't be interpreted as lhs...
589 -- so they won't be interpreted as lhs...
577 let leader = if isEnabled Ext_literate_haskell opts
590 let leader = if isEnabled Ext_literate_haskell opts
578 then " > "
591 then " > "
579− else if plain then " " else "> "
592+ else if variant == PlainText then " " else "> "
580 contents <- blockListToMarkdown opts blocks
593 contents <- blockListToMarkdown opts blocks
581 return $ (prefixed leader contents) <> blankline
594 return $ (prefixed leader contents) <> blankline
582blockToMarkdown' opts t@(Table _ blkCapt specs thead tbody tfoot) = do
595blockToMarkdown' opts t@(Table _ blkCapt specs thead tbody tfoot) = do
@@ -584,9 +597,12 @@ blockToMarkdown' opts t@(Table _ blkCapt specs thead tbody tfoot) = do
584 let numcols = maximum (length aligns : length widths :
597 let numcols = maximum (length aligns : length widths :
585 map length (headers:rows))
598 map length (headers:rows))
586 caption' <- inlineListToMarkdown opts caption
599 caption' <- inlineListToMarkdown opts caption
587− let caption'' = if null caption || not (isEnabled Ext_table_captions opts)
600+ let caption'' = if null caption
588 then blankline
601 then blankline
603+ if isEnabled Ext_table_captions opts
589− else blankline $$ (": " <> caption') $$ blankline
604+ then blankline $$ (": " <> caption') $$ blankline
605+ else blankline $$ caption' $$ blankline
590 let hasSimpleCells = onlySimpleTableCells $ headers : rows
606 let hasSimpleCells = onlySimpleTableCells $ headers : rows
591 let isSimple = hasSimpleCells && all (==0) widths
607 let isSimple = hasSimpleCells && all (==0) widths
592 let isPlainBlock (Plain _) = True
608 let isPlainBlock (Plain _) = True
@@ -806,8 +822,8 @@ definitionListItemToMarkdown opts (label, defs) = do
806 if isEnabled Ext_definition_lists opts
822 if isEnabled Ext_definition_lists opts
808 let tabStop = writerTabStop opts
824 let tabStop = writerTabStop opts
809− isPlain <- asks envPlain
825+ variant <- asks envVariant
810− let leader = if isPlain then " " else ": "
826+ let leader = if variant == PlainText then " " else ": "
811 let sps = case writerTabStop opts - 3 of
827 let sps = case writerTabStop opts - 3 of
812 n | n > 0 -> literal $ T.replicate n " "
828 n | n > 0 -> literal $ T.replicate n " "
813 _ -> literal " "
829 _ -> literal " "
@@ -836,7 +852,7 @@ blockListToMarkdown :: PandocMonad m
836 -> MD m (Doc Text)
852 -> MD m (Doc Text)
837blockListToMarkdown opts blocks = do
853blockListToMarkdown opts blocks = do
838 inlist <- asks envInList
854 inlist <- asks envInList
839− isPlain <- asks envPlain
855+ variant <- asks envVariant
840 -- a) insert comment between list and indented code block, or the
856 -- a) insert comment between list and indented code block, or the
841 -- code block will be treated as a list continuation paragraph
857 -- code block will be treated as a list continuation paragraph
842 -- b) change Plain to Para unless it's followed by a RawBlock
858 -- b) change Plain to Para unless it's followed by a RawBlock
@@ -870,7 +886,7 @@ blockListToMarkdown opts blocks = do
870 isListBlock (OrderedList _ _) = True
886 isListBlock (OrderedList _ _) = True
871 isListBlock (DefinitionList _) = True
887 isListBlock (DefinitionList _) = True
872 isListBlock _ = False
888 isListBlock _ = False
873− commentSep = if isPlain
889+ commentSep = if variant == PlainText
874 then Null
890 then Null
875 else if isEnabled Ext_raw_html opts
891 else if isEnabled Ext_raw_html opts
876 then RawBlock "html" "<!-- -->\n"
892 then RawBlock "html" "<!-- -->\n"
@@ -1022,11 +1038,11 @@ inlineToMarkdown opts (Span ("",["emoji"],kvs) [Str s]) =
1022 return $ ":" <> literal emojiname <> ":"
1038 return $ ":" <> literal emojiname <> ":"
1023 _ -> inlineToMarkdown opts (Str s)
1039 _ -> inlineToMarkdown opts (Str s)
1024inlineToMarkdown opts (Span attrs ils) = do
1040inlineToMarkdown opts (Span attrs ils) = do
1025− plain <- asks envPlain
1041+ variant <- asks envVariant
1026 contents <- inlineListToMarkdown opts ils
1042 contents <- inlineListToMarkdown opts ils
1027− return $ case plain of
1043+ return $ case variant of
1028− True -> contents
1044+ PlainText -> contents
1029− False | attrs == nullAttr -> contents
1045+ _ | attrs == nullAttr -> contents
1030 | isEnabled Ext_bracketed_spans opts ->
1046 | isEnabled Ext_bracketed_spans opts ->
1031 let attrs' = if attrs /= nullAttr
1047 let attrs' = if attrs /= nullAttr
1032 then attrsToMarkdown attrs
1048 then attrsToMarkdown attrs
@@ -1038,20 +1054,20 @@ inlineToMarkdown opts (Span attrs ils) = do
1038 | otherwise -> contents
1054 | otherwise -> contents
1039inlineToMarkdown _ (Emph []) = return empty
1055inlineToMarkdown _ (Emph []) = return empty
1040inlineToMarkdown opts (Emph lst) = do
1056inlineToMarkdown opts (Emph lst) = do
1041− plain <- asks envPlain
1057+ variant <- asks envVariant
1042 contents <- inlineListToMarkdown opts lst
1058 contents <- inlineListToMarkdown opts lst
1043− return $ if plain
1059+ return $ case variant of
1044− then if isEnabled Ext_gutenberg opts
1061+ | isEnabled Ext_gutenberg opts -> "_" <> contents <> "_"
1045− then "_" <> contents <> "_"
1046− else contents
1062+ | otherwise -> contents
1047− else "*" <> contents <> "*"
1063+ _ -> "*" <> contents <> "*"
1048inlineToMarkdown _ (Underline []) = return empty
1064inlineToMarkdown _ (Underline []) = return empty
1049inlineToMarkdown opts (Underline lst) = do
1065inlineToMarkdown opts (Underline lst) = do
1050− plain <- asks envPlain
1066+ variant <- asks envVariant
1051 contents <- inlineListToMarkdown opts lst
1067 contents <- inlineListToMarkdown opts lst
1052− case plain of
1068+ case variant of
1053− True -> return contents
1069+ PlainText -> return contents
1054− False | isEnabled Ext_bracketed_spans opts ->
1070+ _ | isEnabled Ext_bracketed_spans opts ->
1055 return $ "[" <> contents <> "]" <> "{.ul}"
1071 return $ "[" <> contents <> "]" <> "{.ul}"
1056 | isEnabled Ext_native_spans opts ->
1072 | isEnabled Ext_native_spans opts ->
1057 return $ tagWithAttrs "span" ("", ["underline"], [])
1073 return $ tagWithAttrs "span" ("", ["underline"], [])
@@ -1062,13 +1078,14 @@ inlineToMarkdown opts (Underline lst) = do
1062 | otherwise -> inlineToMarkdown opts (Emph lst)
1078 | otherwise -> inlineToMarkdown opts (Emph lst)
1063inlineToMarkdown _ (Strong []) = return empty
1079inlineToMarkdown _ (Strong []) = return empty
1064inlineToMarkdown opts (Strong lst) = do
1080inlineToMarkdown opts (Strong lst) = do
1065− plain <- asks envPlain
1081+ variant <- asks envVariant
1066− if plain
1082+ case variant of
1067− then inlineListToMarkdown opts $
1084+ inlineListToMarkdown opts $
1068− if isEnabled Ext_gutenberg opts
1085+ if isEnabled Ext_gutenberg opts
1069− then capitalize lst
1086+ then capitalize lst
1070− else lst
1087+ else lst
1071− else do
1088+ _ -> do
1072 contents <- inlineListToMarkdown opts lst
1089 contents <- inlineListToMarkdown opts lst
1073 return $ "**" <> contents <> "**"
1090 return $ "**" <> contents <> "**"
1074inlineToMarkdown _ (Strikeout []) = return empty
1091inlineToMarkdown _ (Strikeout []) = return empty
@@ -1081,33 +1098,43 @@ inlineToMarkdown opts (Strikeout lst) = do
1081 else contents
1098 else contents
1082inlineToMarkdown _ (Superscript []) = return empty
1099inlineToMarkdown _ (Superscript []) = return empty
1083inlineToMarkdown opts (Superscript lst) =
1100inlineToMarkdown opts (Superscript lst) =
1084− local (\env -> env {envEscapeSpaces = True}) $ do
1101+ local (\env -> env {envEscapeSpaces = (envVariant env == Markdown)}) $ do
1085 contents <- inlineListToMarkdown opts lst
1102 contents <- inlineListToMarkdown opts lst
1086− return $ if isEnabled Ext_superscript opts
1103+ if isEnabled Ext_superscript opts
1087− then "^" <> contents <> "^"
1104+ then return $ "^" <> contents <> "^"
1088− else if isEnabled Ext_raw_html opts
1105+ else if isEnabled Ext_raw_html opts
1089− then "<sup>" <> contents <> "</sup>"
1106+ then return $ "<sup>" <> contents <> "</sup>"
1108+ case traverse toSuperscriptInline lst of
1109+ Just xs' | not (writerPreferAscii opts)
1110+ -> inlineListToMarkdown opts xs'
1091− let rendered = render Nothing contents
1112+ let rendered = render Nothing contents
1092− in case mapM toSuperscript (T.unpack rendered) of
1114+ case mapM toSuperscript (T.unpack rendered) of
1093− Just r -> literal $ T.pack r
1115+ Just r -> literal $ T.pack r
1094− Nothing -> literal $ "^(" <> rendered <> ")"
1116+ Nothing -> literal $ "^(" <> rendered <> ")"
1095inlineToMarkdown _ (Subscript []) = return empty
1117inlineToMarkdown _ (Subscript []) = return empty
1096inlineToMarkdown opts (Subscript lst) =
1118inlineToMarkdown opts (Subscript lst) =
1097− local (\env -> env {envEscapeSpaces = True}) $ do
1119+ local (\env -> env {envEscapeSpaces = (envVariant env == Markdown)}) $ do
1098 contents <- inlineListToMarkdown opts lst
1120 contents <- inlineListToMarkdown opts lst
1099− return $ if isEnabled Ext_subscript opts
1121+ if isEnabled Ext_subscript opts
1100− then "~" <> contents <> "~"
1122+ then return $ "~" <> contents <> "~"
1101− else if isEnabled Ext_raw_html opts
1123+ else if isEnabled Ext_raw_html opts
1102− then "<sub>" <> contents <> "</sub>"
1124+ then return $ "<sub>" <> contents <> "</sub>"
1126+ case traverse toSubscriptInline lst of
1127+ Just xs' | not (writerPreferAscii opts)
1128+ -> inlineListToMarkdown opts xs'
1104− let rendered = render Nothing contents
1130+ let rendered = render Nothing contents
1105− in case mapM toSubscript (T.unpack rendered) of
1132+ case mapM toSuperscript (T.unpack rendered) of
1106− Just r -> literal $ T.pack r
1133+ Just r -> literal $ T.pack r
1107− Nothing -> literal $ "_(" <> rendered <> ")"
1134+ Nothing -> literal $ "_(" <> rendered <> ")"
1108inlineToMarkdown opts (SmallCaps lst) = do
1135inlineToMarkdown opts (SmallCaps lst) = do
1109− plain <- asks envPlain
1136+ variant <- asks envVariant
1110− if not plain &&
1137+ if variant /= PlainText &&
1111 (isEnabled Ext_raw_html opts || isEnabled Ext_native_spans opts)
1138 (isEnabled Ext_raw_html opts || isEnabled Ext_native_spans opts)
1112 then inlineToMarkdown opts (Span ("",["smallcaps"],[]) lst)
1139 then inlineToMarkdown opts (Span ("",["smallcaps"],[]) lst)
1113 else inlineListToMarkdown opts $ capitalize lst
1140 else inlineListToMarkdown opts $ capitalize lst
@@ -1137,16 +1164,17 @@ inlineToMarkdown opts (Code attr str) = do
1137 let attrs = if isEnabled Ext_inline_code_attributes opts && attr /= nullAttr
1164 let attrs = if isEnabled Ext_inline_code_attributes opts && attr /= nullAttr
1138 then attrsToMarkdown attr
1165 then attrsToMarkdown attr
1139 else empty
1166 else empty
1140− plain <- asks envPlain
1167+ variant <- asks envVariant
1141− if plain
1168+ case variant of
1142− then return $ literal str
1169+ PlainText -> return $ literal str
1170+ _ -> return $ literal
1143− else return $ literal (marker <> spacer <> str <> spacer <> marker) <> attrs
1171+ (marker <> spacer <> str <> spacer <> marker) <> attrs
1144inlineToMarkdown opts (Str str) = do
1172inlineToMarkdown opts (Str str) = do
1145− isPlain <- asks envPlain
1173+ variant <- asks envVariant
1146 let str' = (if isEnabled Ext_smart opts
1174 let str' = (if isEnabled Ext_smart opts
1147 then unsmartify opts
1175 then unsmartify opts
1148 else id) $
1176 else id) $
1149− if isPlain
1177+ if variant == PlainText
1150 then str
1178 then str
1151 else escapeText opts str
1179 else escapeText opts str
1152 return $ literal str'
1180 return $ literal str'
@@ -1161,10 +1189,10 @@ inlineToMarkdown opts (Math InlineMath str) =
1161 | isEnabled Ext_tex_math_double_backslash opts ->
1189 | isEnabled Ext_tex_math_double_backslash opts ->
1162 return $ "\\\\(" <> literal str <> "\\\\)"
1190 return $ "\\\\(" <> literal str <> "\\\\)"
1163 | otherwise -> do
1191 | otherwise -> do
1164− plain <- asks envPlain
1192+ variant <- asks envVariant
1165 texMathToInlines InlineMath str >>=
1193 texMathToInlines InlineMath str >>=
1166 inlineListToMarkdown opts .
1194 inlineListToMarkdown opts .
1167− (if plain then makeMathPlainer else id)
1195+ (if variant == PlainText then makeMathPlainer else id)
1168inlineToMarkdown opts (Math DisplayMath str) =
1196inlineToMarkdown opts (Math DisplayMath str) =
1169 case writerHTMLMathMethod opts of
1197 case writerHTMLMathMethod opts of
1170 WebTeX url -> (\x -> blankline <> x <> blankline) `fmap`
1198 WebTeX url -> (\x -> blankline <> x <> blankline) `fmap`
@@ -1183,15 +1211,15 @@ inlineToMarkdown opts il@(RawInline f str) = do
1183 let numticks = if null tickGroups
1211 let numticks = if null tickGroups
1185 else 1 + maximum (map T.length tickGroups)
1213 else 1 + maximum (map T.length tickGroups)
1186− plain <- asks envPlain
1214+ variant <- asks envVariant
1187 let Format fmt = f
1215 let Format fmt = f
1188 let rawAttribInline = return $
1216 let rawAttribInline = return $
1189 literal (T.replicate numticks "`") <> literal str <>
1217 literal (T.replicate numticks "`") <> literal str <>
1190 literal (T.replicate numticks "`") <> literal "{=" <> literal fmt <> literal "}"
1218 literal (T.replicate numticks "`") <> literal "{=" <> literal fmt <> literal "}"
1191 let renderEmpty = mempty <$ report (InlineNotRendered il)
1219 let renderEmpty = mempty <$ report (InlineNotRendered il)
1192− case () of
1220+ case variant of
1193− _ | plain -> renderEmpty
1221+ PlainText -> renderEmpty
1194− | f `elem` ["markdown", "markdown_github", "markdown_phpextra",
1222+ _ | f `elem` ["markdown", "markdown_github", "markdown_phpextra",
1195 "markdown_mmd", "markdown_strict"] ->
1223 "markdown_mmd", "markdown_strict"] ->
1196 return $ literal str
1224 return $ literal str
1197 | isEnabled Ext_raw_attribute opts -> rawAttribInline
1225 | isEnabled Ext_raw_attribute opts -> rawAttribInline
@@ -1207,8 +1235,8 @@ inlineToMarkdown opts il@(RawInline f str) = do
1207 | otherwise -> renderEmpty
1235 | otherwise -> renderEmpty
1208 | otherwise -> renderEmpty
1236 | otherwise -> renderEmpty
1209inlineToMarkdown opts LineBreak = do
1237inlineToMarkdown opts LineBreak = do
1210− plain <- asks envPlain
1238+ variant <- asks envVariant
1211− if plain || isEnabled Ext_hard_line_breaks opts
1239+ if variant == PlainText || isEnabled Ext_hard_line_breaks opts
1212 then return cr
1240 then return cr
1213 else return $
1241 else return $
1214 if isEnabled Ext_escaped_line_breaks opts
1242 if isEnabled Ext_escaped_line_breaks opts
@@ -1261,7 +1289,7 @@ inlineToMarkdown opts lnk@(Link attr txt (src, tit))
1261 (literal . T.strip) <$>
1289 (literal . T.strip) <$>
1262 writeHtml5String opts{ writerTemplate = Nothing } (Pandoc nullMeta [Plain [lnk]])
1290 writeHtml5String opts{ writerTemplate = Nothing } (Pandoc nullMeta [Plain [lnk]])
1263 | otherwise = do
1291 | otherwise = do
1264− plain <- asks envPlain
1292+ variant <- asks envVariant
1265 linktext <- inlineListToMarkdown opts txt
1293 linktext <- inlineListToMarkdown opts txt
1266 let linktitle = if T.null tit
1294 let linktitle = if T.null tit
1267 then empty
1295 then empty
@@ -1279,9 +1307,9 @@ inlineToMarkdown opts lnk@(Link attr txt (src, tit))
1279 then literal <$> getReference attr linktext (src, tit)
1307 then literal <$> getReference attr linktext (src, tit)
1280 else return mempty
1308 else return mempty
1281 return $ if useAuto
1309 return $ if useAuto
1282− then if plain
1310+ then case variant of
1283− then literal srcSuffix
1311+ PlainText -> literal srcSuffix
1284− else "<" <> literal srcSuffix <> ">"
1312+ _ -> "<" <> literal srcSuffix <> ">"
1285 else if useRefLinks
1313 else if useRefLinks
1286 then let first = "[" <> linktext <> "]"
1314 then let first = "[" <> linktext <> "]"
1287 second = if getKey linktext == getKey reftext
1315 second = if getKey linktext == getKey reftext
@@ -1290,9 +1318,9 @@ inlineToMarkdown opts lnk@(Link attr txt (src, tit))
1290 else "[]"
1318 else "[]"
1291 else "[" <> reftext <> "]"
1319 else "[" <> reftext <> "]"
1292 in first <> second
1320 in first <> second
1293− else if plain
1321+ else case variant of
1294− then linktext
1322+ PlainText -> linktext
1295− else "[" <> linktext <> "](" <>
1323+ _ -> "[" <> linktext <> "](" <>
1296 literal src <> linktitle <> ")" <>
1324 literal src <> linktitle <> ")" <>
1297 linkAttributes opts attr
1325 linkAttributes opts attr
1298inlineToMarkdown opts img@(Image attr alternate (source, tit))
1326inlineToMarkdown opts img@(Image attr alternate (source, tit))
@@ -1302,15 +1330,15 @@ inlineToMarkdown opts img@(Image attr alternate (source, tit))
1302 (literal . T.strip) <$>
1330 (literal . T.strip) <$>
1303 writeHtml5String opts{ writerTemplate = Nothing } (Pandoc nullMeta [Plain [img]])
1331 writeHtml5String opts{ writerTemplate = Nothing } (Pandoc nullMeta [Plain [img]])
1304 | otherwise = do
1332 | otherwise = do
1305− plain <- asks envPlain
1333+ variant <- asks envVariant
1306 let txt = if null alternate || alternate == [Str source]
1334 let txt = if null alternate || alternate == [Str source]
1307 -- to prevent autolinks
1335 -- to prevent autolinks
1308 then [Str ""]
1336 then [Str ""]
1309 else alternate
1337 else alternate
1310 linkPart <- inlineToMarkdown opts (Link attr txt (source, tit))
1338 linkPart <- inlineToMarkdown opts (Link attr txt (source, tit))
1311− return $ if plain
1339+ return $ case variant of
1312− then "[" <> linkPart <> "]"
1340+ PlainText -> "[" <> linkPart <> "]"
1313− else "!" <> linkPart
1341+ _ -> "!" <> linkPart
1314inlineToMarkdown opts (Note contents) = do
1342inlineToMarkdown opts (Note contents) = do
1315 modify (\st -> st{ stNotes = contents : stNotes st })
1343 modify (\st -> st{ stNotes = contents : stNotes st })
1316 st <- get
1344 st <- get
@@ -1329,3 +1357,19 @@ lineBreakToSpace :: Inline -> Inline
1329lineBreakToSpace LineBreak = Space
1357lineBreakToSpace LineBreak = Space
1330lineBreakToSpace SoftBreak = Space
1358lineBreakToSpace SoftBreak = Space
1331lineBreakToSpace x = x
1359lineBreakToSpace x = x
1361+toSubscriptInline :: Inline -> Maybe Inline
1362+toSubscriptInline Space = Just Space
1363+toSubscriptInline (Span attr ils) = Span attr <$> traverse toSubscriptInline ils
1364+toSubscriptInline (Str s) = Str . T.pack <$> traverse toSubscript (T.unpack s)
1365+toSubscriptInline LineBreak = Just LineBreak
1366+toSubscriptInline SoftBreak = Just SoftBreak
1367+toSubscriptInline _ = Nothing
1369+toSuperscriptInline :: Inline -> Maybe Inline
1370+toSuperscriptInline Space = Just Space
1371+toSuperscriptInline (Span attr ils) = Span attr <$> traverse toSuperscriptInline ils
1372+toSuperscriptInline (Str s) = Str . T.pack <$> traverse toSuperscript (T.unpack s)
1373+toSuperscriptInline LineBreak = Just LineBreak
1374+toSuperscriptInline SoftBreak = Just SoftBreak
1375+toSuperscriptInline _ = Nothing