git.iko.soy/typeable/pandoc
on master help sign in
Docx writer: handle table header using styles.

Instead of hard-coding the border and header cell vertical alignment, we now let this be determined by the Table style, making use of Word's "conditional formatting" for the table's first row. For headerless tables, we use the tblLook element to tell Word not to apply conditional first-row formatting. Closes #7008.

commitc451207b08edc36fa5c2f1af5556a8d211e023ed authorJohn MacFarlane <jgm@berkeley.edu> dateTue 12 Jan 2021, 09:49 (6 years ago) parent4a223e6
34 files changed+35−17
data/docx/word/styles.xml+15 src/Text/Pandoc/Writers/Docx.hs+20−17 test/docx/golden/block_quotes.docx test/docx/golden/codeblock.docx test/docx/golden/comments.docx test/docx/golden/custom_style_no_reference.docx test/docx/golden/custom_style_preserve.docx test/docx/golden/definition_list.docx test/docx/golden/document-properties-short-desc.docx test/docx/golden/document-properties.docx test/docx/golden/headers.docx test/docx/golden/image.docx test/docx/golden/inline_code.docx test/docx/golden/inline_formatting.docx test/docx/golden/inline_images.docx test/docx/golden/link_in_notes.docx test/docx/golden/links.docx test/docx/golden/lists.docx test/docx/golden/lists_continuing.docx test/docx/golden/lists_multiple_initial.docx test/docx/golden/lists_restarting.docx test/docx/golden/nested_anchors_in_header.docx test/docx/golden/notes.docx test/docx/golden/raw-blocks.docx test/docx/golden/raw-bookmarks.docx test/docx/golden/table_one_row.docx test/docx/golden/table_with_list_cell.docx test/docx/golden/tables.docx test/docx/golden/track_changes_deletion.docx test/docx/golden/track_changes_insertion.docx test/docx/golden/track_changes_move.docx test/docx/golden/track_changes_scrubbed_metadata.docx test/docx/golden/unicode.docx test/docx/golden/verbatim_subsuper.docx
data/docx/word/styles.xml+15
@@ -350,6 +350,21 @@
350350 <w:right w:w="108" w:type="dxa" />
351351 </w:tblCellMar>
352352 </w:tblPr>
353+ <w:tblStylePr w:type="firstRow">
354+ <w:tblPr>
355+ <w:jc w:val="left"/>
356+ <w:tblInd w:w="0" w:type="dxa"/>
357+ </w:tblPr>
358+ <w:trPr>
359+ <w:jc w:val="left"/>
360+ </w:trPr>
361+ <w:tcPr>
362+ <w:vAlign w:val="bottom"/>
363+ <w:tcBorders>
364+ <w:bottom w:val="single"/>
365+ </w:tcBorders>
366+ </w:tcPr>
367+ </w:tblStylePr>
353368 </w:style>
354369 <w:style w:type="paragraph" w:customStyle="1" w:styleId="DefinitionTerm">
355370 <w:name w:val="Definition Term" />
src/Text/Pandoc/Writers/Docx.hs+20−17
@@ -1023,23 +1023,15 @@ blockToOpenXML' opts (Table _ blkCapt specs thead tbody tfoot) = do
10231023 _ -> es ++ [Elem $ mknode "w:p" [] ()]
10241024 headers' <- mapM cellToOpenXML $ zip aligns headers
10251025 rows' <- mapM (mapM cellToOpenXML . zip aligns) rows
1026− let borderProps = Elem $ mknode "w:tcPr" []
1027− [ mknode "w:tcBorders" []
1028− $ mknode "w:bottom" [("w:val","single")] ()
1029− , mknode "w:vAlign" [("w:val","bottom")] () ]
10301026 compactStyle <- pStyleM "Compact"
10311027 let emptyCell' = [Elem $ mknode "w:p" [] [mknode "w:pPr" [] [compactStyle]]]
1032− let mkcell border contents = mknode "w:tc" []
1033− $ [ borderProps | border ] ++
1034− if null contents
1035− then emptyCell'
1036− else contents
1037− let mkrow border cells =
1028+ let mkcell contents = mknode "w:tc" []
1029+ $ if null contents
1030+ then emptyCell'
1031+ else contents
1032+ let mkrow cells =
10381033 mknode "w:tr" [] $
1039− [ mknode "w:trPr" []
1040− [ mknode "w:cnfStyle" [("w:firstRow","1")] ()]
1041− | border]
1042− ++ map (mkcell border) cells
1034+ map mkcell cells
10431035 let textwidth = 7920 -- 5.5 in in twips, 1/20 pt
10441036 let fullrow = 5000 -- 100% specified in pct
10451037 let rowwidth = fullrow * sum widths
@@ -1047,6 +1039,15 @@ blockToOpenXML' opts (Table _ blkCapt specs thead tbody tfoot) = do
10471039 [("w:w", show (floor (textwidth * w) :: Integer))] ()
10481040 let hasHeader = not $ all null headers
10491041 modify $ \s -> s { stInTable = False }
1042+ -- for compatibility with Word <= 2007, we include a val with a bitmask
1043+ -- 0×0020 Apply first row conditional formatting
1044+ -- 0×0040 Apply last row conditional formatting
1045+ -- 0×0080 Apply first column conditional formatting
1046+ -- 0×0100 Apply last column conditional formatting
1047+ -- 0×0200 Do not apply row banding conditional formatting
1048+ -- 0×0400 Do not apply column banding conditional formattin
1049+ let tblLookVal :: Int
1050+ tblLookVal = if hasHeader then 0x20 else 0
10501051 return $
10511052 caption' ++
10521053 [Elem $
@@ -1059,15 +1060,17 @@ blockToOpenXML' opts (Table _ blkCapt specs thead tbody tfoot) = do
10591060 ,("w:firstColumn","0")
10601061 ,("w:lastColumn","0")
10611062 ,("w:noHBand","0")
1062− ,("w:noVBand","0")] () :
1063+ ,("w:noVBand","0")
1064+ ,("w:val", printf "%04x" tblLookVal)
1065+ ] () :
10631066 [ mknode "w:tblCaption" [("w:val", T.unpack captionStr)] ()
10641067 | not (null caption) ] )
10651068 : mknode "w:tblGrid" []
10661069 (if all (==0) widths
10671070 then []
10681071 else map mkgridcol widths)
1069− : [ mkrow True headers' | hasHeader ] ++
1070− map (mkrow False) rows'
1072+ : [ mkrow headers' | hasHeader ] ++
1073+ map mkrow rows'
10711074 )]
10721075blockToOpenXML' opts el
10731076 | BulletList lst <- el = addOpenXMLList BulletMarker lst
test/docx/golden/block_quotes.docx

