Add support for writing nested tables to asciidoc (#6972)

Added field to WriterState that denotes the current nesting level for traversing tables.
Depending on the value of that field nested tables are recognized and written.
Asciidoc supports one level of nesting. If deeper tables are to be written, they are
omitted and a warning is issued.
This commit is contained in:
timo-a 2020-12-28 03:42:28 +01:00 committed by GitHub
parent dcd89413f3
commit 668596cc89
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 114 additions and 7 deletions

View file

@ -37,6 +37,7 @@ import Text.Pandoc.Shared
import Text.Pandoc.Templates (renderTemplate)
import Text.Pandoc.Writers.Shared
data WriterState = WriterState { defListMarker :: Text
, orderedListLevel :: Int
, bulletListLevel :: Int
@ -45,6 +46,10 @@ data WriterState = WriterState { defListMarker :: Text
, asciidoctorVariant :: Bool
, inList :: Bool
, hasMath :: Bool
-- |0 is no table
-- 1 is top level table
-- 2 is a table in a table
, tableNestingLevel :: Int
}
defaultWriterState :: WriterState
@ -56,6 +61,7 @@ defaultWriterState = WriterState { defListMarker = "::"
, asciidoctorVariant = False
, inList = False
, hasMath = False
, tableNestingLevel = 0
}
-- | Convert Pandoc to AsciiDoc.
@ -194,7 +200,7 @@ blockToAsciiDoc opts (BlockQuote blocks) = do
else contents
let bar = text "____"
return $ bar $$ chomp contents' $$ bar <> blankline
blockToAsciiDoc opts (Table _ blkCapt specs thead tbody tfoot) = do
blockToAsciiDoc opts block@(Table _ blkCapt specs thead tbody tfoot) = do
let (caption, aligns, widths, headers, rows) =
toLegacyTable blkCapt specs thead tbody tfoot
caption' <- inlineListToAsciiDoc opts caption
@ -236,23 +242,42 @@ blockToAsciiDoc opts (Table _ blkCapt specs thead tbody tfoot) = do
$ zipWith colspec aligns widths')
<> text ","
<> headerspec <> text "]"
-- construct cells and recurse in case of nested tables
parentTableLevel <- gets tableNestingLevel
let currentNestingLevel = parentTableLevel + 1
modify $ \st -> st{ tableNestingLevel = currentNestingLevel }
let separator = text (if parentTableLevel == 0
then "|" -- top level separator
else "!") -- nested separator
let makeCell [Plain x] = do d <- blockListToAsciiDoc opts [Plain x]
return $ text "|" <> chomp d
return $ separator <> chomp d
makeCell [Para x] = makeCell [Plain x]
makeCell [] = return $ text "|"
makeCell bs = do d <- blockListToAsciiDoc opts bs
return $ text "a|" $$ d
makeCell [] = return separator
makeCell bs = if currentNestingLevel == 2
then do
--asciidoc only supports nesting once
report $ BlockNotRendered block
return separator
else do
d <- blockListToAsciiDoc opts bs
return $ (text "a" <> separator) $$ d
let makeRow cells = hsep `fmap` mapM makeCell cells
rows' <- mapM makeRow rows
head' <- makeRow headers
modify $ \st -> st{ tableNestingLevel = parentTableLevel }
let head'' = if all null headers then empty else head'
let colwidth = if writerWrapText opts == WrapAuto
then writerColumns opts
else 100000
let maxwidth = maximum $ map offset (head':rows')
let body = if maxwidth > colwidth then vsep rows' else vcat rows'
let border = text "|==="
return $
let border = separator <> text "==="
return $
caption'' $$ tablespec $$ border $$ head'' $$ body $$ border $$ blankline
blockToAsciiDoc opts (BulletList items) = do
inlist <- gets inList

View file

@ -0,0 +1,82 @@
A table within a table should be convertet into a table within table
```
% pandoc -f html -t asciidoc
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title> NestedTables </title>
</head>
<body>
<table>
<tr>
<td >
<table> <tr> <td> a1 </td> <td> a2 </td> </tr> </table>
</td>
<td>b</td>
</tr>
<tr>
<td>c</td> <td>d </td>
</tr>
</table>
</body>
</html>
^D
[width="100%",cols="50%,50%",]
|===
a|
[cols=",",]
!===
!a1 !a2
!===
|b
|c |d
|===
```
A table within a table within a table cannot be converted because asciidoc only
supports two levels of tables.
The table on level 3 is thus converted to level 2 and a warning is produced
```
% pandoc -f html -t asciidoc --verbose
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title> NestedTables </title>
</head>
<body>
<table>
<tr>
<td>
<table> <tr>
<td> a1 </td>
<td>
<table> <tr> <td> 1 </td> <td> 2 </td> </tr> </table>
</td>
</tr> </table>
</td>
<td>b</td>
</tr>
<tr>
<td>c</td> <td>d </td>
</tr>
</table>
</body>
</html>
^D
[INFO] Not rendering Table ("",[],[]) (Caption Nothing []) [(AlignDefault,ColWidth 0.5),(AlignDefault,ColWidth 0.5)] (TableHead ("",[],[]) []) [TableBody ("",[],[]) (RowHeadColumns 0) [] [Row ("",[],[]) [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "a1"]],Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Table ("",[],[]) (Caption Nothing []) [(AlignDefault,ColWidthDefault),(AlignDefault,ColWidthDefault)] (TableHead ("",[],[]) []) [TableBody ("",[],[]) (RowHeadColumns 0) [] [Row ("",[],[]) [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "1"]],Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "2"]]]]] (TableFoot ("",[],[]) [])]]]] (TableFoot ("",[],[]) [])
[width="100%",cols="50%,50%",]
|===
a|
[width="100%",cols="50%,50%",]
!===
!a1 !
!===
|b
|c |d
|===
```