git.iko.soy/typeable/pandoc
on master help sign in
OpenDocument writer: New table cell support with row and column spans (#6682)
4f13c0eNils Carlson
src/Text/Pandoc/Writers/OpenDocument.hs+56−26
@@ -32,11 +32,12 @@ import qualified Text.Pandoc.Builder as B
32import Text.Pandoc.Logging
32import Text.Pandoc.Logging
33import Text.Pandoc.Options
33import Text.Pandoc.Options
34import Text.DocLayout
34import Text.DocLayout
35−import Text.Pandoc.Shared (linesToPara, tshow)
35+import Text.Pandoc.Shared (linesToPara, tshow, blocksToInlines)
36import Text.Pandoc.Templates (renderTemplate)
36import Text.Pandoc.Templates (renderTemplate)
37import qualified Text.Pandoc.Translations as Term (Term(Figure, Table))
37import qualified Text.Pandoc.Translations as Term (Term(Figure, Table))
38import Text.Pandoc.Writers.Math
38import Text.Pandoc.Writers.Math
39import Text.Pandoc.Writers.Shared
39import Text.Pandoc.Writers.Shared
40+import qualified Text.Pandoc.Writers.AnnotatedTable as Ann
40import Text.Pandoc.XML
41import Text.Pandoc.XML
41import Text.Printf (printf)
42import Text.Printf (printf)
42
43
@@ -371,9 +372,7 @@ blockToOpenDocument o bs
371 | BulletList b <- bs = setFirstPara >> bulletListToOpenDocument o b
372 | BulletList b <- bs = setFirstPara >> bulletListToOpenDocument o b
372 | OrderedList a b <- bs = setFirstPara >> orderedList a b
373 | OrderedList a b <- bs = setFirstPara >> orderedList a b
373 | CodeBlock _ s <- bs = setFirstPara >> preformatted s
374 | 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)
377 | HorizontalRule <- bs = setFirstPara >> return (selfClosingTag "text:p"
376 | HorizontalRule <- bs = setFirstPara >> return (selfClosingTag "text:p"
378 [ ("text:style-name", "Horizontal_20_Line") ])
377 [ ("text:style-name", "Horizontal_20_Line") ])
379 | RawBlock f s <- bs = if f == Format "opendocument"
378 | RawBlock f s <- bs = if f == Format "opendocument"
@@ -396,29 +395,32 @@ blockToOpenDocument o bs
396 orderedList a b = do (ln,pn) <- newOrderedListStyle (isTightList b) a
395 orderedList a b = do (ln,pn) <- newOrderedListStyle (isTightList b) a
397 inTags True "text:list" [ ("text:style-name", "L" <> tshow ln)]
396 inTags True "text:list" [ ("text:style-name", "L" <> tshow ln)]
398 <$> orderedListToOpenDocument o pn b
397 <$> 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
400 tn <- length <$> gets stTableStyles
400 tn <- length <$> gets stTableStyles
401 pn <- length <$> gets stParaStyles
401 pn <- length <$> gets stParaStyles
402 let genIds = map chr [65..]
402 let genIds = map chr [65..]
403 name = "Table" <> tshow (tn + 1)
403 name = "Table" <> tshow (tn + 1)
404+ (aligns, mwidths) = unzip colspecs
405+ fromWidth (ColWidth w) | w > 0 = w
406+ fromWidth _ = 0
407+ widths = map fromWidth mwidths
404− columnIds = zip genIds w
408+ columnIds = zip genIds widths
405 mkColumn n = selfClosingTag "table:table-column" [("table:style-name", name <> "." <> T.singleton (fst n))]
409 mkColumn n = selfClosingTag "table:table-column" [("table:style-name", name <> "." <> T.singleton (fst n))]
406 columns = map mkColumn columnIds
410 columns = map mkColumn columnIds
407− paraHStyles = paraTableStyles "Heading" pn a
411+ paraHStyles = paraTableStyles "Heading" pn aligns
408− paraStyles = paraTableStyles "Contents" (pn + length (newPara paraHStyles)) a
412+ paraStyles = paraTableStyles "Contents" (pn + length (newPara paraHStyles)) aligns
409 newPara = map snd . filter (not . isEmpty . snd)
413 newPara = map snd . filter (not . isEmpty . snd)
410 addTableStyle $ tableStyle tn columnIds
414 addTableStyle $ tableStyle tn columnIds
411 mapM_ addParaStyle . newPara $ paraHStyles ++ paraStyles
415 mapM_ addParaStyle . newPara $ paraHStyles ++ paraStyles
412 captionDoc <- if null c
416 captionDoc <- if null c
413 then return empty
417 then return empty
414− else inlinesToOpenDocument o c >>=
418+ else inlinesToOpenDocument o (blocksToInlines c) >>=
415 if isEnabled Ext_native_numbering o
419 if isEnabled Ext_native_numbering o
416 then numberedTableCaption
420 then numberedTableCaption
417 else unNumberedCaption "TableCaption"
421 else unNumberedCaption "TableCaption"
418− th <- if all null h
419− then return empty
420− else colHeadsToOpenDocument o (map fst paraHStyles) h
422+ th <- colHeadsToOpenDocument o (map fst paraHStyles) thead
421− tr <- mapM (tableRowToOpenDocument o (map fst paraStyles)) r
423+ tr <- mapM (tableBodyToOpenDocument o (map fst paraStyles)) tbodies
422 let tableDoc = inTags True "table:table" [
424 let tableDoc = inTags True "table:table" [
423 ("table:name" , name)
425 ("table:name" , name)
424 , ("table:style-name", name)
426 , ("table:style-name", name)
@@ -464,26 +466,54 @@ unNumberedCaption :: Monad m => Text -> Doc Text -> OD m (Doc Text)
464unNumberedCaption style caption = return $ inParagraphTagsWithStyle style caption
466unNumberedCaption style caption = return $ inParagraphTagsWithStyle style caption
465
467
466colHeadsToOpenDocument :: PandocMonad m
468colHeadsToOpenDocument :: PandocMonad m
467− => WriterOptions -> [Text] -> [[Block]]
469+ => WriterOptions -> [Text] -> Ann.TableHead
468 -> OD m (Doc Text)
470 -> OD m (Doc Text)
469−colHeadsToOpenDocument o ns hs =
471+colHeadsToOpenDocument o ns (Ann.TableHead _ hs) =
472+ case hs of
473+ [] -> return empty
474+ (x:_) ->
475+ let (Ann.HeaderRow _ _ c) = x
470− inTagsIndented "table:table-header-rows" . inTagsIndented "table:table-row" . vcat <$>
476+ in inTagsIndented "table:table-header-rows" .
477+ inTagsIndented "table:table-row" .
471− mapM (tableItemToOpenDocument o "TableHeaderRowCell") (zip ns hs)
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
472
486
473tableRowToOpenDocument :: PandocMonad m
487tableRowToOpenDocument :: PandocMonad m
474− => WriterOptions -> [Text] -> [[Block]]
488+ => WriterOptions -> [Text] -> Ann.BodyRow
475 -> OD m (Doc Text)
489 -> OD m (Doc Text)
476−tableRowToOpenDocument o ns cs =
490+tableRowToOpenDocument o ns r =
491+ let (Ann.BodyRow _ _ _ c ) = r
477− inTagsIndented "table:table-row" . vcat <$>
492+ in inTagsIndented "table:table-row" . vcat <$>
478− mapM (tableItemToOpenDocument o "TableRowCell") (zip ns cs)
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)]
479
507
480tableItemToOpenDocument :: PandocMonad m
508tableItemToOpenDocument :: PandocMonad m
481− => WriterOptions -> Text -> (Text,[Block])
509+ => WriterOptions -> Text -> (Text,Ann.Cell)
482 -> OD m (Doc Text)
510 -> OD m (Doc Text)
483−tableItemToOpenDocument o s (n,i) =
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
484− let a = [ ("table:style-name" , s )
515+ a = [ ("table:style-name" , s )
485− , ("office:value-type", "string" )
516+ , ("office:value-type", "string" ) ] ++ csa ++ rsa
486− ]
487 in inTags True "table:table-cell" a <$>
517 in inTags True "table:table-cell" a <$>
488 withParagraphStyle o n (map plainToPara i)
518 withParagraphStyle o n (map plainToPara i)
489
519
test/command/table-with-column-span.md+157
@@ -117,3 +117,160 @@
117 (TableFoot ("",[],[])
117 (TableFoot ("",[],[])
118 [])]
118 [])]
119```
119```
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+```