Support colspans and rowspans in HTML tables (#6644)

* HTML writer: add support for row headers, colspans, rowspans
* Add planet table tests

See #6312
This commit is contained in:
Albert Krewinkel 2020-09-10 18:47:40 +02:00 committed by GitHub
parent c2f1fadb2c
commit 9423b4b7d9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 608 additions and 65 deletions

View file

@ -1,3 +1,5 @@
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE MultiWayIf #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}
@ -30,6 +32,7 @@ module Text.Pandoc.Writers.HTML (
import Control.Monad.State.Strict
import Data.Char (ord)
import Data.List (intercalate, intersperse, partition, delete, (\\))
import Data.List.NonEmpty (NonEmpty((:|)))
import Data.Maybe (fromMaybe, isJust, isNothing, mapMaybe)
import qualified Data.Set as Set
import Data.Text (Text)
@ -53,6 +56,7 @@ import Text.Pandoc.Templates (renderTemplate)
import Text.Pandoc.Walk
import Text.Pandoc.Writers.Math
import Text.Pandoc.Writers.Shared
import Text.Pandoc.Writers.Tables
import Text.Pandoc.XML (escapeStringForXML, fromEntities, toEntities,
html5Attributes, html4Attributes, rdfaAttributes)
import qualified Text.Blaze.XHtml5 as H5
@ -899,39 +903,33 @@ blockToHtml opts (DefinitionList lst) = do
return $ mconcat $ nl opts : term' : nl opts :
intersperse (nl opts) defs') lst
defList opts contents
blockToHtml opts (Table attr blkCapt specs thead tbody tfoot) = do
let (capt, aligns, widths, headers, rows') = toLegacyTable blkCapt specs thead tbody tfoot
captionDoc <- if null capt
then return mempty
else do
cs <- inlineListToHtml opts capt
return $ H.caption cs >> nl opts
html5 <- gets stHtml5
let percent w = show (truncate (100*w) :: Integer) <> "%"
let coltags = if all (== 0.0) widths
then mempty
else do
H.colgroup $ do
nl opts
mapM_ (\w -> do
if html5
then H.col ! A.style (toValue $ "width: " <>
percent w)
else H.col ! A.width (toValue $ percent w)
nl opts) widths
nl opts
head' <- if all null headers
then return mempty
else do
contents <- tableRowToHtml opts aligns 0 headers
return $ H.thead (nl opts >> contents) >> nl opts
body' <- liftM (\x -> H.tbody (nl opts >> mconcat x)) $
zipWithM (tableRowToHtml opts aligns) [1..] rows'
blockToHtml opts (Table attr caption colspecs thead tbody tfoot) =
tableToHtml opts (toAnnTable attr caption colspecs thead tbody tfoot)
tableToHtml :: PandocMonad m
=> WriterOptions
-> AnnTable
-> StateT WriterState m Html
tableToHtml opts (AnnTable attr caption colspecs thead tbodies _tfoot) = do
captionDoc <- case caption of
Caption _ [] -> return mempty
Caption _ longCapt -> do
cs <- blockListToHtml opts longCapt
return $ do
H.caption cs
nl opts
coltags <- colSpecListToHtml opts colspecs
head' <- tableHeadToHtml opts thead
body' <- mconcat <$> mapM (tableBodyToHtml opts) tbodies
let (ident,classes,kvs) = attr
-- When widths of columns are < 100%, we need to set width for the whole
-- table, or some browsers give us skinny columns with lots of space
-- between:
let totalWidth = sum widths
-- let totalWidth = sum widths
let colWidth = \case
ColWidth d -> d
ColWidthDefault -> 0
let totalWidth = sum . map (colWidth . snd) $ colspecs
let attr' = case lookup "style" kvs of
Nothing | totalWidth < 1 && totalWidth > 0
-> (ident,classes, ("style","width:" <>
@ -939,56 +937,180 @@ blockToHtml opts (Table attr blkCapt specs thead tbody tfoot) = do
<> "%;"):kvs)
_ -> attr
addAttrs opts attr' $ H.table $
nl opts >> captionDoc >> coltags >> head' >> body' >> nl opts
nl opts *> captionDoc *> coltags *> head' *> body' *> nl opts
tableBodyToHtml :: PandocMonad m
=> WriterOptions
-> AnnTableBody
-> StateT WriterState m Html
tableBodyToHtml opts (AnnTableBody _attr _rowHeadCols _intm rows) =
H.tbody <$> bodyRowsToHtml opts rows
tableHeadToHtml :: PandocMonad m
=> WriterOptions
-> AnnTableHead
-> StateT WriterState m Html
tableHeadToHtml opts (AnnTableHead attr rows) =
if null rows || all isEmptyRow rows
then return mempty
else do
contents <- headerRowsToHtml opts rows
headElement <- addAttrs opts attr $ H.thead contents
return $ do
headElement
nl opts
where
isEmptyRow (AnnHeaderRow _attr _rownum cells) = all isEmptyCell cells
isEmptyCell (AnnCell _colspecs _colnum cell) =
cell == Cell nullAttr AlignDefault (RowSpan 1) (ColSpan 1) []
data RowType = HeaderRow | FooterRow | BodyRow
deriving (Eq)
data CellType = HeaderCell | BodyCell
data TableRow = TableRow RowType Attr RowNumber AnnRowHead AnnRowBody
headerRowsToHtml :: PandocMonad m
=> WriterOptions
-> [AnnHeaderRow]
-> StateT WriterState m Html
headerRowsToHtml opts =
rowListToHtml opts . map toTableRow
where
toTableRow (AnnHeaderRow attr rownum rowbody) =
TableRow HeaderRow attr rownum [] rowbody
bodyRowsToHtml :: PandocMonad m
=> WriterOptions
-> [AnnBodyRow]
-> StateT WriterState m Html
bodyRowsToHtml opts =
rowListToHtml opts . zipWith toTableRow [1..]
where
toTableRow rownum (AnnBodyRow attr _rownum rowhead rowbody) =
TableRow BodyRow attr rownum rowhead rowbody
rowListToHtml :: PandocMonad m
=> WriterOptions
-> [TableRow]
-> StateT WriterState m Html
rowListToHtml opts rows =
(\x -> (nl opts *> mconcat x)) <$>
mapM (tableRowToHtml opts) rows
colSpecListToHtml :: PandocMonad m
=> WriterOptions
-> [ColSpec]
-> StateT WriterState m Html
colSpecListToHtml opts colspecs = do
html5 <- gets stHtml5
let hasDefaultWidth (_, ColWidthDefault) = True
hasDefaultWidth _ = False
let percent w = show (truncate (100*w) :: Integer) <> "%"
let col :: ColWidth -> Html
col cw = do
H.col ! case cw of
ColWidthDefault -> mempty
ColWidth w -> if html5
then A.style (toValue $ "width: " <> percent w)
else A.width (toValue $ percent w)
nl opts
return $
if all hasDefaultWidth colspecs
then mempty
else do
H.colgroup $ do
nl opts
mapM_ (col . snd) colspecs
nl opts
tableRowToHtml :: PandocMonad m
=> WriterOptions
-> [Alignment]
-> Int
-> [[Block]]
-> TableRow
-> StateT WriterState m Html
tableRowToHtml opts aligns rownum cols' = do
let mkcell = if rownum == 0 then H.th else H.td
let rowclass = case rownum of
0 -> "header"
x | x `rem` 2 == 1 -> "odd"
_ -> "even"
cols'' <- zipWithM
(\alignment item -> tableItemToHtml opts mkcell alignment item)
aligns cols'
return $ (H.tr ! A.class_ rowclass $ nl opts >> mconcat cols'')
>> nl opts
tableRowToHtml opts (TableRow rowtype _attr rownum rowhead rowbody) = do
let rowclass = A.class_ $ case rownum of
RowNumber x | x `rem` 2 == 1 -> "odd"
_ | rowtype /= HeaderRow -> "even"
_ -> "header"
let celltype = case rowtype of
HeaderRow -> HeaderCell
_ -> BodyCell
head' <- mapM (cellToHtml opts HeaderCell) rowhead
body <- mapM (cellToHtml opts celltype) rowbody
return $ do
H.tr ! rowclass $ nl opts *> mconcat (head' <> body)
nl opts
alignmentToString :: Alignment -> [Char]
alignmentToString alignment = case alignment of
AlignLeft -> "left"
AlignRight -> "right"
AlignCenter -> "center"
AlignDefault -> ""
alignmentToString :: Alignment -> Maybe Text
alignmentToString = \case
AlignLeft -> Just "left"
AlignRight -> Just "right"
AlignCenter -> Just "center"
AlignDefault -> Nothing
tableItemToHtml :: PandocMonad m
colspanAttrib :: ColSpan -> Attribute
colspanAttrib = \case
ColSpan 1 -> mempty
ColSpan n -> A.colspan (toValue n)
rowspanAttrib :: RowSpan -> Attribute
rowspanAttrib = \case
RowSpan 1 -> mempty
RowSpan n -> A.rowspan (toValue n)
cellToHtml :: PandocMonad m
=> WriterOptions
-> CellType
-> AnnCell
-> StateT WriterState m Html
cellToHtml opts celltype (AnnCell (colspec :| _) _colNum cell) =
let align = fst colspec
in tableCellToHtml opts celltype align cell
tableCellToHtml :: PandocMonad m
=> WriterOptions
-> (Html -> Html)
-> CellType
-> Alignment
-> [Block]
-> Cell
-> StateT WriterState m Html
tableItemToHtml opts tag' align' item = do
tableCellToHtml opts ctype colAlign (Cell attr align rowspan colspan item) = do
contents <- blockListToHtml opts item
html5 <- gets stHtml5
let alignStr = alignmentToString align'
let attribs = if html5
then A.style (toValue $ "text-align: " <> alignStr <> ";")
else A.align (toValue alignStr)
let tag'' = if null alignStr
then tag'
else tag' ! attribs
return $ tag'' contents >> nl opts
let tag' = case ctype of
BodyCell -> H.td
HeaderCell -> H.th
let align' = case align of
AlignDefault -> colAlign
_ -> align
let alignAttribs = case alignmentToString align' of
Nothing ->
mempty
Just alignStr ->
if html5
then A.style (toValue $ "text-align: " <> alignStr <> ";")
else A.align (toValue alignStr)
otherAttribs <- attrsToHtml opts attr
let attribs = mconcat
$ alignAttribs
: colspanAttrib colspan
: rowspanAttrib rowspan
: otherAttribs
return $ do
tag' ! attribs $ contents
nl opts
toListItems :: WriterOptions -> [Html] -> [Html]
toListItems opts items = map (toListItem opts) items ++ [nl opts]
toListItem :: WriterOptions -> Html -> Html
toListItem opts item = nl opts >> H.li item
toListItem opts item = nl opts *> H.li item
blockListToHtml :: PandocMonad m
=> WriterOptions -> [Block] -> StateT WriterState m Html

View file

@ -67,8 +67,11 @@ tests pandocPath =
]
]
, testGroup "html"
[ testGroup "writer" (writerTests' "html4" ++ writerTests' "html5" ++
lhsWriterTests' "html")
[ testGroup "writer" $ mconcat
[ extWriterTests' "html4"
, extWriterTests' "html5"
, lhsWriterTests' "html"
]
, test' "reader" ["-r", "html", "-w", "native", "-s"]
"html-reader.html" "html-reader.native"
]
@ -225,6 +228,7 @@ tests pandocPath =
fb2WriterTest' = fb2WriterTest pandocPath
lhsWriterTests' = lhsWriterTests pandocPath
lhsReaderTest' = lhsReaderTest pandocPath
extWriterTests' = extendedWriterTests pandocPath
-- makes sure file is fully closed after reading
readFile' :: FilePath -> IO String
@ -260,6 +264,19 @@ writerTests pandocPath format
opts = ["-r", "native", "-w", format, "--columns=78",
"--variable", "pandoc-version="]
extendedWriterTests :: FilePath -> String -> [TestTree]
extendedWriterTests pandocPath format
= writerTests pandocPath format ++
[ test pandocPath
"tables"
opts
("tables" </> "planets.native")
("tables" </> "planets" <.> format)
]
where
opts = ["-r", "native", "-w", format, "--columns=78",
"--variable", "pandoc-version="]
s5WriterTest :: FilePath -> String -> [String] -> String -> TestTree
s5WriterTest pandocPath modifier opts format
= test pandocPath (format ++ " writer (" ++ modifier ++ ")")

133
test/tables/planets.html4 Normal file
View file

@ -0,0 +1,133 @@
<table>
<caption><p>Data about the planets of our solar system.</p></caption>
<thead>
<tr class="header">
<th align="center" colspan="2"></th>
<th>Name</th>
<th align="right">Mass (10^24kg)</th>
<th align="right">Diameter (km)</th>
<th align="right">Density (kg/m^3)</th>
<th align="right">Gravity (m/s^2)</th>
<th align="right">Length of day (hours)</th>
<th align="right">Distance from Sun (10^6km)</th>
<th align="right">Mean temperature (C)</th>
<th align="right">Number of moons</th>
<th>Notes</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<th align="center" colspan="2" rowspan="4">Terrestial planets</th>
<th>Mercury</th>
<td align="right">0.330</td>
<td align="right">4,879</td>
<td align="right">5427</td>
<td align="right">3.7</td>
<td align="right">4222.6</td>
<td align="right">57.9</td>
<td align="right">167</td>
<td align="right">0</td>
<td>Closest to the Sun</td>
</tr>
<tr class="even">
<th>Venus</th>
<td align="right">4.87</td>
<td align="right">12,104</td>
<td align="right">5243</td>
<td align="right">8.9</td>
<td align="right">2802.0</td>
<td align="right">108.2</td>
<td align="right">464</td>
<td align="right">0</td>
<td></td>
</tr>
<tr class="odd">
<th>Earth</th>
<td align="right">5.97</td>
<td align="right">12,756</td>
<td align="right">5514</td>
<td align="right">9.8</td>
<td align="right">24.0</td>
<td align="right">149.6</td>
<td align="right">15</td>
<td align="right">1</td>
<td>Our world</td>
</tr>
<tr class="even">
<th>Mars</th>
<td align="right">0.642</td>
<td align="right">6,792</td>
<td align="right">3933</td>
<td align="right">3.7</td>
<td align="right">24.7</td>
<td align="right">227.9</td>
<td align="right">-65</td>
<td align="right">2</td>
<td>The red planet</td>
</tr>
<tr class="odd">
<th align="center" rowspan="4">Jovian planets</th>
<th align="center" rowspan="2">Gas giants</th>
<th>Jupiter</th>
<td align="right">1898</td>
<td align="right">142,984</td>
<td align="right">1326</td>
<td align="right">23.1</td>
<td align="right">9.9</td>
<td align="right">778.6</td>
<td align="right">-110</td>
<td align="right">67</td>
<td>The largest planet</td>
</tr>
<tr class="even">
<th>Saturn</th>
<td align="right">568</td>
<td align="right">120,536</td>
<td align="right">687</td>
<td align="right">9.0</td>
<td align="right">10.7</td>
<td align="right">1433.5</td>
<td align="right">-140</td>
<td align="right">62</td>
<td></td>
</tr>
<tr class="odd">
<th align="center" rowspan="2">Ice giants</th>
<th>Uranus</th>
<td align="right">86.8</td>
<td align="right">51,118</td>
<td align="right">1271</td>
<td align="right">8.7</td>
<td align="right">17.2</td>
<td align="right">2872.5</td>
<td align="right">-195</td>
<td align="right">27</td>
<td></td>
</tr>
<tr class="even">
<th>Neptune</th>
<td align="right">102</td>
<td align="right">49,528</td>
<td align="right">1638</td>
<td align="right">11.0</td>
<td align="right">16.1</td>
<td align="right">4495.1</td>
<td align="right">-200</td>
<td align="right">14</td>
<td></td>
</tr>
<tr class="odd">
<th align="center" colspan="2">Dwarf planets</th>
<th>Pluto</th>
<td align="right">0.0146</td>
<td align="right">2,370</td>
<td align="right">2095</td>
<td align="right">0.7</td>
<td align="right">153.3</td>
<td align="right">5906.4</td>
<td align="right">-225</td>
<td align="right">5</td>
<td>Declassified as a planet in 2006.</td>
</tr>
</tbody>
</table>

133
test/tables/planets.html5 Normal file
View file

@ -0,0 +1,133 @@
<table>
<caption><p>Data about the planets of our solar system.</p></caption>
<thead>
<tr class="header">
<th style="text-align: center;" colspan="2"></th>
<th>Name</th>
<th style="text-align: right;">Mass (10^24kg)</th>
<th style="text-align: right;">Diameter (km)</th>
<th style="text-align: right;">Density (kg/m^3)</th>
<th style="text-align: right;">Gravity (m/s^2)</th>
<th style="text-align: right;">Length of day (hours)</th>
<th style="text-align: right;">Distance from Sun (10^6km)</th>
<th style="text-align: right;">Mean temperature (C)</th>
<th style="text-align: right;">Number of moons</th>
<th>Notes</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<th style="text-align: center;" colspan="2" rowspan="4">Terrestial planets</th>
<th>Mercury</th>
<td style="text-align: right;">0.330</td>
<td style="text-align: right;">4,879</td>
<td style="text-align: right;">5427</td>
<td style="text-align: right;">3.7</td>
<td style="text-align: right;">4222.6</td>
<td style="text-align: right;">57.9</td>
<td style="text-align: right;">167</td>
<td style="text-align: right;">0</td>
<td>Closest to the Sun</td>
</tr>
<tr class="even">
<th>Venus</th>
<td style="text-align: right;">4.87</td>
<td style="text-align: right;">12,104</td>
<td style="text-align: right;">5243</td>
<td style="text-align: right;">8.9</td>
<td style="text-align: right;">2802.0</td>
<td style="text-align: right;">108.2</td>
<td style="text-align: right;">464</td>
<td style="text-align: right;">0</td>
<td></td>
</tr>
<tr class="odd">
<th>Earth</th>
<td style="text-align: right;">5.97</td>
<td style="text-align: right;">12,756</td>
<td style="text-align: right;">5514</td>
<td style="text-align: right;">9.8</td>
<td style="text-align: right;">24.0</td>
<td style="text-align: right;">149.6</td>
<td style="text-align: right;">15</td>
<td style="text-align: right;">1</td>
<td>Our world</td>
</tr>
<tr class="even">
<th>Mars</th>
<td style="text-align: right;">0.642</td>
<td style="text-align: right;">6,792</td>
<td style="text-align: right;">3933</td>
<td style="text-align: right;">3.7</td>
<td style="text-align: right;">24.7</td>
<td style="text-align: right;">227.9</td>
<td style="text-align: right;">-65</td>
<td style="text-align: right;">2</td>
<td>The red planet</td>
</tr>
<tr class="odd">
<th style="text-align: center;" rowspan="4">Jovian planets</th>
<th style="text-align: center;" rowspan="2">Gas giants</th>
<th>Jupiter</th>
<td style="text-align: right;">1898</td>
<td style="text-align: right;">142,984</td>
<td style="text-align: right;">1326</td>
<td style="text-align: right;">23.1</td>
<td style="text-align: right;">9.9</td>
<td style="text-align: right;">778.6</td>
<td style="text-align: right;">-110</td>
<td style="text-align: right;">67</td>
<td>The largest planet</td>
</tr>
<tr class="even">
<th>Saturn</th>
<td style="text-align: right;">568</td>
<td style="text-align: right;">120,536</td>
<td style="text-align: right;">687</td>
<td style="text-align: right;">9.0</td>
<td style="text-align: right;">10.7</td>
<td style="text-align: right;">1433.5</td>
<td style="text-align: right;">-140</td>
<td style="text-align: right;">62</td>
<td></td>
</tr>
<tr class="odd">
<th style="text-align: center;" rowspan="2">Ice giants</th>
<th>Uranus</th>
<td style="text-align: right;">86.8</td>
<td style="text-align: right;">51,118</td>
<td style="text-align: right;">1271</td>
<td style="text-align: right;">8.7</td>
<td style="text-align: right;">17.2</td>
<td style="text-align: right;">2872.5</td>
<td style="text-align: right;">-195</td>
<td style="text-align: right;">27</td>
<td></td>
</tr>
<tr class="even">
<th>Neptune</th>
<td style="text-align: right;">102</td>
<td style="text-align: right;">49,528</td>
<td style="text-align: right;">1638</td>
<td style="text-align: right;">11.0</td>
<td style="text-align: right;">16.1</td>
<td style="text-align: right;">4495.1</td>
<td style="text-align: right;">-200</td>
<td style="text-align: right;">14</td>
<td></td>
</tr>
<tr class="odd">
<th style="text-align: center;" colspan="2">Dwarf planets</th>
<th>Pluto</th>
<td style="text-align: right;">0.0146</td>
<td style="text-align: right;">2,370</td>
<td style="text-align: right;">2095</td>
<td style="text-align: right;">0.7</td>
<td style="text-align: right;">153.3</td>
<td style="text-align: right;">5906.4</td>
<td style="text-align: right;">-225</td>
<td style="text-align: right;">5</td>
<td>Declassified as a planet in 2006.</td>
</tr>
</tbody>
</table>

138
test/tables/planets.native Normal file
View file

@ -0,0 +1,138 @@
[Table ("",[],[]) (Caption Nothing
[Para [Str "Data about the planets of our solar system."]])
[(AlignCenter,ColWidthDefault)
,(AlignCenter,ColWidthDefault)
,(AlignDefault,ColWidthDefault)
,(AlignRight,ColWidthDefault)
,(AlignRight,ColWidthDefault)
,(AlignRight,ColWidthDefault)
,(AlignRight,ColWidthDefault)
,(AlignRight,ColWidthDefault)
,(AlignRight,ColWidthDefault)
,(AlignRight,ColWidthDefault)
,(AlignRight,ColWidthDefault)
,(AlignDefault,ColWidthDefault)]
(TableHead ("",[],[])
[Row ("",[],[])
[Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 2) [Plain [Str ""]]
,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "Name"]]
,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "Mass (10^24kg)"]]
,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "Diameter (km)"]]
,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "Density (kg/m^3)"]]
,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "Gravity (m/s^2)"]]
,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "Length of day (hours)"]]
,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "Distance from Sun (10^6km)"]]
,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "Mean temperature (C)"]]
,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "Number of moons"]]
,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "Notes"]]]]
)
[(TableBody ("",[],[]) (RowHeadColumns 3)
[]
[Row ("",[],[])
[Cell ("",[],[]) AlignDefault (RowSpan 4) (ColSpan 2) [Plain [Str "Terrestial planets"]]
,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "Mercury"]]
,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "0.330"]]
,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "4,879"]]
,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "5427"]]
,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "3.7"]]
,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "4222.6"]]
,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "57.9"]]
,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "167"]]
,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "0"]]
,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "Closest to the Sun"]]]
,Row ("",[],[])
[Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "Venus"]]
,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "4.87"]]
,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "12,104"]]
,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "5243"]]
,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "8.9"]]
,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "2802.0"]]
,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "108.2"]]
,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "464"]]
,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "0"]]
,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str ""]]]
,Row ("",[],[])
[Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "Earth"]]
,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "5.97"]]
,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "12,756"]]
,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "5514"]]
,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "9.8"]]
,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "24.0"]]
,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "149.6"]]
,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "15"]]
,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "1"]]
,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "Our world"]]]
,Row ("",[],[])
[Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "Mars"]]
,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "0.642"]]
,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "6,792"]]
,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "3933"]]
,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "3.7"]]
,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "24.7"]]
,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "227.9"]]
,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "-65"]]
,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "2"]]
,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "The red planet"]]]
,Row ("",[],[])
[Cell ("",[],[]) AlignDefault (RowSpan 4) (ColSpan 1) [Plain [Str "Jovian planets"]]
,Cell ("",[],[]) AlignDefault (RowSpan 2) (ColSpan 1) [Plain [Str "Gas giants"]]
,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "Jupiter"]]
,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "1898"]]
,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "142,984"]]
,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "1326"]]
,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "23.1"]]
,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "9.9"]]
,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "778.6"]]
,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "-110"]]
,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "67"]]
,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "The largest planet"]]]
,Row ("",[],[])
[Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "Saturn"]]
,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "568"]]
,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "120,536"]]
,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "687"]]
,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "9.0"]]
,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "10.7"]]
,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "1433.5"]]
,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "-140"]]
,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "62"]]
,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str ""]]]
,Row ("",[],[])
[Cell ("",[],[]) AlignDefault (RowSpan 2) (ColSpan 1) [Plain [Str "Ice giants"]]
,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "Uranus"]]
,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "86.8"]]
,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "51,118"]]
,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "1271"]]
,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "8.7"]]
,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "17.2"]]
,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "2872.5"]]
,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "-195"]]
,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "27"]]
,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str ""]]]
,Row ("",[],[])
[Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "Neptune"]]
,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "102"]]
,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "49,528"]]
,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "1638"]]
,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "11.0"]]
,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "16.1"]]
,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "4495.1"]]
,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "-200"]]
,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "14"]]
,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str ""]]]
,Row ("",[],[])
[Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 2) [Plain [Str "Dwarf planets"]]
,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "Pluto"]]
,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "0.0146"]]
,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "2,370"]]
,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "2095"]]
,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "0.7"]]
,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "153.3"]]
,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "5906.4"]]
,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "-225"]]
,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "5"]]
,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "Declassified as a planet in 2006."]]]])]
(TableFoot ("",[],[])
[]
)
]