git.iko.soy/typeable/pandoc
on master help sign in
Docx writer: allow multirow table headers
17d9640Albert Krewinkel
src/Text/Pandoc/Writers/Docx/Table.hs+25−17
@@ -42,11 +42,12 @@ tableToOpenXML blocksToOpenXML gridTable = do
42 then return []
42 then return []
43 else withParaPropM (pStyleM "Table Caption")
43 else withParaPropM (pStyleM "Table Caption")
44 $ blocksToOpenXML captionBlocks
44 $ blocksToOpenXML captionBlocks
45− head' <- cellGridToOpenXML blocksToOpenXML thead
45+ head' <- cellGridToOpenXML blocksToOpenXML HeadRow thead
46− bodies <- mapM (cellGridToOpenXML blocksToOpenXML) tbodies
46+ bodies <- mapM (cellGridToOpenXML blocksToOpenXML BodyRow) tbodies
47− foot' <- cellGridToOpenXML blocksToOpenXML tfoot
47+ foot' <- cellGridToOpenXML blocksToOpenXML FootRow tfoot
48
48
49 let hasHeader = not . null . indices . partRowAttrs $ thead
49 let hasHeader = not . null . indices . partRowAttrs $ thead
50+ let hasFooter = not . null . indices . partRowAttrs $ tfoot
50 -- for compatibility with Word <= 2007, we include a val with a bitmask
51 -- for compatibility with Word <= 2007, we include a val with a bitmask
51 -- 0×0020 Apply first row conditional formatting
52 -- 0×0020 Apply first row conditional formatting
52 -- 0×0040 Apply last row conditional formatting
53 -- 0×0040 Apply last row conditional formatting
@@ -61,7 +62,7 @@ tableToOpenXML blocksToOpenXML gridTable = do
61 ( mknode "w:tblStyle" [("w:val","Table")] () :
62 ( mknode "w:tblStyle" [("w:val","Table")] () :
62 mknode "w:tblW" tblWattr () :
63 mknode "w:tblW" tblWattr () :
63 mknode "w:tblLook" [("w:firstRow",if hasHeader then "1" else "0")
64 mknode "w:tblLook" [("w:firstRow",if hasHeader then "1" else "0")
64− ,("w:lastRow","0")
65+ ,("w:lastRow",if hasFooter then "1" else "0")
65 ,("w:firstColumn","0")
66 ,("w:firstColumn","0")
66 ,("w:lastColumn","0")
67 ,("w:lastColumn","0")
67 ,("w:noHBand","0")
68 ,("w:noHBand","0")
@@ -77,6 +78,9 @@ tableToOpenXML blocksToOpenXML gridTable = do
77 modify $ \s -> s { stInTable = False }
78 modify $ \s -> s { stInTable = False }
78 return $ captionXml ++ [Elem tbl]
79 return $ captionXml ++ [Elem tbl]
79
80
81+-- | Parts of a table
82+data RowType = HeadRow | BodyRow | FootRow
83+
80alignmentToString :: Alignment -> Text
84alignmentToString :: Alignment -> Text
81alignmentToString = \case
85alignmentToString = \case
82 AlignLeft -> "left"
86 AlignLeft -> "left"
@@ -104,22 +108,23 @@ tableLayout specs =
104 , [ ("w:type", "pct"), ("w:w", tshow rowwidth) ])
108 , [ ("w:type", "pct"), ("w:w", tshow rowwidth) ])
105
109
106cellGridToOpenXML :: PandocMonad m
110cellGridToOpenXML :: PandocMonad m
107− => ([Block] -> WS m [Content])
111+ => ([Block] -> WS m [Content])
112+ -> RowType
108− -> Part
113+ -> Part
109− -> WS m [Element]
114+ -> WS m [Element]
110−cellGridToOpenXML blocksToOpenXML part@(Part _ _ rowAttrs) =
115+cellGridToOpenXML blocksToOpenXML rowType part@(Part _ _ rowAttrs) =
111 if null (indices rowAttrs)
116 if null (indices rowAttrs)
112 then return mempty
117 then return mempty
113− else mapM (rowToOpenXML blocksToOpenXML) $ partToRows part
118+ else mapM (rowToOpenXML blocksToOpenXML) $ partToRows rowType part
114
119
115data OOXMLCell
120data OOXMLCell
116 = OOXMLCell Attr Alignment RowSpan ColSpan [Block]
121 = OOXMLCell Attr Alignment RowSpan ColSpan [Block]
117 | OOXMLCellMerge ColSpan
122 | OOXMLCellMerge ColSpan
118
123
119−data OOXMLRow = OOXMLRow Attr [OOXMLCell]
124+data OOXMLRow = OOXMLRow RowType Attr [OOXMLCell]
120
125
121−partToRows :: Part -> [OOXMLRow]
126+partToRows :: RowType -> Part -> [OOXMLRow]
122−partToRows part =
127+partToRows rowType part =
123 let
128 let
124 toOOXMLCell :: RowIndex -> ColIndex -> GridCell -> [OOXMLCell]
129 toOOXMLCell :: RowIndex -> ColIndex -> GridCell -> [OOXMLCell]
125 toOOXMLCell ridx cidx = \case
130 toOOXMLCell ridx cidx = \case
@@ -132,7 +137,7 @@ partToRows part =
132 " at index " ++ show idx'
137 " at index " ++ show idx'
133 _ -> mempty
138 _ -> mempty
134 mkRow :: (RowIndex, Attr) -> OOXMLRow
139 mkRow :: (RowIndex, Attr) -> OOXMLRow
135− mkRow (ridx, attr) = OOXMLRow attr
140+ mkRow (ridx, attr) = OOXMLRow rowType attr
136 . concatMap (uncurry $ toOOXMLCell ridx)
141 . concatMap (uncurry $ toOOXMLCell ridx)
137 . assocs
142 . assocs
138 . rowArray ridx
143 . rowArray ridx
@@ -143,12 +148,17 @@ rowToOpenXML :: PandocMonad m
143 => ([Block] -> WS m [Content])
148 => ([Block] -> WS m [Content])
144 -> OOXMLRow
149 -> OOXMLRow
145 -> WS m Element
150 -> WS m Element
146−rowToOpenXML blocksToOpenXML (OOXMLRow _attr cells) = do
151+rowToOpenXML blocksToOpenXML (OOXMLRow rowType _attr cells) = do
147 xmlcells <- mapM (ooxmlCellToOpenXML blocksToOpenXML) cells
152 xmlcells <- mapM (ooxmlCellToOpenXML blocksToOpenXML) cells
153+ let addTrPr = case rowType of
154+ HeadRow -> (mknode "w:trPr" []
155+ [mknode "w:tblHeader" [("w:val", "true")] ()] :)
156+ BodyRow -> id
157+ FootRow -> id
148 -- let align' = case align of
158 -- let align' = case align of
149 -- AlignDefault -> colAlign
159 -- AlignDefault -> colAlign
150 -- _ -> align
160 -- _ -> align
151− return $ mknode "w:tr" [] xmlcells
161+ return $ mknode "w:tr" [] (addTrPr xmlcells)
152
162
153ooxmlCellToOpenXML :: PandocMonad m
163ooxmlCellToOpenXML :: PandocMonad m
154 => ([Block] -> WS m [Content])
164 => ([Block] -> WS m [Content])
@@ -161,8 +171,6 @@ ooxmlCellToOpenXML blocksToOpenXML = \case
161 , mknode "w:vMerge" [("w:val", "continue")] () ]
171 , mknode "w:vMerge" [("w:val", "continue")] () ]
162 , mknode "w:p" [] [mknode "w:pPr" [] ()]]
172 , mknode "w:p" [] [mknode "w:pPr" [] ()]]
163 OOXMLCell _attr align rowspan (ColSpan colspan) contents -> do
173 OOXMLCell _attr align rowspan (ColSpan colspan) contents -> do
164− -- we handle rowspans via 'leftpad', so we can ignore those here
165−
166 compactStyle <- pStyleM "Compact"
174 compactStyle <- pStyleM "Compact"
167 es <- withParaProp (alignmentFor align) $ blocksToOpenXML contents
175 es <- withParaProp (alignmentFor align) $ blocksToOpenXML contents
168 -- Table cells require a <w:p> element, even an empty one!
176 -- Table cells require a <w:p> element, even an empty one!
test/docx/golden/table_with_list_cell.docx

Binary file not shown.

test/docx/golden/tables.docx

Binary file not shown.