git.iko.soy/typeable/pandoc
on master help sign in
Allow alignments to be specified in Markdown grid tables.
commit298e6f38f9dd2723bce3c68c5b8c376fceb49755 authorJohn MacFarlane <jgm@berkeley.edu> dateTue 15 Nov 2016, 16:41 (10 years ago) parent064e3f8
5 files changed+113−28
MANUAL.txt+19−2 src/Text/Pandoc/Readers/Markdown.hs+23−17 src/Text/Pandoc/Writers/Markdown.hs+29−9 tests/markdown-reader-more.native+22 tests/markdown-reader-more.txt+20
MANUAL.txt+19−2
@@ -2356,11 +2356,28 @@ Grid tables look like this:
23562356The row of `=`s separates the header from the table body, and can be
23572357omitted for a headerless table. The cells of grid tables may contain
23582358arbitrary block elements (multiple paragraphs, code blocks, lists,
2359−etc.). Alignments are not supported, nor are cells that span multiple
2360−columns or rows. Grid tables can be created easily using [Emacs table mode].
2359+etc.). Cells that span multiple columns or rows are not
2360+supported. Grid tables can be created easily using [Emacs table mode].
23612361
23622362[Emacs table mode]: http://table.sourceforge.net/
23632363
2364+Alignments can be specified as with pipe tables, by putting
2365+colons at the boundaries of the separator line after the
2366+header:
2367+
2368+ +---------------+---------------+--------------------+
2369+ | Right | Left | Centered |
2370+ +==============:+:==============+:==================:+
2371+ | Bananas | $1.34 | built-in wrapper |
2372+ +---------------+---------------+--------------------+
2373+
2374+For headerless tables, the colons go on the top line instead:
2375+
2376+ +--------------:+:--------------+:------------------:+
2377+ | Right | Left | Centered |
2378+ +---------------+---------------+--------------------+
2379+
2380+
23642381#### Extension: `pipe_tables` ####
23652382
23662383Pipe tables look like this:
src/Text/Pandoc/Readers/Markdown.hs+23−17
@@ -1271,14 +1271,22 @@ gridTableSplitLine :: [Int] -> String -> [String]
12711271gridTableSplitLine indices line = map removeFinalBar $ tail $
12721272 splitStringByIndices (init indices) $ trimr line
12731273
1274−gridPart :: Char -> Parser [Char] st (Int, Int)
1274+gridPart :: Char -> Parser [Char] st ((Int, Int), Alignment)
12751275gridPart ch = do
1276+ leftColon <- option False (True <$ char ':')
12761277 dashes <- many1 (char ch)
1278+ rightColon <- option False (True <$ char ':')
12771279 char '+'
1278− let lengthDashes = length dashes
1279− return (lengthDashes, lengthDashes + 1)
1280−
1281−gridDashedLines :: Char -> Parser [Char] st [(Int,Int)]
1280+ let lengthDashes = length dashes + (if leftColon then 1 else 0) +
1281+ (if rightColon then 1 else 0)
1282+ let alignment = case (leftColon, rightColon) of
1283+ (True, True) -> AlignCenter
1284+ (True, False) -> AlignLeft
1285+ (False, True) -> AlignRight
1286+ (False, False) -> AlignDefault
1287+ return ((lengthDashes, lengthDashes + 1), alignment)
1288+
1289+gridDashedLines :: Char -> Parser [Char] st [((Int, Int), Alignment)]
12821290gridDashedLines ch = try $ char '+' >> many1 (gridPart ch) <* blankline
12831291
12841292removeFinalBar :: String -> String
@@ -1296,19 +1304,17 @@ gridTableHeader headless = try $ do
12961304 optional blanklines
12971305 dashes <- gridDashedLines '-'
12981306 rawContent <- if headless
1299− then return $ repeat ""
1300− else many1
1301− (notFollowedBy (gridTableSep '=') >> char '|' >>
1302− many1Till anyChar newline)
1303− if headless
1304− then return ()
1305− else gridTableSep '=' >> return ()
1306− let lines' = map snd dashes
1307+ then return []
1308+ else many1 (try (char '|' >> anyLine))
1309+ underDashes <- if headless
1310+ then return dashes
1311+ else gridDashedLines '='
1312+ guard $ length dashes == length underDashes
1313+ let lines' = map (snd . fst) underDashes
13071314 let indices = scanl (+) 0 lines'
1308− let aligns = replicate (length lines') AlignDefault
1309− -- RST does not have a notion of alignments
1315+ let aligns = map snd underDashes
13101316 let rawHeads = if headless
1311− then replicate (length dashes) ""
1317+ then replicate (length underDashes) ""
13121318 else map (unlines . map trim) $ transpose
13131319 $ map (gridTableSplitLine indices) rawContent
13141320 heads <- fmap sequence $ mapM (parseFromString parseBlocks . trim) rawHeads
@@ -1317,7 +1323,7 @@ gridTableHeader headless = try $ do
13171323gridTableRawLine :: [Int] -> MarkdownParser [String]
13181324gridTableRawLine indices = do
13191325 char '|'
1320− line <- many1Till anyChar newline
1326+ line <- anyLine
13211327 return (gridTableSplitLine indices line)
13221328
13231329-- | Parse row of grid table.
src/Text/Pandoc/Writers/Markdown.hs+29−9
@@ -632,12 +632,13 @@ pandocTable opts headless aligns widths rawHeaders rawRows = do
632632
633633gridTable :: WriterOptions -> Bool -> [Alignment] -> [Double]
634634 -> [Doc] -> [[Doc]] -> MD Doc
635−gridTable opts headless _aligns widths headers' rawRows = do
635+gridTable opts headless aligns widths headers' rawRows = do
636636 let numcols = length headers'
637637 let widths' = if all (==0) widths
638638 then replicate numcols (1.0 / fromIntegral numcols)
639639 else widths
640− let widthsInChars = map (floor . (fromIntegral (writerColumns opts) *)) widths'
640+ let widthsInChars = map
641+ ((\x -> x - 1) . floor . (fromIntegral (writerColumns opts) *)) widths'
641642 let hpipeBlocks blocks = hcat [beg, middle, end]
642643 where h = maximum (1 : map height blocks)
643644 sep' = lblock 3 $ vcat (map text $ replicate h " | ")
@@ -647,15 +648,34 @@ gridTable opts headless _aligns widths headers' rawRows = do
647648 let makeRow = hpipeBlocks . zipWith lblock widthsInChars
648649 let head' = makeRow headers'
649650 let rows' = map (makeRow . map chomp) rawRows
650− let border ch = char '+' <> char ch <>
651− (hcat $ intersperse (char ch <> char '+' <> char ch) $
652− map (\l -> text $ replicate l ch) widthsInChars) <>
653− char ch <> char '+'
654− let body = vcat $ intersperse (border '-') rows'
651+ let borderpart ch align widthInChars =
652+ let widthInChars' = if widthInChars < 1 then 1 else widthInChars
653+ in (if (align == AlignLeft || align == AlignCenter)
654+ then char ':'
655+ else char ch) <>
656+ text (replicate widthInChars' ch) <>
657+ (if (align == AlignRight || align == AlignCenter)
658+ then char ':'
659+ else char ch)
660+ let border ch aligns' widthsInChars' =
661+ char '+' <>
662+ hcat (intersperse (char '+') (zipWith (borderpart ch)
663+ aligns' widthsInChars')) <> char '+'
664+ let body = vcat $ intersperse (border '-' (repeat AlignDefault) widthsInChars)
665+ rows'
655666 let head'' = if headless
656667 then empty
657− else head' $$ border '='
658− return $ border '-' $$ head'' $$ body $$ border '-'
668+ else head' $$ border '=' aligns widthsInChars
669+ if headless
670+ then return $
671+ border '-' aligns widthsInChars $$
672+ body $$
673+ border '-' (repeat AlignDefault) widthsInChars
674+ else return $
675+ border '-' (repeat AlignDefault) widthsInChars $$
676+ head'' $$
677+ body $$
678+ border '-' (repeat AlignDefault) widthsInChars
659679
660680itemEndsWithTightList :: [Block] -> Bool
661681itemEndsWithTightList bs =
tests/markdown-reader-more.native+22
@@ -116,6 +116,28 @@ Pandoc (Meta {unMeta = fromList [("author",MetaList [MetaInlines [Str "Author",S
116116 ,[[Para [Str "r2",Space,Str "d"]]
117117 ,[Para [Str "e"]]
118118 ,[Para [Str "f"]]]]
119+,Para [Str "With",Space,Str "alignments"]
120+,Table [] [AlignRight,AlignLeft,AlignCenter] [0.2638888888888889,0.16666666666666666,0.18055555555555555]
121+ [[Plain [Str "col",Space,Str "1"]]
122+ ,[Plain [Str "col",Space,Str "2"]]
123+ ,[Plain [Str "col",Space,Str "3"]]]
124+ [[[Para [Str "r1",Space,Str "a",SoftBreak,Str "r1",Space,Str "bis"]]
125+ ,[Para [Str "b",SoftBreak,Str "b",Space,Str "2"]]
126+ ,[Para [Str "c",SoftBreak,Str "c",Space,Str "2"]]]
127+ ,[[Para [Str "r2",Space,Str "d"]]
128+ ,[Para [Str "e"]]
129+ ,[Para [Str "f"]]]]
130+,Para [Str "Headless",Space,Str "with",Space,Str "alignments"]
131+,Table [] [AlignRight,AlignLeft,AlignCenter] [0.2638888888888889,0.16666666666666666,0.18055555555555555]
132+ [[]
133+ ,[]
134+ ,[]]
135+ [[[Para [Str "r1",Space,Str "a",SoftBreak,Str "r1",Space,Str "bis"]]
136+ ,[Para [Str "b",SoftBreak,Str "b",Space,Str "2"]]
137+ ,[Para [Str "c",SoftBreak,Str "c",Space,Str "2"]]]
138+ ,[[Para [Str "r2",Space,Str "d"]]
139+ ,[Para [Str "e"]]
140+ ,[Para [Str "f"]]]]
119141,Para [Str "Spaces",Space,Str "at",Space,Str "ends",Space,Str "of",Space,Str "lines"]
120142,Table [] [AlignDefault,AlignDefault,AlignDefault] [0.2638888888888889,0.16666666666666666,0.18055555555555555]
121143 [[]
tests/markdown-reader-more.txt+20
@@ -220,6 +220,26 @@ Headless
220220| r2 d | e | f |
221221+------------------+-----------+------------+
222222
223+With alignments
224+
225++------------------+-----------+------------+
226+| col 1 | col 2 | col 3 |
227++=================:+:==========+:==========:+
228+| r1 a | b | c |
229+| r1 bis | b 2 | c 2 |
230++------------------+-----------+------------+
231+| r2 d | e | f |
232++------------------+-----------+------------+
233+
234+Headless with alignments
235+
236++-----------------:+:----------+:----------:+
237+| r1 a | b | c |
238+| r1 bis | b 2 | c 2 |
239++------------------+-----------+------------+
240+| r2 d | e | f |
241++------------------+-----------+------------+
242+
223243Spaces at ends of lines
224244
225245+------------------+-----------+------------+