git.iko.soy/typeable/pandoc
on master help sign in
OpenDocument writer: New table cell support with row and column spans (#6682)

Unit tests only verify column spans at this point. Co-authored-by: Nils Carlson <nils.carlson@ludd.ltu.se>

commit4f13c0e25e7c97c0590944718a65147cf2c5d07a authorNils Carlson <nils@nilscarlson.se> dateThu 24 Sep 2020, 16:31 (6 years ago) parent1f707da
2 files changed+213−26
src/Text/Pandoc/Writers/OpenDocument.hs+56−26 test/command/table-with-column-span.md+157
src/Text/Pandoc/Writers/OpenDocument.hs+56−26
@@ -32,11 +32,12 @@ import qualified Text.Pandoc.Builder as B
3232import Text.Pandoc.Logging
3333import Text.Pandoc.Options
3434import Text.DocLayout
35−import Text.Pandoc.Shared (linesToPara, tshow)
35+import Text.Pandoc.Shared (linesToPara, tshow, blocksToInlines)
3636import Text.Pandoc.Templates (renderTemplate)
3737import qualified Text.Pandoc.Translations as Term (Term(Figure, Table))
3838import Text.Pandoc.Writers.Math
3939import Text.Pandoc.Writers.Shared
40+import qualified Text.Pandoc.Writers.AnnotatedTable as Ann
4041import Text.Pandoc.XML
4142import Text.Printf (printf)
4243
@@ -371,9 +372,7 @@ blockToOpenDocument o bs
371372 | BulletList b <- bs = setFirstPara >> bulletListToOpenDocument o b
372373 | OrderedList a b <- bs = setFirstPara >> orderedList a b
373374 | CodeBlock _ s <- bs = setFirstPara >> preformatted s
374− | Table _ bc s th tb tf
375− <- bs = let (c, a, w, h, r) = toLegacyTable bc s th tb tf
376− in setFirstPara >> table c a w h r
375+ | Table a bc s th tb tf <- bs = setFirstPara >> table (Ann.toTable a bc s th tb tf)
377376 | HorizontalRule <- bs = setFirstPara >> return (selfClosingTag "text:p"
378377 [ ("text:style-name", "Horizontal_20_Line") ])
379378 | RawBlock f s <- bs = if f == Format "opendocument"
@@ -396,29 +395,32 @@ blockToOpenDocument o bs
396395 orderedList a b = do (ln,pn) <- newOrderedListStyle (isTightList b) a
397396 inTags True "text:list" [ ("text:style-name", "L" <> tshow ln)]
398397 <$> orderedListToOpenDocument o pn b
399− table c a w h r = do
398+ table :: PandocMonad m => Ann.Table -> OD m (Doc Text)
399+ table (Ann.Table _ (Caption _ c) colspecs thead tbodies _) = do
400400 tn <- length <$> gets stTableStyles
401401 pn <- length <$> gets stParaStyles
402402 let genIds = map chr [65..]
403403 name = "Table" <> tshow (tn + 1)
404− columnIds = zip genIds w
404+ (aligns, mwidths) = unzip colspecs
405+ fromWidth (ColWidth w) | w > 0 = w
406+ fromWidth _ = 0
407+ widths = map fromWidth mwidths
408+ columnIds = zip genIds widths
405409 mkColumn n = selfClosingTag "table:table-column" [("table:style-name", name <> "." <> T.singleton (fst n))]
406410 columns = map mkColumn columnIds
407− paraHStyles = paraTableStyles "Heading" pn a
408− paraStyles = paraTableStyles "Contents" (pn + length (newPara paraHStyles)) a
411+ paraHStyles = paraTableStyles "Heading" pn aligns
412+ paraStyles = paraTableStyles "Contents" (pn + length (newPara paraHStyles)) aligns
409413 newPara = map snd . filter (not . isEmpty . snd)
410414 addTableStyle $ tableStyle tn columnIds
411415 mapM_ addParaStyle . newPara $ paraHStyles ++ paraStyles
412416 captionDoc <- if null c
413417 then return empty
414− else inlinesToOpenDocument o c >>=
418+ else inlinesToOpenDocument o (blocksToInlines c) >>=
415419 if isEnabled Ext_native_numbering o
416420 then numberedTableCaption
417421 else unNumberedCaption "TableCaption"
418− th <- if all null h
419− then return empty
420− else colHeadsToOpenDocument o (map fst paraHStyles) h
421− tr <- mapM (tableRowToOpenDocument o (map fst paraStyles)) r
422+ th <- colHeadsToOpenDocument o (map fst paraHStyles) thead
423+ tr <- mapM (tableBodyToOpenDocument o (map fst paraStyles)) tbodies
422424 let tableDoc = inTags True "table:table" [
423425 ("table:name" , name)
424426 , ("table:style-name", name)
@@ -464,26 +466,54 @@ unNumberedCaption :: Monad m => Text -> Doc Text -> OD m (Doc Text)
464466unNumberedCaption style caption = return $ inParagraphTagsWithStyle style caption
465467
466468colHeadsToOpenDocument :: PandocMonad m
467− => WriterOptions -> [Text] -> [[Block]]
469+ => WriterOptions -> [Text] -> Ann.TableHead
468470 -> OD m (Doc Text)
469−colHeadsToOpenDocument o ns hs =
470− inTagsIndented "table:table-header-rows" . inTagsIndented "table:table-row" . vcat <$>
471− mapM (tableItemToOpenDocument o "TableHeaderRowCell") (zip ns hs)
471+colHeadsToOpenDocument o ns (Ann.TableHead _ hs) =
472+ case hs of
473+ [] -> return empty
474+ (x:_) ->
475+ let (Ann.HeaderRow _ _ c) = x
476+ in inTagsIndented "table:table-header-rows" .
477+ inTagsIndented "table:table-row" .
478+ vcat <$> mapM (tableItemToOpenDocument o "TableHeaderRowCell") (zip ns c)
479+
480+tableBodyToOpenDocument:: PandocMonad m
481+ => WriterOptions -> [Text] -> Ann.TableBody
482+ -> OD m (Doc Text)
483+tableBodyToOpenDocument o ns tb =
484+ let (Ann.TableBody _ _ _ r) = tb
485+ in vcat <$> mapM (tableRowToOpenDocument o ns) r
472486
473487tableRowToOpenDocument :: PandocMonad m
474− => WriterOptions -> [Text] -> [[Block]]
488+ => WriterOptions -> [Text] -> Ann.BodyRow
475489 -> OD m (Doc Text)
476−tableRowToOpenDocument o ns cs =
477− inTagsIndented "table:table-row" . vcat <$>
478− mapM (tableItemToOpenDocument o "TableRowCell") (zip ns cs)
490+tableRowToOpenDocument o ns r =
491+ let (Ann.BodyRow _ _ _ c ) = r
492+ in inTagsIndented "table:table-row" . vcat <$>
493+ mapM (tableItemToOpenDocument o "TableRowCell") (zip ns c)
494+
495+
496+colspanAttrib :: ColSpan -> [(Text, Text)]
497+colspanAttrib cs =
498+ case cs of
499+ ColSpan 1 -> mempty
500+ ColSpan n -> [("table:number-columns-spanned", tshow n)]
501+
502+rowspanAttrib :: RowSpan -> [(Text, Text)]
503+rowspanAttrib rs =
504+ case rs of
505+ RowSpan 1 -> mempty
506+ RowSpan n -> [("table:number-rows-spanned", tshow n)]
479507
480508tableItemToOpenDocument :: PandocMonad m
481− => WriterOptions -> Text -> (Text,[Block])
509+ => WriterOptions -> Text -> (Text,Ann.Cell)
482510 -> OD m (Doc Text)
483−tableItemToOpenDocument o s (n,i) =
484− let a = [ ("table:style-name" , s )
485− , ("office:value-type", "string" )
486− ]
511+tableItemToOpenDocument o s (n,c) =
512+ let (Ann.Cell _colspecs _colnum (Cell _ _ rs cs i) ) = c
513+ csa = colspanAttrib cs
514+ rsa = rowspanAttrib rs
515+ a = [ ("table:style-name" , s )
516+ , ("office:value-type", "string" ) ] ++ csa ++ rsa
487517 in inTags True "table:table-cell" a <$>
488518 withParagraphStyle o n (map plainToPara i)
489519
test/command/table-with-column-span.md+157
@@ -117,3 +117,160 @@
117117 (TableFoot ("",[],[])
118118 [])]
119119```
120+```
121+% pandoc -f native -t opendocument --quiet
122+[Table ("",[],[]) (Caption Nothing
123+ [])
124+ [(AlignDefault,ColWidth 6.25e-2)
125+ ,(AlignDefault,ColWidth 6.25e-2)
126+ ,(AlignDefault,ColWidth 6.25e-2)
127+ ,(AlignDefault,ColWidth 6.25e-2)
128+ ,(AlignDefault,ColWidth 6.25e-2)
129+ ,(AlignDefault,ColWidth 6.25e-2)
130+ ,(AlignDefault,ColWidth 6.25e-2)
131+ ,(AlignDefault,ColWidth 6.25e-2)
132+ ,(AlignDefault,ColWidth 6.25e-2)
133+ ,(AlignDefault,ColWidth 6.25e-2)
134+ ,(AlignDefault,ColWidth 6.25e-2)
135+ ,(AlignDefault,ColWidth 6.25e-2)
136+ ,(AlignDefault,ColWidth 6.25e-2)
137+ ,(AlignDefault,ColWidth 6.25e-2)
138+ ,(AlignDefault,ColWidth 6.25e-2)
139+ ,(AlignDefault,ColWidth 6.25e-2)]
140+ (TableHead ("",[],[])
141+ [])
142+ [(TableBody ("",[],[]) (RowHeadColumns 0)
143+ []
144+ [Row ("",[],[])
145+ [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 8)
146+ [Para [Strong [Str "Octet",Space,Str "no.",Space,Str "1"]]]
147+ ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 8)
148+ [Para [Strong [Str "Octet",Space,Str "no.",Space,Str "2"]]]]
149+ ,Row ("",[],[])
150+ [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
151+ [Para [Str "16"]]
152+ ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
153+ [Para [Str "15"]]
154+ ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
155+ [Para [Str "14"]]
156+ ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
157+ [Para [Str "13"]]
158+ ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
159+ [Para [Str "12"]]
160+ ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
161+ [Para [Str "11"]]
162+ ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
163+ [Para [Str "10"]]
164+ ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
165+ [Para [Str "9"]]
166+ ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
167+ [Para [Str "8"]]
168+ ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
169+ [Para [Str "7"]]
170+ ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
171+ [Para [Str "6"]]
172+ ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
173+ [Para [Str "5"]]
174+ ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
175+ [Para [Str "4"]]
176+ ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
177+ [Para [Str "3"]]
178+ ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
179+ [Para [Str "2"]]
180+ ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
181+ [Para [Str "1"]]]
182+ ,Row ("",[],[])
183+ [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 8)
184+ [Para [Str "Code",Space,Str "A"]]
185+ ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 8)
186+ [Para [Str "Code",Space,Str "B"]]]])]
187+ (TableFoot ("",[],[])
188+ [])]
189+^D
190+<table:table table:name="Table1" table:style-name="Table1">
191+ <table:table-column table:style-name="Table1.A" />
192+ <table:table-column table:style-name="Table1.B" />
193+ <table:table-column table:style-name="Table1.C" />
194+ <table:table-column table:style-name="Table1.D" />
195+ <table:table-column table:style-name="Table1.E" />
196+ <table:table-column table:style-name="Table1.F" />
197+ <table:table-column table:style-name="Table1.G" />
198+ <table:table-column table:style-name="Table1.H" />
199+ <table:table-column table:style-name="Table1.I" />
200+ <table:table-column table:style-name="Table1.J" />
201+ <table:table-column table:style-name="Table1.K" />
202+ <table:table-column table:style-name="Table1.L" />
203+ <table:table-column table:style-name="Table1.M" />
204+ <table:table-column table:style-name="Table1.N" />
205+ <table:table-column table:style-name="Table1.O" />
206+ <table:table-column table:style-name="Table1.P" />
207+ <table:table-row>
208+ <table:table-cell table:style-name="TableRowCell" office:value-type="string" table:number-columns-spanned="8">
209+ <text:p text:style-name="Table_20_Contents"><text:span text:style-name="T1">Octet
210+ no. 1</text:span></text:p>
211+ </table:table-cell>
212+ <table:table-cell table:style-name="TableRowCell" office:value-type="string" table:number-columns-spanned="8">
213+ <text:p text:style-name="Table_20_Contents"><text:span text:style-name="T1">Octet
214+ no. 2</text:span></text:p>
215+ </table:table-cell>
216+ </table:table-row>
217+ <table:table-row>
218+ <table:table-cell table:style-name="TableRowCell" office:value-type="string">
219+ <text:p text:style-name="Table_20_Contents">16</text:p>
220+ </table:table-cell>
221+ <table:table-cell table:style-name="TableRowCell" office:value-type="string">
222+ <text:p text:style-name="Table_20_Contents">15</text:p>
223+ </table:table-cell>
224+ <table:table-cell table:style-name="TableRowCell" office:value-type="string">
225+ <text:p text:style-name="Table_20_Contents">14</text:p>
226+ </table:table-cell>
227+ <table:table-cell table:style-name="TableRowCell" office:value-type="string">
228+ <text:p text:style-name="Table_20_Contents">13</text:p>
229+ </table:table-cell>
230+ <table:table-cell table:style-name="TableRowCell" office:value-type="string">
231+ <text:p text:style-name="Table_20_Contents">12</text:p>
232+ </table:table-cell>
233+ <table:table-cell table:style-name="TableRowCell" office:value-type="string">
234+ <text:p text:style-name="Table_20_Contents">11</text:p>
235+ </table:table-cell>
236+ <table:table-cell table:style-name="TableRowCell" office:value-type="string">
237+ <text:p text:style-name="Table_20_Contents">10</text:p>
238+ </table:table-cell>
239+ <table:table-cell table:style-name="TableRowCell" office:value-type="string">
240+ <text:p text:style-name="Table_20_Contents">9</text:p>
241+ </table:table-cell>
242+ <table:table-cell table:style-name="TableRowCell" office:value-type="string">
243+ <text:p text:style-name="Table_20_Contents">8</text:p>
244+ </table:table-cell>
245+ <table:table-cell table:style-name="TableRowCell" office:value-type="string">
246+ <text:p text:style-name="Table_20_Contents">7</text:p>
247+ </table:table-cell>
248+ <table:table-cell table:style-name="TableRowCell" office:value-type="string">
249+ <text:p text:style-name="Table_20_Contents">6</text:p>
250+ </table:table-cell>
251+ <table:table-cell table:style-name="TableRowCell" office:value-type="string">
252+ <text:p text:style-name="Table_20_Contents">5</text:p>
253+ </table:table-cell>
254+ <table:table-cell table:style-name="TableRowCell" office:value-type="string">
255+ <text:p text:style-name="Table_20_Contents">4</text:p>
256+ </table:table-cell>
257+ <table:table-cell table:style-name="TableRowCell" office:value-type="string">
258+ <text:p text:style-name="Table_20_Contents">3</text:p>
259+ </table:table-cell>
260+ <table:table-cell table:style-name="TableRowCell" office:value-type="string">
261+ <text:p text:style-name="Table_20_Contents">2</text:p>
262+ </table:table-cell>
263+ <table:table-cell table:style-name="TableRowCell" office:value-type="string">
264+ <text:p text:style-name="Table_20_Contents">1</text:p>
265+ </table:table-cell>
266+ </table:table-row>
267+ <table:table-row>
268+ <table:table-cell table:style-name="TableRowCell" office:value-type="string" table:number-columns-spanned="8">
269+ <text:p text:style-name="Table_20_Contents">Code A</text:p>
270+ </table:table-cell>
271+ <table:table-cell table:style-name="TableRowCell" office:value-type="string" table:number-columns-spanned="8">
272+ <text:p text:style-name="Table_20_Contents">Code B</text:p>
273+ </table:table-cell>
274+ </table:table-row>
275+</table:table>
276+```