Skip to content
This repository was archived by the owner on Aug 3, 2024. It is now read-only.

Commit 8203737

Browse files
committed
Add markup support for tables
Tables are composed by an optional header and body. The header is composed by a single row. The body is composed by a non-empty list of rows. Example table with header: +----------+----------+ | /32bit/ | 64bit | +==========+==========+ | 0x0000 | @0x0000@ | +----------+----------+ See #530
1 parent 240bc38 commit 8203737

File tree

3 files changed

+101
-1
lines changed

3 files changed

+101
-1
lines changed

haddock-library/src/Documentation/Haddock/Parser.hs

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ overIdentifier f d = g d
7878
g (DocAName x) = DocAName x
7979
g (DocProperty x) = DocProperty x
8080
g (DocExamples x) = DocExamples x
81+
g (DocTable (Table h c)) = DocTable $ Table (fmap g <$> h) (fmap g <$> c)
8182
g (DocHeader (Header l x)) = DocHeader . Header l $ g x
8283

8384
parse :: Parser a -> BS.ByteString -> (ParserState, a)
@@ -251,7 +252,7 @@ markdownImage = fromHyperlink <$> ("!" *> linkParser)
251252

252253
-- | Paragraph parser, called by 'parseParas'.
253254
paragraph :: Parser (DocH mod Identifier)
254-
paragraph = examples <|> do
255+
paragraph = examples <|> table <|> do
255256
indent <- takeIndent
256257
choice
257258
[ since
@@ -422,6 +423,55 @@ takeIndent = do
422423
indent <- takeHorizontalSpace
423424
"\n" *> takeIndent <|> return indent
424425

426+
-- | Provides support for simple tables.
427+
--
428+
-- Tables are composed by an optional header and body. The header is composed by
429+
-- a single row. The body is composed by a non-empty list of rows.
430+
--
431+
-- Example table with header:
432+
--
433+
-- > +----------+----------+
434+
-- > | /32bit/ | 64bit |
435+
-- > +==========+==========+
436+
-- > | 0x0000 | @0x0000@ |
437+
-- > +----------+----------+
438+
table :: Parser (DocH mod Identifier)
439+
table = do
440+
parseTableRowDivider
441+
mHeader <- optional parseTableHeader
442+
content <- parseTableContent
443+
return $ DocTable (Table mHeader content)
444+
445+
parseTableHeader :: Parser [DocH mod Identifier]
446+
parseTableHeader = parseTableRow <* parseTableHeaderDivider
447+
448+
parseTableContent :: Parser [[DocH mod Identifier]]
449+
parseTableContent = many1 (parseTableRow <* parseTableRowDivider)
450+
451+
parseTableRow :: Parser [DocH mod Identifier]
452+
parseTableRow = skipHorizontalSpace *> manyTill columnValue endOfRow
453+
where
454+
columnValue = parseStringBS . bsStrip <$> ("|" *> takeWhile_ (/= '|'))
455+
endOfRow = "|" *> skipHorizontalSpace *> "\n"
456+
bsStrip = bsDropWhile isSpace . bsDropWhileEnd isSpace
457+
bsDropWhile c = snd . BS.span c
458+
bsDropWhileEnd c = fst . BS.spanEnd c
459+
460+
parseTableRowDivider :: Parser ()
461+
parseTableRowDivider = parseTableDivider "-"
462+
463+
parseTableHeaderDivider :: Parser ()
464+
parseTableHeaderDivider = parseTableDivider "="
465+
466+
parseTableDivider :: Parser BS.ByteString -> Parser ()
467+
parseTableDivider c = void $
468+
skipHorizontalSpace
469+
*> many1 (columnDivider c) *> "+"
470+
*> skipHorizontalSpace *> "\n"
471+
where
472+
columnDivider :: Parser BS.ByteString -> Parser [BS.ByteString]
473+
columnDivider d = "+" *> many1 d
474+
425475
-- | Blocks of text of the form:
426476
--
427477
-- >> foo

haddock-library/src/Documentation/Haddock/Types.hs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,11 @@ data Example = Example
5353
, exampleResult :: [String]
5454
} deriving (Eq, Show)
5555

56+
data Table id = Table
57+
{ tableHeader :: Maybe [id]
58+
, tableBody :: [[id]]
59+
} deriving (Eq, Show, Functor, Foldable, Traversable)
60+
5661
data DocH mod id
5762
= DocEmpty
5863
| DocAppend (DocH mod id) (DocH mod id)
@@ -76,5 +81,6 @@ data DocH mod id
7681
| DocAName String
7782
| DocProperty String
7883
| DocExamples [Example]
84+
| DocTable (Table (DocH mod id))
7985
| DocHeader (Header (DocH mod id))
8086
deriving (Eq, Show, Functor, Foldable, Traversable)

haddock-library/test/Documentation/Haddock/ParserSpec.hs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -649,6 +649,50 @@ spec = do
649649
, " bar"
650650
] `shouldParseTo` DocExamples [Example "foo" [" bar"]]
651651

652+
context "when parsing tables" $ do
653+
let simpleTable :: Maybe [DocH () String] -> [[DocH () String]] -> Doc String
654+
simpleTable header rows = DocTable (Table header rows)
655+
table :: Maybe [DocH () a] -> [[DocH () a]] -> Doc a
656+
table header rows = DocTable (Table header rows)
657+
658+
it "parses a table with a header" $
659+
"+----------+----------+\n\
660+
\| 32bit | 64bit |\n\
661+
\+==========+==========+\n\
662+
\| 0x0000 | 0x0000 |\n\
663+
\+----------+----------+"
664+
`shouldParseTo`
665+
simpleTable (Just ["32bit", "64bit"]) [["0x0000", "0x0000"]]
666+
667+
it "parses a table without header" $
668+
"+----------+----------+\n\
669+
\| 32bit | 64bit |\n\
670+
\+----------+----------+\n\
671+
\| 0x0000 | 0x0000 |\n\
672+
\+----------+----------+"
673+
`shouldParseTo`
674+
simpleTable Nothing [["32bit", "64bit"], ["0x0000", "0x0000"]]
675+
676+
it "parses a table that contains formatted elements" $
677+
"+----------+----------+\n\
678+
\| /32bit/ | 64bit |\n\
679+
\+----------+----------+\n\
680+
\| 0x0000 | @0x0000@ |\n\
681+
\+----------+----------+"
682+
`shouldParseTo`
683+
table Nothing [
684+
[ DocEmphasis (DocString "32bit"), DocString "64bit" ]
685+
, [ DocString "0x0000", DocMonospaced (DocString "0x0000") ]
686+
]
687+
688+
it "can deal with whitespace before and after each line" $
689+
" +----------+----------+ \n\
690+
\ | 32bit | 64bit | \n\
691+
\ +----------+----------+ \n\
692+
\ | 0x0000 | 0x0000 | \n\
693+
\ +----------+----------+ "
694+
`shouldParseTo`
695+
simpleTable Nothing [["32bit", "64bit"], ["0x0000", "0x0000"]]
652696

653697
context "when parsing paragraphs nested in lists" $ do
654698
it "can nest the same type of list" $ do

0 commit comments

Comments
 (0)