Binary file not shown.

test/docx/golden/codeblock.docx

Binary file not shown.

test/docx/golden/comments.docx

Binary file not shown.

test/docx/golden/custom_style_no_reference.docx

Binary file not shown.

test/docx/golden/custom_style_preserve.docx

Binary file not shown.

test/docx/golden/definition_list.docx

Binary file not shown.

test/docx/golden/document-properties-short-desc.docx

Binary file not shown.

test/docx/golden/document-properties.docx

Binary file not shown.

test/docx/golden/headers.docx

Binary file not shown.

test/docx/golden/image.docx

Binary file not shown.

test/docx/golden/inline_code.docx

Binary file not shown.

test/docx/golden/inline_formatting.docx

Binary file not shown.

test/docx/golden/inline_images.docx

Binary file not shown.

test/docx/golden/link_in_notes.docx

Binary file not shown.

test/docx/golden/links.docx

Binary file not shown.

test/docx/golden/lists.docx

Binary file not shown.

test/docx/golden/lists_continuing.docx

Binary file not shown.

test/docx/golden/lists_multiple_initial.docx

Binary file not shown.

test/docx/golden/lists_restarting.docx

Binary file not shown.

test/docx/golden/nested_anchors_in_header.docx

Binary file not shown.

test/docx/golden/notes.docx

Binary file not shown.

test/docx/golden/raw-blocks.docx

Binary file not shown.

test/docx/golden/raw-bookmarks.docx

Binary file not shown.

test/docx/golden/table_one_row.docx

Binary file not shown.

test/docx/golden/table_with_list_cell.docx

Binary file not shown.

test/docx/golden/tables.docx

Binary file not shown.

test/docx/golden/track_changes_deletion.docx

Binary file not shown.

test/docx/golden/track_changes_insertion.docx

Binary file not shown.

test/docx/golden/track_changes_move.docx

Binary file not shown.

test/docx/golden/track_changes_scrubbed_metadata.docx

Binary file not shown.

test/docx/golden/unicode.docx

Binary file not shown.

test/docx/golden/verbatim_subsuper.docx

Binary file not shown.