@@ -34,6 +34,7 @@ module Text.Pandoc.Writers.CommonMark (writeCommonMark) where
34import CMarkGFM
34import CMarkGFM
35import Control.Monad.State.Strict (State, get, modify, runState)
35import Control.Monad.State.Strict (State, get, modify, runState)
36import Data.Foldable (foldrM)
36import Data.Foldable (foldrM)
37+import Data.Monoid (Any (..))
37import Data.Text (Text)
38import Data.Text (Text)
38import qualified Data.Text as T
39import qualified Data.Text as T
39import Text.Pandoc.Class (PandocMonad)
40import Text.Pandoc.Class (PandocMonad)
@@ -41,7 +42,7 @@ import Text.Pandoc.Definition
41import Text.Pandoc.Options
42import Text.Pandoc.Options
42import Text.Pandoc.Shared (isTightList, linesToPara)
43import Text.Pandoc.Shared (isTightList, linesToPara)
43import Text.Pandoc.Templates (renderTemplate')
44import Text.Pandoc.Templates (renderTemplate')
44−import Text.Pandoc.Walk (walkM)
45+import Text.Pandoc.Walk (walkM, walk, query)
45import Text.Pandoc.Writers.HTML (writeHtml5String)
46import Text.Pandoc.Writers.HTML (writeHtml5String)
46import Text.Pandoc.Writers.Shared
47import Text.Pandoc.Writers.Shared
@@ -52,7 +53,12 @@ writeCommonMark opts (Pandoc meta blocks) = do
52 notes' = if null notes
53 notes' = if null notes
54 else [OrderedList (1, Decimal, Period) $ reverse notes]
55 else [OrderedList (1, Decimal, Period) $ reverse notes]
56+ let softBreakToSpace SoftBreak = Space
57+ softBreakToSpace x = x
58+ let blocks'' = if writerWrapText opts == WrapNone
59+ then walk softBreakToSpace blocks'
55− main <- blocksToCommonMark opts (blocks' ++ notes')
61+ main <- blocksToCommonMark opts (blocks'' ++ notes')
56 metadata <- metaToJSON opts
62 metadata <- metaToJSON opts
57 (blocksToCommonMark opts)
63 (blocksToCommonMark opts)
58 (inlinesToCommonMark opts)
64 (inlinesToCommonMark opts)
@@ -78,43 +84,46 @@ blocksToCommonMark opts bs = do
78 colwidth = if writerWrapText opts == WrapAuto
84 colwidth = if writerWrapText opts == WrapAuto
79 then Just $ writerColumns opts
85 then Just $ writerColumns opts
80 else Nothing
86 else Nothing
81− nodes <- blocksToNodes bs
87+ nodes <- blocksToNodes opts bs
83 nodeToCommonmark cmarkOpts colwidth $
89 nodeToCommonmark cmarkOpts colwidth $
84 node DOCUMENT nodes
90 node DOCUMENT nodes
86inlinesToCommonMark :: PandocMonad m => WriterOptions -> [Inline] -> m Text
92inlinesToCommonMark :: PandocMonad m => WriterOptions -> [Inline] -> m Text
87inlinesToCommonMark opts ils = return $
93inlinesToCommonMark opts ils = return $
88− nodeToCommonmark cmarkOpts colwidth $ node PARAGRAPH (inlinesToNodes ils)
94+ nodeToCommonmark cmarkOpts colwidth $
95+ node PARAGRAPH (inlinesToNodes opts ils)
89 where cmarkOpts = [optHardBreaks | isEnabled Ext_hard_line_breaks opts]
96 where cmarkOpts = [optHardBreaks | isEnabled Ext_hard_line_breaks opts]
90 colwidth = if writerWrapText opts == WrapAuto
97 colwidth = if writerWrapText opts == WrapAuto
91 then Just $ writerColumns opts
98 then Just $ writerColumns opts
92 else Nothing
99 else Nothing
94−blocksToNodes :: PandocMonad m => [Block] -> m [Node]
101+blocksToNodes :: PandocMonad m => WriterOptions -> [Block] -> m [Node]
95−blocksToNodes = foldrM blockToNodes []
102+blocksToNodes opts = foldrM (blockToNodes opts) []
97−blockToNodes :: PandocMonad m => Block -> [Node] -> m [Node]
104+blockToNodes :: PandocMonad m => WriterOptions -> Block -> [Node] -> m [Node]
105+blockToNodes opts (Plain xs) ns =
98−blockToNodes (Plain xs) ns = return (node PARAGRAPH (inlinesToNodes xs) : ns)
106+ return (node PARAGRAPH (inlinesToNodes opts xs) : ns)
107+blockToNodes opts (Para xs) ns =
99−blockToNodes (Para xs) ns = return (node PARAGRAPH (inlinesToNodes xs) : ns)
108+ return (node PARAGRAPH (inlinesToNodes opts xs) : ns)
100−blockToNodes (LineBlock lns) ns = blockToNodes (linesToPara lns) ns
109+blockToNodes opts (LineBlock lns) ns = blockToNodes opts (linesToPara lns) ns
101−blockToNodes (CodeBlock (_,classes,_) xs) ns = return $
110+blockToNodes _ (CodeBlock (_,classes,_) xs) ns = return $
102 (node (CODE_BLOCK (T.pack (unwords classes)) (T.pack xs)) [] : ns)
111 (node (CODE_BLOCK (T.pack (unwords classes)) (T.pack xs)) [] : ns)
103−blockToNodes (RawBlock fmt xs) ns
112+blockToNodes _ (RawBlock fmt xs) ns
104 | fmt == Format "html" = return (node (HTML_BLOCK (T.pack xs)) [] : ns)
113 | fmt == Format "html" = return (node (HTML_BLOCK (T.pack xs)) [] : ns)
105 | otherwise = return (node (CUSTOM_BLOCK (T.pack xs) (T.empty)) [] : ns)
114 | otherwise = return (node (CUSTOM_BLOCK (T.pack xs) (T.empty)) [] : ns)
106−blockToNodes (BlockQuote bs) ns = do
115+blockToNodes opts (BlockQuote bs) ns = do
107− nodes <- blocksToNodes bs
116+ nodes <- blocksToNodes opts bs
108 return (node BLOCK_QUOTE nodes : ns)
117 return (node BLOCK_QUOTE nodes : ns)
109−blockToNodes (BulletList items) ns = do
118+blockToNodes opts (BulletList items) ns = do
110− nodes <- mapM blocksToNodes items
119+ nodes <- mapM (blocksToNodes opts) items
111 return (node (LIST ListAttributes{
120 return (node (LIST ListAttributes{
112 listType = BULLET_LIST,
121 listType = BULLET_LIST,
113 listDelim = PERIOD_DELIM,
122 listDelim = PERIOD_DELIM,
114 listTight = isTightList items,
123 listTight = isTightList items,
115 listStart = 1 }) (map (node ITEM) nodes) : ns)
124 listStart = 1 }) (map (node ITEM) nodes) : ns)
116−blockToNodes (OrderedList (start, _sty, delim) items) ns = do
125+blockToNodes opts (OrderedList (start, _sty, delim) items) ns = do
117− nodes <- mapM blocksToNodes items
126+ nodes <- mapM (blocksToNodes opts) items
118 return (node (LIST ListAttributes{
127 return (node (LIST ListAttributes{
119 listType = ORDERED_LIST,
128 listType = ORDERED_LIST,
120 listDelim = case delim of
129 listDelim = case delim of
@@ -123,12 +132,14 @@ blockToNodes (OrderedList (start, _sty, delim) items) ns = do
123 _ -> PERIOD_DELIM,
132 _ -> PERIOD_DELIM,
124 listTight = isTightList items,
133 listTight = isTightList items,
125 listStart = start }) (map (node ITEM) nodes) : ns)
134 listStart = start }) (map (node ITEM) nodes) : ns)
126−blockToNodes HorizontalRule ns = return (node THEMATIC_BREAK [] : ns)
135+blockToNodes _ HorizontalRule ns = return (node THEMATIC_BREAK [] : ns)
136+blockToNodes opts (Header lev _ ils) ns =
127−blockToNodes (Header lev _ ils) ns = return (node (HEADING lev) (inlinesToNodes ils) : ns)
137+ return (node (HEADING lev) (inlinesToNodes opts ils) : ns)
128−blockToNodes (Div _ bs) ns = do
138+blockToNodes opts (Div _ bs) ns = do
129− nodes <- blocksToNodes bs
139+ nodes <- blocksToNodes opts bs
130 return (nodes ++ ns)
140 return (nodes ++ ns)
131−blockToNodes (DefinitionList items) ns = blockToNodes (BulletList items') ns
141+blockToNodes opts (DefinitionList items) ns =
142+ blockToNodes opts (BulletList items') ns
132 where items' = map dlToBullet items
143 where items' = map dlToBullet items
133 dlToBullet (term, ((Para xs : ys) : zs)) =
144 dlToBullet (term, ((Para xs : ys) : zs)) =
134 Para (term ++ [LineBreak] ++ xs) : ys ++ concat zs
145 Para (term ++ [LineBreak] ++ xs) : ys ++ concat zs
@@ -136,54 +147,74 @@ blockToNodes (DefinitionList items) ns = blockToNodes (BulletList items') ns
136 Plain (term ++ [LineBreak] ++ xs) : ys ++ concat zs
147 Plain (term ++ [LineBreak] ++ xs) : ys ++ concat zs
137 dlToBullet (term, xs) =
148 dlToBullet (term, xs) =
138 Para term : concat xs
149 Para term : concat xs
139−blockToNodes t@(Table _ _ _ _ _) ns = do
150+blockToNodes opts t@(Table _capt aligns widths headers rows) ns = do
151+ let allrows = headers:rows
152+ let isLineBreak LineBreak = Any True
153+ isLineBreak _ = Any False
154+ let isSimple = all (==0) widths &&
155+ not ( getAny (query isLineBreak allrows) )
156+ if isEnabled Ext_pipe_tables opts && isSimple
158+ let toAlign AlignDefault = NoAlignment
159+ toAlign AlignLeft = LeftAligned
160+ toAlign AlignCenter = CenterAligned
161+ toAlign AlignRight = RightAligned
162+ let aligns' = map toAlign aligns
163+ let toCell bs = node TABLE_CELL <$> blocksToNodes opts bs
164+ let toRow cells = node TABLE_ROW <$> mapM toCell cells
165+ cmrows <- mapM toRow allrows
166+ return (node (TABLE aligns') cmrows : ns)
167+ else do -- fall back to raw HTML
140− s <- writeHtml5String def $! Pandoc nullMeta [t]
168+ s <- writeHtml5String def $! Pandoc nullMeta [t]
141− return (node (HTML_BLOCK s) [] : ns)
169+ return (node (HTML_BLOCK s) [] : ns)
142−blockToNodes Null ns = return ns
170+blockToNodes _ Null ns = return ns
144−inlinesToNodes :: [Inline] -> [Node]
172+inlinesToNodes :: WriterOptions -> [Inline] -> [Node]
145−inlinesToNodes = foldr inlineToNodes []
173+inlinesToNodes opts = foldr (inlineToNodes opts) []
147−inlineToNodes :: Inline -> [Node] -> [Node]
175+inlineToNodes :: WriterOptions -> Inline -> [Node] -> [Node]
148−inlineToNodes (Str s) = (node (TEXT (T.pack s)) [] :)
176+inlineToNodes _ (Str s) = (node (TEXT (T.pack s)) [] :)
149−inlineToNodes Space = (node (TEXT (T.pack " ")) [] :)
177+inlineToNodes _ Space = (node (TEXT (T.pack " ")) [] :)
150−inlineToNodes LineBreak = (node LINEBREAK [] :)
178+inlineToNodes _ LineBreak = (node LINEBREAK [] :)
151−inlineToNodes SoftBreak = (node SOFTBREAK [] :)
179+inlineToNodes _ SoftBreak = (node SOFTBREAK [] :)
152−inlineToNodes (Emph xs) = (node EMPH (inlinesToNodes xs) :)
180+inlineToNodes opts (Emph xs) = (node EMPH (inlinesToNodes opts xs) :)
153−inlineToNodes (Strong xs) = (node STRONG (inlinesToNodes xs) :)
181+inlineToNodes opts (Strong xs) = (node STRONG (inlinesToNodes opts xs) :)
154−inlineToNodes (Strikeout xs) =
182+inlineToNodes opts (Strikeout xs) =
183+ if isEnabled Ext_strikeout opts
184+ then (node STRIKETHROUGH (inlinesToNodes opts xs) :)
155− ((node (HTML_INLINE (T.pack "<s>")) [] : inlinesToNodes xs ++
185+ else ((node (HTML_INLINE (T.pack "<s>")) [] : inlinesToNodes opts xs ++
156− [node (HTML_INLINE (T.pack "</s>")) []]) ++ )
186+ [node (HTML_INLINE (T.pack "</s>")) []]) ++ )
157−inlineToNodes (Superscript xs) =
187+inlineToNodes opts (Superscript xs) =
158− ((node (HTML_INLINE (T.pack "<sup>")) [] : inlinesToNodes xs ++
188+ ((node (HTML_INLINE (T.pack "<sup>")) [] : inlinesToNodes opts xs ++
159 [node (HTML_INLINE (T.pack "</sup>")) []]) ++ )
189 [node (HTML_INLINE (T.pack "</sup>")) []]) ++ )
160−inlineToNodes (Subscript xs) =
190+inlineToNodes opts (Subscript xs) =
161− ((node (HTML_INLINE (T.pack "<sub>")) [] : inlinesToNodes xs ++
191+ ((node (HTML_INLINE (T.pack "<sub>")) [] : inlinesToNodes opts xs ++
162 [node (HTML_INLINE (T.pack "</sub>")) []]) ++ )
192 [node (HTML_INLINE (T.pack "</sub>")) []]) ++ )
163−inlineToNodes (SmallCaps xs) =
193+inlineToNodes opts (SmallCaps xs) =
164 ((node (HTML_INLINE (T.pack "<span class=\"smallcaps\">")) []
194 ((node (HTML_INLINE (T.pack "<span class=\"smallcaps\">")) []
165− : inlinesToNodes xs ++
195+ : inlinesToNodes opts xs ++
166 [node (HTML_INLINE (T.pack "</span>")) []]) ++ )
196 [node (HTML_INLINE (T.pack "</span>")) []]) ++ )
167−inlineToNodes (Link _ ils (url,tit)) =
197+inlineToNodes opts (Link _ ils (url,tit)) =
168− (node (LINK (T.pack url) (T.pack tit)) (inlinesToNodes ils) :)
198+ (node (LINK (T.pack url) (T.pack tit)) (inlinesToNodes opts ils) :)
169−inlineToNodes (Image _ ils (url,tit)) =
199+inlineToNodes opts (Image _ ils (url,tit)) =
170− (node (IMAGE (T.pack url) (T.pack tit)) (inlinesToNodes ils) :)
200+ (node (IMAGE (T.pack url) (T.pack tit)) (inlinesToNodes opts ils) :)
171−inlineToNodes (RawInline fmt xs)
201+inlineToNodes _ (RawInline fmt xs)
172 | fmt == Format "html" = (node (HTML_INLINE (T.pack xs)) [] :)
202 | fmt == Format "html" = (node (HTML_INLINE (T.pack xs)) [] :)
173 | otherwise = (node (CUSTOM_INLINE (T.pack xs) (T.empty)) [] :)
203 | otherwise = (node (CUSTOM_INLINE (T.pack xs) (T.empty)) [] :)
174−inlineToNodes (Quoted qt ils) =
204+inlineToNodes opts (Quoted qt ils) =
205+ ((node (TEXT start) [] :
175− ((node (TEXT start) [] : inlinesToNodes ils ++ [node (TEXT end) []]) ++)
206+ inlinesToNodes opts ils ++ [node (TEXT end) []]) ++)
176 where (start, end) = case qt of
207 where (start, end) = case qt of
177 SingleQuote -> (T.pack "‘", T.pack "’")
208 SingleQuote -> (T.pack "‘", T.pack "’")
178 DoubleQuote -> (T.pack "“", T.pack "”")
209 DoubleQuote -> (T.pack "“", T.pack "”")
179−inlineToNodes (Code _ str) = (node (CODE (T.pack str)) [] :)
210+inlineToNodes _ (Code _ str) = (node (CODE (T.pack str)) [] :)
180−inlineToNodes (Math mt str) =
211+inlineToNodes _ (Math mt str) =
181 case mt of
212 case mt of
182 InlineMath ->
213 InlineMath ->
183 (node (HTML_INLINE (T.pack ("\\(" ++ str ++ "\\)"))) [] :)
214 (node (HTML_INLINE (T.pack ("\\(" ++ str ++ "\\)"))) [] :)
184 DisplayMath ->
215 DisplayMath ->
185 (node (HTML_INLINE (T.pack ("\\[" ++ str ++ "\\]"))) [] :)
216 (node (HTML_INLINE (T.pack ("\\[" ++ str ++ "\\]"))) [] :)
186−inlineToNodes (Span _ ils) = (inlinesToNodes ils ++)
217+inlineToNodes opts (Span _ ils) = (inlinesToNodes opts ils ++)
187−inlineToNodes (Cite _ ils) = (inlinesToNodes ils ++)
218+inlineToNodes opts (Cite _ ils) = (inlinesToNodes opts ils ++)
188−inlineToNodes (Note _) = id -- should not occur
219+inlineToNodes _ (Note _) = id -- should not occur
189-- we remove Note elements in preprocessing
220-- we remove Note elements in preprocessing