git.iko.soy/typeable/pandoc
on master help sign in
Better table handling for Haddock.

In the reader, we use the new Table type in Haddock. Note that tables with col/rowspans will not translate well into Pandoc. In the writer, we now render tables always as grid tables, since Haddock supports these.

commitbe12ae3bca4f1c2d712e412b11a14b6473c7ab10 authorJohn MacFarlane <jgm@berkeley.edu> dateFri 16 Mar 2018, 22:38 (9 years ago) parentc166861
3 files changed+85−113
src/Text/Pandoc/Readers/Haddock.hs+14−1 src/Text/Pandoc/Writers/Haddock.hs+4−59 test/tables.haddock+67−53
src/Text/Pandoc/Readers/Haddock.hs+14−1
@@ -19,7 +19,7 @@ import Data.List (intersperse, stripPrefix)
1919import Data.Maybe (fromMaybe)
2020import Data.Text (Text, unpack)
2121import Documentation.Haddock.Parser
22−import Documentation.Haddock.Types
22+import Documentation.Haddock.Types as H
2323import Text.Pandoc.Builder (Blocks, Inlines)
2424import qualified Text.Pandoc.Builder as B
2525import Text.Pandoc.Class (PandocMonad)
@@ -85,6 +85,18 @@ docHToBlocks d' =
8585 DocProperty s -> B.codeBlockWith ("",["property","haskell"],[]) (trim s)
8686 DocExamples es -> mconcat $ map (\e ->
8787 makeExample ">>>" (exampleExpression e) (exampleResult e)) es
88+ DocTable H.Table{ tableHeaderRows = headerRows
89+ , tableBodyRows = bodyRows
90+ }
91+ -> let toCells = map (docHToBlocks . tableCellContents) . tableRowCells
92+ (header, body) =
93+ if null headerRows
94+ then ([], map toCells bodyRows)
95+ else (toCells (head headerRows),
96+ map toCells (tail headerRows ++ bodyRows))
97+ colspecs = replicate (maximum (map length body))
98+ (AlignDefault, 0.0)
99+ in B.table mempty colspecs header body
88100
89101 where inlineFallback = B.plain $ docHToInlines False d'
90102 consolidatePlains = B.fromList . consolidatePlains' . B.toList
@@ -133,6 +145,7 @@ docHToInlines isCode d' =
133145 DocAName s -> B.spanWith (s,["anchor"],[]) mempty
134146 DocProperty _ -> mempty
135147 DocExamples _ -> mempty
148+ DocTable _ -> mempty
136149
137150-- | Create an 'Example', stripping superfluous characters as appropriate
138151makeExample :: String -> String -> [String] -> Blocks
src/Text/Pandoc/Writers/Haddock.hs+4−59
@@ -35,7 +35,6 @@ Haddock: <http://www.haskell.org/haddock/doc/html/>
3535module Text.Pandoc.Writers.Haddock (writeHaddock) where
3636import Control.Monad.State.Strict
3737import Data.Default
38−import Data.List (intersperse, transpose)
3938import Data.Text (Text)
4039import Text.Pandoc.Class (PandocMonad, report)
4140import Text.Pandoc.Definition
@@ -136,29 +135,15 @@ blockToHaddock _ (CodeBlock (_,_,_) str) =
136135-- Nothing in haddock corresponds to block quotes:
137136blockToHaddock opts (BlockQuote blocks) =
138137 blockListToHaddock opts blocks
139−-- Haddock doesn't have tables. Use haddock tables in code.
140138blockToHaddock opts (Table caption aligns widths headers rows) = do
141139 caption' <- inlineListToHaddock opts caption
142140 let caption'' = if null caption
143141 then empty
144142 else blankline <> caption' <> blankline
145− rawHeaders <- mapM (blockListToHaddock opts) headers
146− rawRows <- mapM (mapM (blockListToHaddock opts)) rows
147− let isSimple = all (==0) widths
148− let isPlainBlock (Plain _) = True
149− isPlainBlock _ = False
150− let hasBlocks = not (all isPlainBlock $ concat . concat $ headers:rows)
151− (nst,tbl) <- case True of
152− _ | isSimple -> (nest 2,) <$>
153− pandocTable opts (all null headers) aligns widths
154− rawHeaders rawRows
155− | not hasBlocks -> (nest 2,) <$>
156− pandocTable opts (all null headers) aligns widths
157− rawHeaders rawRows
158− | otherwise -> (id,) <$>
159− gridTable opts blockListToHaddock
160− (all null headers) aligns widths headers rows
161− return $ prefixed "> " (nst $ tbl $$ blankline $$ caption'') $$ blankline
143+ tbl <- gridTable opts blockListToHaddock
144+ (all null headers) (map (\_ -> AlignDefault) aligns)
145+ widths headers rows
146+ return $ prefixed "> " (tbl $$ blankline $$ caption'') $$ blankline
162147blockToHaddock opts (BulletList items) = do
163148 contents <- mapM (bulletListItemToHaddock opts) items
164149 return $ cat contents <> blankline
@@ -174,46 +159,6 @@ blockToHaddock opts (DefinitionList items) = do
174159 contents <- mapM (definitionListItemToHaddock opts) items
175160 return $ cat contents <> blankline
176161
177−pandocTable :: PandocMonad m
178− => WriterOptions -> Bool -> [Alignment] -> [Double]
179− -> [Doc] -> [[Doc]] -> StateT WriterState m Doc
180−pandocTable opts headless aligns widths rawHeaders rawRows = do
181− let isSimple = all (==0) widths
182− let alignHeader alignment = case alignment of
183− AlignLeft -> lblock
184− AlignCenter -> cblock
185− AlignRight -> rblock
186− AlignDefault -> lblock
187− let numChars = maximum . map offset
188− let widthsInChars = if isSimple
189− then map ((+2) . numChars)
190− $ transpose (rawHeaders : rawRows)
191− else map
192− (floor . (fromIntegral (writerColumns opts) *))
193− widths
194− let makeRow = hcat . intersperse (lblock 1 (text " ")) .
195− zipWith3 alignHeader aligns widthsInChars
196− let rows' = map makeRow rawRows
197− let head' = makeRow rawHeaders
198− let maxRowHeight = maximum $ map height (head':rows')
199− let underline = cat $ intersperse (text " ") $
200− map (\width -> text (replicate width '-')) widthsInChars
201− let border
202− | maxRowHeight > 1 = text (replicate (sum widthsInChars +
203− length widthsInChars - 1) '-')
204− | headless = underline
205− | otherwise = empty
206− let head'' = if headless
207− then empty
208− else border <> cr <> head'
209− let body = if maxRowHeight > 1
210− then vsep rows'
211− else vcat rows'
212− let bottom = if headless
213− then underline
214− else border
215− return $ head'' $$ underline $$ body $$ bottom
216−
217162-- | Convert bullet list item (list of blocks) to haddock
218163bulletListItemToHaddock :: PandocMonad m
219164 => WriterOptions -> [Block] -> StateT WriterState m Doc
test/tables.haddock+67−53
@@ -1,76 +1,90 @@
11Simple table with caption:
22
3−> Right Left Center Default
4−> ------- ------ -------- ---------
5−> 12 12 12 12
6−> 123 123 123 123
7−> 1 1 1 1
3+> +-------+------+--------+---------+
4+> | Right | Left | Center | Default |
5+> +=======+======+========+=========+
6+> | 12 | 12 | 12 | 12 |
7+> +-------+------+--------+---------+
8+> | 123 | 123 | 123 | 123 |
9+> +-------+------+--------+---------+
10+> | 1 | 1 | 1 | 1 |
11+> +-------+------+--------+---------+
812>
9−> Demonstration of simple table syntax.
13+> Demonstration of simple table syntax.
1014
1115Simple table without caption:
1216
13−> Right Left Center Default
14−> ------- ------ -------- ---------
15−> 12 12 12 12
16−> 123 123 123 123
17−> 1 1 1 1
17+> +-------+------+--------+---------+
18+> | Right | Left | Center | Default |
19+> +=======+======+========+=========+
20+> | 12 | 12 | 12 | 12 |
21+> +-------+------+--------+---------+
22+> | 123 | 123 | 123 | 123 |
23+> +-------+------+--------+---------+
24+> | 1 | 1 | 1 | 1 |
25+> +-------+------+--------+---------+
1826
1927Simple table indented two spaces:
2028
21−> Right Left Center Default
22−> ------- ------ -------- ---------
23−> 12 12 12 12
24−> 123 123 123 123
25−> 1 1 1 1
29+> +-------+------+--------+---------+
30+> | Right | Left | Center | Default |
31+> +=======+======+========+=========+
32+> | 12 | 12 | 12 | 12 |
33+> +-------+------+--------+---------+
34+> | 123 | 123 | 123 | 123 |
35+> +-------+------+--------+---------+
36+> | 1 | 1 | 1 | 1 |
37+> +-------+------+--------+---------+
2638>
27−> Demonstration of simple table syntax.
39+> Demonstration of simple table syntax.
2840
2941Multiline table with caption:
3042
31−> --------------------------------------------------------------
32−> Centered Left Right Default aligned
33−> Header Aligned Aligned
34−> ----------- ---------- ------------ --------------------------
35−> First row 12.0 Example of a row that
36−> spans multiple lines.
43+> +----------+---------+-----------+-------------------------+
44+> | Centered | Left | Right | Default aligned |
45+> | Header | Aligned | Aligned | |
46+> +==========+=========+===========+=========================+
47+> | First | row | 12.0 | Example of a row that |
48+> | | | | spans multiple lines. |
49+> +----------+---------+-----------+-------------------------+
50+> | Second | row | 5.0 | Here’s another one. |
51+> | | | | Note the blank line |
52+> | | | | between rows. |
53+> +----------+---------+-----------+-------------------------+
3754>
38−> Second row 5.0 Here’s another one. Note
39−> the blank line between
40−> rows.
41−> --------------------------------------------------------------
42−>
43−> Here’s the caption. It may span multiple lines.
55+> Here’s the caption. It may span multiple lines.
4456
4557Multiline table without caption:
4658
47−> --------------------------------------------------------------
48−> Centered Left Right Default aligned
49−> Header Aligned Aligned
50−> ----------- ---------- ------------ --------------------------
51−> First row 12.0 Example of a row that
52−> spans multiple lines.
53−>
54−> Second row 5.0 Here’s another one. Note
55−> the blank line between
56−> rows.
57−> --------------------------------------------------------------
59+> +----------+---------+-----------+-------------------------+
60+> | Centered | Left | Right | Default aligned |
61+> | Header | Aligned | Aligned | |
62+> +==========+=========+===========+=========================+
63+> | First | row | 12.0 | Example of a row that |
64+> | | | | spans multiple lines. |
65+> +----------+---------+-----------+-------------------------+
66+> | Second | row | 5.0 | Here’s another one. |
67+> | | | | Note the blank line |
68+> | | | | between rows. |
69+> +----------+---------+-----------+-------------------------+
5870
5971Table without column headers:
6072
61−> ----- ----- ----- -----
62−> 12 12 12 12
63−> 123 123 123 123
64−> 1 1 1 1
65−> ----- ----- ----- -----
73+> +-----+-----+-----+-----+
74+> | 12 | 12 | 12 | 12 |
75+> +-----+-----+-----+-----+
76+> | 123 | 123 | 123 | 123 |
77+> +-----+-----+-----+-----+
78+> | 1 | 1 | 1 | 1 |
79+> +-----+-----+-----+-----+
6680
6781Multiline table without column headers:
6882
69−> ----------- ---------- ------------ --------------------------
70−> First row 12.0 Example of a row that
71−> spans multiple lines.
72−>
73−> Second row 5.0 Here’s another one. Note
74−> the blank line between
75−> rows.
76−> ----------- ---------- ------------ --------------------------
83+> +----------+---------+-----------+-------------------------+
84+> | First | row | 12.0 | Example of a row that |
85+> | | | | spans multiple lines. |
86+> +----------+---------+-----------+-------------------------+
87+> | Second | row | 5.0 | Here’s another one. |
88+> | | | | Note the blank line |
89+> | | | | between rows. |
90+> +----------+---------+-----------+-------------------------+