git.iko.soy/typeable/pandoc
on master help sign in
HTML reader: support row or column-spanning table cells
c9f98e2Albert Krewinkel
src/Text/Pandoc/Readers/HTML.hs+8−12
@@ -476,18 +476,10 @@ pHrule = do
476pTable :: PandocMonad m => TagParser m Blocks
476pTable :: PandocMonad m => TagParser m Blocks
477pTable = pTable' block pCell
477pTable = pTable' block pCell
478
478
479−noColOrRowSpans :: Tag Text -> Bool
480−noColOrRowSpans t = isNullOrOne "colspan" && isNullOrOne "rowspan"
481− where isNullOrOne x = case fromAttrib x t of
482− "" -> True
483− "1" -> True
484− _ -> False
485−
486−pCell :: PandocMonad m => Text -> TagParser m [(Alignment, Blocks)]
479+pCell :: PandocMonad m => Text -> TagParser m [Cell]
487pCell celltype = try $ do
480pCell celltype = try $ do
488 skipMany pBlank
481 skipMany pBlank
489− tag <- lookAhead $
490− pSatisfy (\t -> t ~== TagOpen celltype [] && noColOrRowSpans t)
482+ tag <- lookAhead $ pSatisfy (\t -> t ~== TagOpen celltype [])
491 let extractAlign' [] = ""
483 let extractAlign' [] = ""
492 extractAlign' ("text-align":x:_) = x
484 extractAlign' ("text-align":x:_) = x
493 extractAlign' (_:xs) = extractAlign' xs
485 extractAlign' (_:xs) = extractAlign' xs
@@ -498,9 +490,13 @@ pCell celltype = try $ do
498 Just "right" -> AlignRight
490 Just "right" -> AlignRight
499 Just "center" -> AlignCenter
491 Just "center" -> AlignCenter
500 _ -> AlignDefault
492 _ -> AlignDefault
493+ let rowspan = RowSpan . fromMaybe 1 $
494+ safeRead =<< maybeFromAttrib "rowspan" tag
495+ let colspan = ColSpan . fromMaybe 1 $
496+ safeRead =<< maybeFromAttrib "colspan" tag
501− res <- pInTags' celltype noColOrRowSpans block
497+ res <- pInTags celltype block
502 skipMany pBlank
498 skipMany pBlank
503− return [(align, res)]
499+ return [B.cell align rowspan colspan res]
504
500
505pBlockQuote :: PandocMonad m => TagParser m Blocks
501pBlockQuote :: PandocMonad m => TagParser m Blocks
506pBlockQuote = do
502pBlockQuote = do
src/Text/Pandoc/Readers/HTML/Table.hs+18−16
@@ -59,8 +59,8 @@ pColgroup = try $ do
59
59
60-- | Parses a simple HTML table
60-- | Parses a simple HTML table
61pTable' :: PandocMonad m
61pTable' :: PandocMonad m
62− => TagParser m Blocks -- ^ Caption parser
62+ => TagParser m Blocks -- ^ Caption parser
63− -> (Text -> TagParser m [(Alignment, Blocks)]) -- ^ Table cell parser
63+ -> (Text -> TagParser m [Cell]) -- ^ Table cell parser
64 -> TagParser m Blocks
64 -> TagParser m Blocks
65pTable' block pCell = try $ do
65pTable' block pCell = try $ do
66 TagOpen _ attribs' <- pSatisfy (matchTagOpen "table" [])
66 TagOpen _ attribs' <- pSatisfy (matchTagOpen "table" [])
@@ -73,35 +73,31 @@ pTable' block pCell = try $ do
73 pInTags "tr" (pCell "td" <|> pCell "th")
73 pInTags "tr" (pCell "td" <|> pCell "th")
74 pTBody = pInTag True "tbody" $ many1 pTr
74 pTBody = pInTag True "tbody" $ many1 pTr
75 head'' <- pInTag False "thead" (option [] pTr) <|> pInTag True "thead" pTh
75 head'' <- pInTag False "thead" (option [] pTr) <|> pInTag True "thead" pTh
76− head' <- map snd <$>
77− pInTag True "tbody"
76+ head' <- pInTag True "tbody"
78 (if null head'' then pTh else return head'')
77 (if null head'' then pTh else return head'')
79 topfoot <- option [] $ pInTag False "tfoot" $ many pTr
78 topfoot <- option [] $ pInTag False "tfoot" $ many pTr
80 rowsLs <- many pTBody
79 rowsLs <- many pTBody
81 bottomfoot <- option [] $ pInTag False "tfoot" $ many pTr
80 bottomfoot <- option [] $ pInTag False "tfoot" $ many pTr
82 TagClose _ <- pSatisfy (matchTagClose "table")
81 TagClose _ <- pSatisfy (matchTagClose "table")
83− let rows'' = concat rowsLs <> topfoot <> bottomfoot
82+ let rows = concat rowsLs <> topfoot <> bottomfoot
84− let rows''' = map (map snd) rows''
83+ rows''' = map (map cellContents) rows
85 -- fail on empty table
84 -- fail on empty table
86 guard $ not $ null head' && null rows'''
85 guard $ not $ null head' && null rows'''
87− let isSimple = onlySimpleTableCells $ fmap B.toList <$> head':rows'''
86+ let isSimple = onlySimpleTableCells $
87+ map cellContents head' : rows'''
88 let cols = if null head'
88 let cols = if null head'
89 then maximum (map length rows''')
89 then maximum (map length rows''')
90 else length head'
90 else length head'
91− -- add empty cells to short rows
92− let addEmpties r = case cols - length r of
93− n | n > 0 -> r <> replicate n mempty
94− | otherwise -> r
95− let rows = map addEmpties rows'''
96− let aligns = case rows'' of
91+ let aligns = case rows of
92+ (cs:_) -> take cols $
97− (cs:_) -> take cols $ map fst cs ++ repeat AlignDefault
93+ concatMap cellAligns cs ++ repeat AlignDefault
98− _ -> replicate cols AlignDefault
94+ _ -> replicate cols AlignDefault
99 let widths = if null widths'
95 let widths = if null widths'
100 then if isSimple
96 then if isSimple
101 then replicate cols ColWidthDefault
97 then replicate cols ColWidthDefault
102 else replicate cols (ColWidth (1.0 / fromIntegral cols))
98 else replicate cols (ColWidth (1.0 / fromIntegral cols))
103 else widths'
99 else widths'
104− let toRow = Row nullAttr . map B.simpleCell
100+ let toRow = Row nullAttr
105 toHeaderRow l = [toRow l | not (null l)]
101 toHeaderRow l = [toRow l | not (null l)]
106 return $ B.tableWith attribs
102 return $ B.tableWith attribs
107 (B.simpleCaption caption)
103 (B.simpleCaption caption)
@@ -109,3 +105,9 @@ pTable' block pCell = try $ do
109 (TableHead nullAttr $ toHeaderRow head')
105 (TableHead nullAttr $ toHeaderRow head')
110 [TableBody nullAttr 0 [] $ map toRow rows]
106 [TableBody nullAttr 0 [] $ map toRow rows]
111 (TableFoot nullAttr [])
107 (TableFoot nullAttr [])
108+
109+cellContents :: Cell -> [Block]
110+cellContents (Cell _ _ _ _ bs) = bs
111+
112+cellAligns :: Cell -> [Alignment]
113+cellAligns (Cell _ align _ (ColSpan cs) _) = replicate cs align
test/command/1881.md+10−10
@@ -28,22 +28,22 @@
28 ,(AlignDefault,ColWidthDefault)]
28 ,(AlignDefault,ColWidthDefault)]
29 (TableHead ("",[],[])
29 (TableHead ("",[],[])
30 [Row ("",[],[])
30 [Row ("",[],[])
31− [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
31+ [Cell ("",[],[]) AlignRight (RowSpan 1) (ColSpan 1)
32 [Plain [Str "Right"]]
32 [Plain [Str "Right"]]
33− ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
33+ ,Cell ("",[],[]) AlignLeft (RowSpan 1) (ColSpan 1)
34 [Plain [Str "Left"]]
34 [Plain [Str "Left"]]
35− ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
35+ ,Cell ("",[],[]) AlignCenter (RowSpan 1) (ColSpan 1)
36 [Plain [Str "Center"]]
36 [Plain [Str "Center"]]
37 ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
37 ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
38 [Plain [Str "Default"]]]])
38 [Plain [Str "Default"]]]])
39 [(TableBody ("",[],[]) (RowHeadColumns 0)
39 [(TableBody ("",[],[]) (RowHeadColumns 0)
40 []
40 []
41 [Row ("",[],[])
41 [Row ("",[],[])
42− [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
42+ [Cell ("",[],[]) AlignRight (RowSpan 1) (ColSpan 1)
43 [Plain [Str "12"]]
43 [Plain [Str "12"]]
44− ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
44+ ,Cell ("",[],[]) AlignLeft (RowSpan 1) (ColSpan 1)
45 [Plain [Str "12"]]
45 [Plain [Str "12"]]
46− ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
46+ ,Cell ("",[],[]) AlignCenter (RowSpan 1) (ColSpan 1)
47 [Plain [Str "12"]]
47 [Plain [Str "12"]]
48 ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
48 ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
49 [Plain [Str "12"]]]])]
49 [Plain [Str "12"]]]])]
@@ -73,13 +73,13 @@
73 [(TableBody ("",[],[]) (RowHeadColumns 0)
73 [(TableBody ("",[],[]) (RowHeadColumns 0)
74 []
74 []
75 [Row ("",[],[])
75 [Row ("",[],[])
76− [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
76+ [Cell ("",[],[]) AlignRight (RowSpan 1) (ColSpan 1)
77 [Plain [Str "12"]]
77 [Plain [Str "12"]]
78− ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
78+ ,Cell ("",[],[]) AlignLeft (RowSpan 1) (ColSpan 1)
79 [Plain [Str "12"]]
79 [Plain [Str "12"]]
80− ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
80+ ,Cell ("",[],[]) AlignCenter (RowSpan 1) (ColSpan 1)
81 [Plain [Str "12"]]
81 [Plain [Str "12"]]
82− ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)
82+ ,Cell ("",[],[]) AlignRight (RowSpan 1) (ColSpan 1)
83 [Plain [Str "12"]]]])]
83 [Plain [Str "12"]]]])]
84 (TableFoot ("",[],[])
84 (TableFoot ("",[],[])
85 [])]
85 [])]