diff options
| author | John MacFarlane <[email protected]> | 2023-05-08 13:09:04 -0700 |
|---|---|---|
| committer | John MacFarlane <[email protected]> | 2023-05-08 13:09:04 -0700 |
| commit | 05ad84a0c6c027c2c78bdb3ec0e25864d8725efd (patch) | |
| tree | ab029df7d958dc6b3012ab2f185aa99e9a2da133 /src | |
| parent | ca5940bf2c36e4329cf6bc726763817e928a30db (diff) | |
LaTeX writer: better fix for colspecs for multicolumn table.
Improves on the last commit; closes #8831.
Diffstat (limited to 'src')
| -rw-r--r-- | src/Text/Pandoc/Writers/LaTeX/Table.hs | 88 |
1 files changed, 54 insertions, 34 deletions
diff --git a/src/Text/Pandoc/Writers/LaTeX/Table.hs b/src/Text/Pandoc/Writers/LaTeX/Table.hs index 6ebcaa559..1d9b117ca 100644 --- a/src/Text/Pandoc/Writers/LaTeX/Table.hs +++ b/src/Text/Pandoc/Writers/LaTeX/Table.hs @@ -47,6 +47,11 @@ tableToLaTeX :: PandocMonad m tableToLaTeX inlnsToLaTeX blksToLaTeX tbl = do let (Ann.Table (ident, _, _) caption specs thead tbodies tfoot) = tbl CaptionDocs capt captNotes <- captionToLaTeX inlnsToLaTeX caption ident + let isSimpleTable = all (all isSimpleCell) $ mconcat + [ headRows thead + , concatMap bodyRows tbodies + , footRows tfoot + ] let removeNote (Note _) = Span ("", [], []) [] removeNote x = x let colCount = ColumnCount $ length specs @@ -56,7 +61,7 @@ tableToLaTeX inlnsToLaTeX blksToLaTeX tbl = do -- making the caption part of the first head. The downside is that we must -- duplicate the header rows for this. head' <- do - let mkHead = headToLaTeX blksToLaTeX colCount + let mkHead = headToLaTeX blksToLaTeX isSimpleTable colCount case (not $ isEmpty capt, not $ isEmptyHead thead) of (False, False) -> return "\\toprule\\noalign{}" (False, True) -> mkHead thead @@ -66,20 +71,21 @@ tableToLaTeX inlnsToLaTeX blksToLaTeX tbl = do firsthead <- mkHead thead repeated <- mkHead (walk removeNote thead) return $ capt $$ firsthead $$ "\\endfirsthead" $$ repeated - rows' <- mapM (rowToLaTeX blksToLaTeX colCount BodyCell) $ + rows' <- mapM (rowToLaTeX blksToLaTeX isSimpleTable colCount BodyCell) $ mconcat (map bodyRows tbodies) foot' <- if isEmptyFoot tfoot then pure empty else do - lastfoot <- mapM (rowToLaTeX blksToLaTeX colCount BodyCell) $ - footRows tfoot + lastfoot <- mapM + (rowToLaTeX blksToLaTeX isSimpleTable colCount BodyCell) $ + footRows tfoot pure $ "\\midrule\\noalign{}" $$ vcat lastfoot modify $ \s -> s{ stTable = True } notes <- notesToLaTeX <$> gets stNotes beamer <- gets stBeamer return $ "\\begin{longtable}[]" <> - braces ("@{}" <> colDescriptors tbl <> "@{}") + braces ("@{}" <> colDescriptors isSimpleTable tbl <> "@{}") -- the @{} removes extra space at beginning and end $$ head' $$ "\\endhead" @@ -102,20 +108,26 @@ tableToLaTeX inlnsToLaTeX blksToLaTeX tbl = do $$ captNotes $$ notes +isSimpleCell :: Ann.Cell -> Bool +isSimpleCell (Ann.Cell _ _ (Cell _attr _align _rowspan _colspan blocks)) = + case blocks of + [Para _] -> True + [Plain _] -> True + [] -> True + _ -> False + + + -- | Total number of columns in a table. newtype ColumnCount = ColumnCount Int -- | Creates column descriptors for the table. -colDescriptors :: Ann.Table -> Doc Text -colDescriptors (Ann.Table _attr _caption specs thead tbodies tfoot) = +colDescriptors :: Bool -> Ann.Table -> Doc Text +colDescriptors isSimpleTable + (Ann.Table _attr _caption specs _thead _tbodies _tfoot) = let (aligns, widths) = unzip specs defaultWidthsOnly = all (== ColWidthDefault) widths - isSimpleTable = all (all isSimpleCell) $ mconcat - [ headRows thead - , concatMap bodyRows tbodies - , footRows tfoot - ] relativeWidths = if defaultWidthsOnly then replicate (length specs) @@ -136,13 +148,6 @@ colDescriptors (Ann.Table _attr _caption specs thead tbodies tfoot) = ((numcols - 1) * 2) width - isSimpleCell (Ann.Cell _ _ (Cell _attr _align _rowspan _colspan blocks)) = - case blocks of - [Para _] -> True - [Plain _] -> True - [] -> True - _ -> False - toRelWidth ColWidthDefault = 0 toRelWidth (ColWidth w) = w @@ -188,24 +193,29 @@ type BlocksWriter m = [Block] -> LW m (Doc Text) headToLaTeX :: PandocMonad m => BlocksWriter m + -> Bool -> ColumnCount -> Ann.TableHead -> LW m (Doc Text) -headToLaTeX blocksWriter colCount (Ann.TableHead _attr headerRows) = do +headToLaTeX blocksWriter isSimpleTable + colCount (Ann.TableHead _attr headerRows) = do rowsContents <- - mapM (rowToLaTeX blocksWriter colCount HeaderCell . headerRowCells) + mapM (rowToLaTeX blocksWriter isSimpleTable + colCount HeaderCell . headerRowCells) headerRows return ("\\toprule\\noalign{}" $$ vcat rowsContents $$ "\\midrule\\noalign{}") -- | Converts a row of table cells into a LaTeX row. rowToLaTeX :: PandocMonad m => BlocksWriter m + -> Bool -> ColumnCount -> CellType -> [Ann.Cell] -> LW m (Doc Text) -rowToLaTeX blocksWriter colCount celltype row = do - cellsDocs <- mapM (cellToLaTeX blocksWriter colCount celltype) (fillRow row) +rowToLaTeX blocksWriter isSimpleTable colCount celltype row = do + cellsDocs <- mapM (cellToLaTeX blocksWriter isSimpleTable + colCount celltype) (fillRow row) return $ hsep (intersperse "&" cellsDocs) <> " \\\\" -- | Pads row with empty cells to adjust for rowspans above this row. @@ -280,11 +290,12 @@ displayMathToInline x = x cellToLaTeX :: PandocMonad m => BlocksWriter m + -> Bool -> ColumnCount -> CellType -> Ann.Cell -> LW m (Doc Text) -cellToLaTeX blockListToLaTeX colCount celltype annotatedCell = do +cellToLaTeX blockListToLaTeX isSimpleTable colCount celltype annotatedCell = do let (Ann.Cell specs colnum cell) = annotatedCell let colWidths = NonEmpty.map snd specs let hasWidths = NonEmpty.head colWidths /= ColWidthDefault @@ -329,7 +340,8 @@ cellToLaTeX blockListToLaTeX colCount celltype annotatedCell = do let inMultiColumn x = case colspan of (ColSpan 1) -> x (ColSpan n) -> - let colDescr = multicolumnDescriptor align + let colDescr = multicolumnDescriptor isSimpleTable + align colWidths colCount colnum @@ -346,12 +358,14 @@ cellToLaTeX blockListToLaTeX colCount celltype annotatedCell = do return . inMultiColumn . inMultiRow $ result -- | Returns the width of a cell spanning @n@ columns. -multicolumnDescriptor :: Alignment +multicolumnDescriptor :: Bool + -> Alignment -> NonEmpty ColWidth -> ColumnCount -> Ann.ColNumber -> Text -multicolumnDescriptor align +multicolumnDescriptor isSimpleTable + align colWidths (ColumnCount numcols) (Ann.ColNumber colnum) = @@ -364,13 +378,19 @@ multicolumnDescriptor align -- no column separators at beginning of first and end of last column. skipColSep = "@{}" :: String in T.pack $ - printf "%s>{%s\\arraybackslash}p{(\\columnwidth - %d\\tabcolsep) * \\real{%0.4f} + %d\\tabcolsep}%s" - (if colnum == 0 then skipColSep else "") - (T.unpack (alignCommand align)) - (2 * (numcols - 1)) - width - (2 * (colspan - 1)) - (if colnum + colspan >= numcols then skipColSep else "") + if isSimpleTable + then printf "%s%s%s" + (if colnum == 0 then skipColSep else "") + (T.unpack (colAlign align)) + (if colnum + colspan >= numcols then skipColSep else "") + + else printf "%s>{%s\\arraybackslash}p{(\\columnwidth - %d\\tabcolsep) * \\real{%0.4f} + %d\\tabcolsep}%s" + (if colnum == 0 then skipColSep else "") + (T.unpack (alignCommand align)) + (2 * (numcols - 1)) + width + (2 * (colspan - 1)) + (if colnum + colspan >= numcols then skipColSep else "") -- | Perform a conversion, assuming that the context is a minipage. inMinipage :: Monad m => LW m a -> LW m a |
