From 854b7332d9f3044be15344fd57637f15b482f7e9 Mon Sep 17 00:00:00 2001 From: Tuong Nguyen Manh Date: Mon, 29 Dec 2025 01:13:06 +0100 Subject: ODT reader: Add table row and column spans (#11366) Parse the number-rows-spanned and number-columns-spanned attributes to create Cells for the Table. --- src/Text/Pandoc/Readers/ODT/ContentReader.hs | 24 +++-- test/Tests/Readers/ODT.hs | 1 + test/odt/native/tableWithSpans.native | 134 +++++++++++++++++++++++++++ test/odt/odt/tableWithSpans.odt | Bin 0 -> 10695 bytes 4 files changed, 149 insertions(+), 10 deletions(-) create mode 100644 test/odt/native/tableWithSpans.native create mode 100644 test/odt/odt/tableWithSpans.odt diff --git a/src/Text/Pandoc/Readers/ODT/ContentReader.hs b/src/Text/Pandoc/Readers/ODT/ContentReader.hs index b9778bdd3..e5f1a4822 100644 --- a/src/Text/Pandoc/Readers/ODT/ContentReader.hs +++ b/src/Text/Pandoc/Readers/ODT/ContentReader.hs @@ -794,42 +794,46 @@ read_citation = matchingElement NsText "bibliography-mark" -- read_table :: BlockMatcher read_table = matchingElement NsTable "table" - $ liftA simpleTable' + $ liftA table' $ (matchChildContent' [read_table_header]) &&& - (matchChildContent' [read_table_row]) + (matchChildContent' [read_table_row]) --- | A simple table without a caption. -simpleTable' :: ([[Blocks]], [[Blocks]]) -> Blocks -simpleTable' (headers, rows) = +-- | A table without a caption. +table' :: ([[Cell]], [[Cell]]) -> Blocks +table' (headers, rows) = table emptyCaption (replicate numcols defaults) th [tb] tf where defaults = (AlignDefault, ColWidthDefault) numcols = maximum $ map length $ headers ++ rows - toRow = Row nullAttr . map simpleCell + toRow = Row nullAttr th = TableHead nullAttr $ map toRow headers tb = TableBody nullAttr 0 [] $ map toRow rows tf = TableFoot nullAttr [] -- -read_table_header :: ElementMatcher [[Blocks]] +read_table_header :: ElementMatcher [[Cell]] read_table_header = matchingElement NsTable "table-header-rows" $ matchChildContent' [ read_table_row ] -- -read_table_row :: ElementMatcher [[Blocks]] +read_table_row :: ElementMatcher [[Cell]] read_table_row = matchingElement NsTable "table-row" $ liftA (:[]) $ matchChildContent' [ read_table_cell ] -- -read_table_cell :: ElementMatcher [Blocks] +read_table_cell :: ElementMatcher [Cell] read_table_cell = matchingElement NsTable "table-cell" - $ liftA (compactify.(:[])) + $ liftA3 cell' + (readAttrWithDefault NsTable "number-rows-spanned" 1 >>^ RowSpan) + (readAttrWithDefault NsTable "number-columns-spanned" 1 >>^ ColSpan) $ matchChildContent' [ read_paragraph , read_list ] + where + cell' rowSpan colSpan blocks = map (cell AlignDefault rowSpan colSpan) $ compactify [blocks] ---------------------- -- Frames diff --git a/test/Tests/Readers/ODT.hs b/test/Tests/Readers/ODT.hs index a5e2dc009..dcca9237d 100644 --- a/test/Tests/Readers/ODT.hs +++ b/test/Tests/Readers/ODT.hs @@ -186,6 +186,7 @@ namesOfTestsComparingToNative = [ "blockquote" -- , "table" , "textMixedStyles" , "tableWithContents" + , "tableWithSpans" , "unicode" , "unorderedList" , "unorderedListHeader" diff --git a/test/odt/native/tableWithSpans.native b/test/odt/native/tableWithSpans.native new file mode 100644 index 000000000..6faaebad9 --- /dev/null +++ b/test/odt/native/tableWithSpans.native @@ -0,0 +1,134 @@ +[ Table + ( "" , [] , [] ) + (Caption Nothing []) + [ ( AlignDefault , ColWidthDefault ) + , ( AlignDefault , ColWidthDefault ) + , ( AlignDefault , ColWidthDefault ) + ] + (TableHead + ( "" , [] , [] ) + [ Row + ( "" , [] , [] ) + [ Cell + ( "" , [] , [] ) + AlignDefault + (RowSpan 2) + (ColSpan 1) + [ Plain + [ Str "H1" + , Space + , Str "Rowspan" + , Space + , Str "2" + ] + ] + , Cell + ( "" , [] , [] ) + AlignDefault + (RowSpan 1) + (ColSpan 1) + [ Plain [ Str "H1-2" ] ] + , Cell + ( "" , [] , [] ) + AlignDefault + (RowSpan 1) + (ColSpan 1) + [ Plain [ Str "H1-3" ] ] + ] + , Row + ( "" , [] , [] ) + [ Cell + ( "" , [] , [] ) + AlignDefault + (RowSpan 1) + (ColSpan 2) + [ Plain [ Str "H2-2/3" ] ] + ] + ]) + [ TableBody + ( "" , [] , [] ) + (RowHeadColumns 0) + [] + [ Row + ( "" , [] , [] ) + [ Cell + ( "" , [] , [] ) + AlignDefault + (RowSpan 1) + (ColSpan 1) + [ Plain [ Str "B1-1" ] ] + , Cell + ( "" , [] , [] ) + AlignDefault + (RowSpan 1) + (ColSpan 1) + [ Plain [ Str "B1-2" ] ] + , Cell + ( "" , [] , [] ) + AlignDefault + (RowSpan 3) + (ColSpan 1) + [ Plain [ Str "Rowspan" , Space , Str "3" ] ] + ] + , Row + ( "" , [] , [] ) + [ Cell + ( "" , [] , [] ) + AlignDefault + (RowSpan 1) + (ColSpan 1) + [ Plain [ Str "B2-1" ] ] + , Cell + ( "" , [] , [] ) + AlignDefault + (RowSpan 1) + (ColSpan 1) + [ Plain [ Str "B2-2" ] ] + ] + , Row + ( "" , [] , [] ) + [ Cell + ( "" , [] , [] ) + AlignDefault + (RowSpan 1) + (ColSpan 2) + [ Plain [ Str "Columnspan" , Space , Str "2" ] ] + ] + , Row + ( "" , [] , [] ) + [ Cell + ( "" , [] , [] ) + AlignDefault + (RowSpan 1) + (ColSpan 1) + [ Plain [ Str "B4-1" ] ] + , Cell + ( "" , [] , [] ) + AlignDefault + (RowSpan 2) + (ColSpan 2) + [ Plain + [ Str "Columnspan" + , Space + , Str "&" + , Space + , Str "Rowspan" + , Space + , Str "2" + ] + ] + ] + , Row + ( "" , [] , [] ) + [ Cell + ( "" , [] , [] ) + AlignDefault + (RowSpan 1) + (ColSpan 1) + [ Plain [ Str "B5-1" ] ] + ] + ] + ] + (TableFoot ( "" , [] , [] ) []) +, Para [] +] diff --git a/test/odt/odt/tableWithSpans.odt b/test/odt/odt/tableWithSpans.odt new file mode 100644 index 000000000..f37e0b6b5 Binary files /dev/null and b/test/odt/odt/tableWithSpans.odt differ -- cgit v1.2.3