{-
The MIT License (MIT)

Copyright (c) 2015 Wasif Hasan Baig <pr.wasif@gmail.com>

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
-}

{- |
   Module      : Text.Table.Builder
   Copyright   : Copyright (C) 2015 Wasif Hasan Baig
   License     : MIT

   Maintainer  : Venkateswara Rao Mandela <venkat.mandela@gmail.com>
   Stability   : alpha

Functions for building Tables and converting them to markdown.
-}

module Text.Table.Builder (
      mkTable
    , toMarkdown
    , CaptionPos (..)
    , Atrs
) where

import Data.List
import Data.Text (pack, unpack, strip, justifyLeft, justifyRight, center)

-- Local import
import Text.Table.Definition

-- | Table Builder Functions
--   Helper functions to create a Table from the parsed CSV file (a list of
--   list of Strings).

-- | Converts Lines to Cell.
mkCell :: Align -> Lines -> [Cell]
mkCell :: Align -> Lines -> [Cell]
mkCell Align
a Lines
xs = (Lines -> Cell) -> [Lines] -> [Cell]
forall a b. (a -> b) -> [a] -> [b]
map (Span -> Span -> Align -> Lines -> Cell
Cell (Lines -> Span
span Lines
xs) Span
0 Align
a) [Lines]
liness
            where
              span :: Lines -> Span
span   = [Span] -> Span
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
maximum ([Span] -> Span) -> (Lines -> [Span]) -> Lines -> Span
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (String -> Span) -> Lines -> [Span]
forall a b. (a -> b) -> [a] -> [b]
map (Lines -> Span
forall (t :: * -> *) a. Foldable t => t a -> Span
length (Lines -> Span) -> (String -> Lines) -> String -> Span
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Lines
lines)
              liness :: [Lines]
liness = (String -> Lines) -> Lines -> [Lines]
forall a b. (a -> b) -> [a] -> [b]
map String -> Lines
lines Lines
xs

-- | Converts a list of Lines to a list of Cells.
mkCells :: [Align] -> [Lines] -> [[Cell]]
mkCells :: [Align] -> [Lines] -> [[Cell]]
mkCells [Align]
as [Lines]
xss = (Lines -> [Cell]) -> [Lines] -> [[Cell]]
forall a b. (a -> b) -> [a] -> [b]
map ([Align] -> [Cell] -> [Cell]
addCellAligns [Align]
as ([Cell] -> [Cell]) -> (Lines -> [Cell]) -> Lines -> [Cell]
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
                      [Span] -> [Cell] -> [Cell]
addCellWidths [Span]
columnWidths ([Cell] -> [Cell]) -> (Lines -> [Cell]) -> Lines -> [Cell]
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
                      Align -> Lines -> [Cell]
mkCell Align
DefaultAlign) [Lines]
xss
               where
                 lines1 :: [Lines] -> [[Lines]]
lines1       = (Lines -> [Lines]) -> [Lines] -> [[Lines]]
forall a b. (a -> b) -> [a] -> [b]
map ((Lines -> [Lines]) -> [Lines] -> [[Lines]])
-> ((String -> Lines) -> Lines -> [Lines])
-> (String -> Lines)
-> [Lines]
-> [[Lines]]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (String -> Lines) -> Lines -> [Lines]
forall a b. (a -> b) -> [a] -> [b]
map ((String -> Lines) -> [Lines] -> [[Lines]])
-> (String -> Lines) -> [Lines] -> [[Lines]]
forall a b. (a -> b) -> a -> b
$ String -> Lines
lines
                 calcWidths :: [[[[a]]]] -> [[[Span]]]
calcWidths   = ([[[a]]] -> [[Span]]) -> [[[[a]]]] -> [[[Span]]]
forall a b. (a -> b) -> [a] -> [b]
map (([[[a]]] -> [[Span]]) -> [[[[a]]]] -> [[[Span]]])
-> (([a] -> Span) -> [[[a]]] -> [[Span]])
-> ([a] -> Span)
-> [[[[a]]]]
-> [[[Span]]]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ([[a]] -> [Span]) -> [[[a]]] -> [[Span]]
forall a b. (a -> b) -> [a] -> [b]
map (([[a]] -> [Span]) -> [[[a]]] -> [[Span]])
-> (([a] -> Span) -> [[a]] -> [Span])
-> ([a] -> Span)
-> [[[a]]]
-> [[Span]]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ([a] -> Span) -> [[a]] -> [Span]
forall a b. (a -> b) -> [a] -> [b]
map (([a] -> Span) -> [[[[a]]]] -> [[[Span]]])
-> ([a] -> Span) -> [[[[a]]]] -> [[[Span]]]
forall a b. (a -> b) -> a -> b
$ (Span -> Span -> Span
forall a. Num a => a -> a -> a
+Span
2) (Span -> Span) -> ([a] -> Span) -> [a] -> Span
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [a] -> Span
forall (t :: * -> *) a. Foldable t => t a -> Span
length
                 columnWidths :: [Span]
columnWidths = ([Span] -> Span) -> [[Span]] -> [Span]
forall a b. (a -> b) -> [a] -> [b]
map [Span] -> Span
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
maximum ([[Span]] -> [Span]) -> ([Lines] -> [[Span]]) -> [Lines] -> [Span]
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
                                ([[Span]] -> [Span]) -> [[[Span]]] -> [[Span]]
forall a b. (a -> b) -> [a] -> [b]
map [[Span]] -> [Span]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat  ([[[Span]]] -> [[Span]])
-> ([Lines] -> [[[Span]]]) -> [Lines] -> [[Span]]
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
                                [[[Span]]] -> [[[Span]]]
forall a. [[a]] -> [[a]]
transpose   ([[[Span]]] -> [[[Span]]])
-> ([Lines] -> [[[Span]]]) -> [Lines] -> [[[Span]]]
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
                                [[Lines]] -> [[[Span]]]
forall a. [[[[a]]]] -> [[[Span]]]
calcWidths  ([[Lines]] -> [[[Span]]])
-> ([Lines] -> [[Lines]]) -> [Lines] -> [[[Span]]]
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
                                [Lines] -> [[Lines]]
lines1      ([Lines] -> [Span]) -> [Lines] -> [Span]
forall a b. (a -> b) -> a -> b
$
                                [Lines]
xss

addCellAligns :: [Align] -> [Cell] -> [Cell]
addCellAligns :: [Align] -> [Cell] -> [Cell]
addCellAligns (Align
a:[Align]
as) (Cell
c:[Cell]
cs) = Align -> Cell -> Cell
updateCellAlign Align
a Cell
c  Cell -> [Cell] -> [Cell]
forall a. a -> [a] -> [a]
: [Align] -> [Cell] -> [Cell]
addCellAligns [Align]
as [Cell]
cs
addCellAligns []     (Cell
c:[Cell]
cs) = Cell
c Cell -> [Cell] -> [Cell]
forall a. a -> [a] -> [a]
: [Align] -> [Cell] -> [Cell]
addCellAligns [] [Cell]
cs
addCellAligns (Align
a:[Align]
as) []     = []
addCellAligns []     []     = []

updateCellAlign :: Align -> Cell -> Cell
updateCellAlign :: Align -> Cell -> Cell
updateCellAlign Align
a (Cell Span
s Span
w Align
_ Lines
xs) = Span -> Span -> Align -> Lines -> Cell
Cell Span
s Span
w Align
a Lines
xs

addCellWidths :: [Width] -> [Cell] -> [Cell]
addCellWidths :: [Span] -> [Cell] -> [Cell]
addCellWidths (Span
w:[Span]
ws) (Cell
c:[Cell]
cs) = Span -> Cell -> Cell
updateCellWidth Span
w Cell
c Cell -> [Cell] -> [Cell]
forall a. a -> [a] -> [a]
: [Span] -> [Cell] -> [Cell]
addCellWidths [Span]
ws [Cell]
cs
addCellWidths []     (Cell
c:[Cell]
cs) = Cell
c Cell -> [Cell] -> [Cell]
forall a. a -> [a] -> [a]
: [Span] -> [Cell] -> [Cell]
addCellWidths [] [Cell]
cs
addCellWidths (Span
w:[Span]
ws) []     = []
addCellWidths []     []     = []

updateCellWidth :: Width -> Cell -> Cell
updateCellWidth :: Span -> Cell -> Cell
updateCellWidth Span
w (Cell Span
s Span
_ Align
a Lines
xs) = Span -> Span -> Align -> Lines -> Cell
Cell Span
s Span
w Align
a Lines
xs

mkRows :: [Align] -> [Lines] -> [Row]
mkRows :: [Align] -> [Lines] -> [Row]
mkRows [Align]
as = ([Cell] -> Row) -> [[Cell]] -> [Row]
forall a b. (a -> b) -> [a] -> [b]
map [Cell] -> Row
Row ([[Cell]] -> [Row]) -> ([Lines] -> [[Cell]]) -> [Lines] -> [Row]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Align] -> [Lines] -> [[Cell]]
mkCells [Align]
as

mkColumns :: [Align] -> Row -> [Column]
mkColumns :: [Align] -> Row -> [Column]
mkColumns [Align]
as (Row [Cell]
cs) = [Align] -> [Cell] -> [Column]
columnify [Align]
as [Cell]
cs
                      where
                        columnify :: [Align] -> [Cell] -> [Column]
columnify (Align
a:[Align]
as) ((Cell Span
_ Span
w Align
_ Lines
_):[Cell]
cs) = Span -> Align -> Column
Column Span
w Align
a  Column -> [Column] -> [Column]
forall a. a -> [a] -> [a]
: [Align] -> [Cell] -> [Column]
columnify [Align]
as [Cell]
cs
                        columnify []     ((Cell Span
_ Span
w Align
_ Lines
_):[Cell]
cs) = Span -> Align -> Column
Column Span
w Align
DefaultAlign Column -> [Column] -> [Column]
forall a. a -> [a] -> [a]
: [Align] -> [Cell] -> [Column]
columnify [] [Cell]
cs
                        columnify (Align
a:[Align]
as) []                  = []
                        columnify []     []                  = []

mkTable :: Caption -> [Align] -> Bool -> [Lines] -> Table
mkTable :: String -> [Align] -> Bool -> [Lines] -> Table
mkTable String
c [Align]
as Bool
h [Lines]
xss = case Bool
h of
                       Bool
True  -> String -> [Column] -> Header -> [Row] -> Table
Table String
c [Column]
columns Header
mkHeader ([Row] -> Table) -> [Row] -> Table
forall a b. (a -> b) -> a -> b
$ [Row] -> [Row]
forall a. [a] -> [a]
tail ([Row] -> [Row]) -> [Row] -> [Row]
forall a b. (a -> b) -> a -> b
$ [Align] -> [Lines] -> [Row]
mkRows [Align]
as [Lines]
csv
                       Bool
False -> String -> [Column] -> Header -> [Row] -> Table
Table String
c [Column]
columns Header
NoHeader ([Row] -> Table) -> [Row] -> Table
forall a b. (a -> b) -> a -> b
$ [Align] -> [Lines] -> [Row]
mkRows [Align]
as [Lines]
csv
                   where
                     csv :: [Lines]
csv      = (Lines -> Bool) -> [Lines] -> [Lines]
forall a. (a -> Bool) -> [a] -> [a]
filter (Lines -> Lines -> Bool
forall a. Eq a => a -> a -> Bool
/=[String
""]) [Lines]
xss
                     columns :: [Column]
columns  = [Align] -> Row -> [Column]
mkColumns [Align]
as (Row -> [Column]) -> ([Lines] -> Row) -> [Lines] -> [Column]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Row] -> Row
forall a. [a] -> a
head ([Row] -> Row) -> ([Lines] -> [Row]) -> [Lines] -> Row
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Align] -> [Lines] -> [Row]
mkRows [Align]
as ([Lines] -> [Column]) -> [Lines] -> [Column]
forall a b. (a -> b) -> a -> b
$ [Lines]
csv
                     mkHeader :: Header
mkHeader = Row -> Header
Header (Row -> Header) -> Row -> Header
forall a b. (a -> b) -> a -> b
$ [Row] -> Row
forall a. [a] -> a
head ([Row] -> Row) -> [Row] -> Row
forall a b. (a -> b) -> a -> b
$ [Align] -> [Lines] -> [Row]
mkRows [Align]
as [Lines]
csv

insertRowSeparator :: TableType -> [Column] -> Lines -> Lines
insertRowSeparator :: TableType -> [Column] -> Lines -> Lines
insertRowSeparator (TableType
Multiline) [Column]
cs Lines
xs = String -> Lines -> Lines
forall a. a -> [a] -> [a]
intersperse String
"\n" Lines
xs
insertRowSeparator (TableType
Grid)      [Column]
cs Lines
xs = String -> Lines -> Lines
forall a. a -> [a] -> [a]
intersperse ([Column] -> String
separator [Column]
cs) Lines
xs
                                     where
                                       separator :: [Column] -> String
separator ((Column Span
w Align
_):[Column]
cs) = String
"+" String -> String -> String
forall a. [a] -> [a] -> [a]
++ Span -> Char -> String
forall a. Span -> a -> [a]
replicate (Span
wSpan -> Span -> Span
forall a. Num a => a -> a -> a
+Span
2) Char
'-' String -> String -> String
forall a. [a] -> [a] -> [a]
++ [Column] -> String
separator [Column]
cs
                                       separator []     = String
"+\n"
insertRowSeparator TableType
_           [Column]
_  Lines
_  = []
                                                 
mkTableBorder :: TableType -> [Column] -> String
mkTableBorder :: TableType -> [Column] -> String
mkTableBorder (TableType
Multiline) ((Column Span
w Align
_):[]) = Span -> Char -> String
forall a. Span -> a -> [a]
replicate Span
w Char
'-' String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"\n"
mkTableBorder (TableType
Multiline) ((Column Span
w Align
_):[Column]
cs) = Span -> Char -> String
forall a. Span -> a -> [a]
replicate (Span
wSpan -> Span -> Span
forall a. Num a => a -> a -> a
+Span
1) Char
'-' String -> String -> String
forall a. [a] -> [a] -> [a]
++ TableType -> [Column] -> String
mkTableBorder TableType
Multiline [Column]
cs
mkTableBorder (TableType
Grid)      []                = String
"+\n"
mkTableBorder (TableType
Grid)      ((Column Span
w Align
_):[Column]
cs) = String
"+" String -> String -> String
forall a. [a] -> [a] -> [a]
++ Span -> Char -> String
forall a. Span -> a -> [a]
replicate (Span
wSpan -> Span -> Span
forall a. Num a => a -> a -> a
+Span
2) Char
'-' String -> String -> String
forall a. [a] -> [a] -> [a]
++ TableType -> [Column] -> String
mkTableBorder TableType
Grid [Column]
cs
mkTableBorder TableType
_           [Column]
_                 = String
""

mkHeaderRowSeparator :: TableType -> [Column] -> String
mkHeaderRowSeparator :: TableType -> [Column] -> String
mkHeaderRowSeparator (TableType
Grid) ((Column Span
w Align
_):[Column]
cs) = String
"+" String -> String -> String
forall a. [a] -> [a] -> [a]
++ Span -> Char -> String
forall a. Span -> a -> [a]
replicate (Span
wSpan -> Span -> Span
forall a. Num a => a -> a -> a
+Span
2) Char
'=' String -> String -> String
forall a. [a] -> [a] -> [a]
++
                                                TableType -> [Column] -> String
mkHeaderRowSeparator TableType
Grid [Column]
cs
mkHeaderRowSeparator (TableType
Pipe) ((Column Span
w Align
a):[Column]
cs) = (let sep :: String
sep = String
"|" String -> String -> String
forall a. [a] -> [a] -> [a]
++ Span -> Char -> String
forall a. Span -> a -> [a]
replicate (Span
wSpan -> Span -> Span
forall a. Num a => a -> a -> a
+Span
2) Char
'-' 
                                                 in case Align
a of
                                                     Align
LeftAlign   -> String
"|:" String -> String -> String
forall a. [a] -> [a] -> [a]
++ (Span -> String -> String
forall a. Span -> [a] -> [a]
drop Span
2 String
sep)
                                                     Align
RightAlign  -> String -> String
forall a. [a] -> [a]
reverse (String -> String) -> String -> String
forall a b. (a -> b) -> a -> b
$ String
":" String -> String -> String
forall a. [a] -> [a] -> [a]
++ (Span -> String -> String
forall a. Span -> [a] -> [a]
drop Span
1 (String -> String) -> (String -> String) -> String -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> String
forall a. [a] -> [a]
reverse (String -> String) -> String -> String
forall a b. (a -> b) -> a -> b
$ String
sep)
                                                     Align
CenterAlign -> (String
"|:" String -> String -> String
forall a. [a] -> [a] -> [a]
++) (String -> String) -> String -> String
forall a b. (a -> b) -> a -> b
$ Span -> String -> String
forall a. Span -> [a] -> [a]
drop Span
2 (String -> String) -> String -> String
forall a b. (a -> b) -> a -> b
$ String -> String
forall a. [a] -> [a]
reverse (String -> String) -> String -> String
forall a b. (a -> b) -> a -> b
$ String
":" String -> String -> String
forall a. [a] -> [a] -> [a]
++ (Span -> String -> String
forall a. Span -> [a] -> [a]
drop Span
1 (String -> String) -> (String -> String) -> String -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> String
forall a. [a] -> [a]
reverse (String -> String) -> String -> String
forall a b. (a -> b) -> a -> b
$ String
sep)
                                                     Align
_           -> String -> String
forall a. [a] -> [a]
reverse (String -> String) -> (String -> String) -> String -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Span -> String -> String
forall a. Span -> [a] -> [a]
drop Span
1(String -> String) -> (String -> String) -> String -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> String
forall a. [a] -> [a]
reverse (String -> String) -> String -> String
forall a b. (a -> b) -> a -> b
$ String
sep ) String -> String -> String
forall a. [a] -> [a] -> [a]
++
                                                TableType -> [Column] -> String
mkHeaderRowSeparator TableType
Pipe [Column]
cs
mkHeaderRowSeparator (TableType
Grid) []                = String
"+\n"
mkHeaderRowSeparator (TableType
Pipe) []                = String
"|\n"
mkHeaderRowSeparator TableType
t      ((Column Span
w Align
_):[]) = Span -> Char -> String
forall a. Span -> a -> [a]
replicate Span
w Char
'-' String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"\n"
mkHeaderRowSeparator TableType
t      ((Column Span
w Align
_):[Column]
cs) = Span -> Char -> String
forall a. Span -> a -> [a]
replicate Span
w Char
'-' String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" " String -> String -> String
forall a. [a] -> [a] -> [a]
++
                                                TableType -> [Column] -> String
mkHeaderRowSeparator TableType
t [Column]
cs

-- | Add members to pad cell content based on span
padCell :: Cell -> Cell
padCell :: Cell -> Cell
padCell (Cell Span
s Span
w Align
a Lines
xs) = Span -> Span -> Align -> Lines -> Cell
Cell Span
s Span
w Align
a (Lines
xs Lines -> Lines -> Lines
forall a. [a] -> [a] -> [a]
++ Lines
padList)
                        where
                          padList :: Lines
padList  = Span -> String -> Lines
forall a. Span -> a -> [a]
replicate Span
padByNum (Span -> String -> String
forall a. Span -> [a] -> [a]
take Span
w (String -> String) -> String -> String
forall a b. (a -> b) -> a -> b
$ Char -> String
forall a. a -> [a]
repeat Char
' ')
                          padByNum :: Span
padByNum = Span
s Span -> Span -> Span
forall a. Num a => a -> a -> a
- Lines -> Span
forall (t :: * -> *) a. Foldable t => t a -> Span
length Lines
xs

-- | Expects padded cells
alignCellStrings :: TableType -> Cell -> Lines
alignCellStrings :: TableType -> Cell -> Lines
alignCellStrings (TableType
Grid) (Cell Span
_ Span
w Align
a Lines
cs) = (String -> String) -> Lines -> Lines
forall a b. (a -> b) -> [a] -> [b]
map (Span -> Align -> String -> String
alignText Span
w Align
LeftAlign) Lines
cs
alignCellStrings TableType
_      (Cell Span
_ Span
w Align
a Lines
cs) = (String -> String) -> Lines -> Lines
forall a b. (a -> b) -> [a] -> [b]
map (Span -> Align -> String -> String
alignText Span
w Align
a) Lines
cs

cellToLines :: TableType -> Cell -> Lines
cellToLines :: TableType -> Cell -> Lines
cellToLines TableType
t = TableType -> Cell -> Lines
alignCellStrings TableType
t (Cell -> Lines) -> (Cell -> Cell) -> Cell -> Lines
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Cell -> Cell
padCell

flatten :: [Lines] -> String
flatten :: [Lines] -> String
flatten = (String -> String) -> Lines -> String
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (String -> String -> String
forall a. [a] -> [a] -> [a]
++String
"\n") (Lines -> String) -> ([Lines] -> Lines) -> [Lines] -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Lines -> String) -> [Lines] -> Lines
forall a b. (a -> b) -> [a] -> [b]
map Lines -> String
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat

addGutter :: Gutter -> Lines -> Lines
addGutter :: Span -> Lines -> Lines
addGutter Span
g (String
x:Lines
xs) = String
x String -> Lines -> Lines
forall a. a -> [a] -> [a]
: (String -> String) -> Lines -> Lines
forall a b. (a -> b) -> [a] -> [b]
map ((Span -> Char -> String
forall a. Span -> a -> [a]
replicate Span
g Char
' ')String -> String -> String
forall a. [a] -> [a] -> [a]
++) Lines
xs

alignText :: Width -> Align -> String -> String
alignText :: Span -> Align -> String -> String
alignText Span
w (Align
LeftAlign)    = Text -> String
unpack (Text -> String) -> (String -> Text) -> String -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Span -> Char -> Text -> Text
justifyLeft   Span
w Char
' ' (Text -> Text) -> (String -> Text) -> String -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Text
strip (Text -> Text) -> (String -> Text) -> String -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Text
pack
alignText Span
w (Align
RightAlign)   = Text -> String
unpack (Text -> String) -> (String -> Text) -> String -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Span -> Char -> Text -> Text
justifyRight  Span
w Char
' ' (Text -> Text) -> (String -> Text) -> String -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Text
strip (Text -> Text) -> (String -> Text) -> String -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Text
pack
alignText Span
w (Align
CenterAlign)  = Text -> String
unpack (Text -> String) -> (String -> Text) -> String -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Span -> Char -> Text -> Text
center        Span
w Char
' ' (Text -> Text) -> (String -> Text) -> String -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Text
strip (Text -> Text) -> (String -> Text) -> String -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Text
pack
alignText Span
w (Align
DefaultAlign) = Text -> String
unpack (Text -> String) -> (String -> Text) -> String -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Span -> Char -> Text -> Text
justifyLeft   Span
w Char
' ' (Text -> Text) -> (String -> Text) -> String -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Text
strip (Text -> Text) -> (String -> Text) -> String -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Text
pack

row2Md :: TableType -> Row -> String
row2Md :: TableType -> Row -> String
row2Md (TableType
Grid) (Row [Cell]
cs) = [Lines] -> String
flatten ([Lines] -> String) -> [Lines] -> String
forall a b. (a -> b) -> a -> b
$ [Lines] -> [Lines]
forall a. [[a]] -> [[a]]
transpose ([Lines] -> [Lines]) -> [Lines] -> [Lines]
forall a b. (a -> b) -> a -> b
$ [Lines] -> [Lines]
appendPipes ([Lines] -> [Lines]) -> [Lines] -> [Lines]
forall a b. (a -> b) -> a -> b
$ (Cell -> Lines) -> [Cell] -> [Lines]
forall a b. (a -> b) -> [a] -> [b]
map (TableType -> Cell -> Lines
cellToLines TableType
Grid) [Cell]
cs
row2Md (TableType
Pipe) (Row [Cell]
cs) = [Lines] -> String
flatten ([Lines] -> String) -> [Lines] -> String
forall a b. (a -> b) -> a -> b
$ [Lines] -> [Lines]
forall a. [[a]] -> [[a]]
transpose ([Lines] -> [Lines]) -> [Lines] -> [Lines]
forall a b. (a -> b) -> a -> b
$ [Lines] -> [Lines]
appendPipes ([Lines] -> [Lines]) -> [Lines] -> [Lines]
forall a b. (a -> b) -> a -> b
$ (Cell -> Lines) -> [Cell] -> [Lines]
forall a b. (a -> b) -> [a] -> [b]
map (TableType -> Cell -> Lines
cellToLines TableType
Pipe) [Cell]
cs
row2Md TableType
t      (Row [Cell]
cs) = [Lines] -> String
flatten ([Lines] -> String) -> [Lines] -> String
forall a b. (a -> b) -> a -> b
$ (Lines -> Lines) -> [Lines] -> [Lines]
forall a b. (a -> b) -> [a] -> [b]
map (Span -> Lines -> Lines
addGutter Span
1) ([Lines] -> [Lines]) -> [Lines] -> [Lines]
forall a b. (a -> b) -> a -> b
$ [Lines] -> [Lines]
forall a. [[a]] -> [[a]]
transpose ([Lines] -> [Lines]) -> [Lines] -> [Lines]
forall a b. (a -> b) -> a -> b
$ (Cell -> Lines) -> [Cell] -> [Lines]
forall a b. (a -> b) -> [a] -> [b]
map (TableType -> Cell -> Lines
cellToLines TableType
t) [Cell]
cs

appendPipes :: [Lines] -> [Lines]
appendPipes :: [Lines] -> [Lines]
appendPipes (Lines
xs:[])  = [(String -> String) -> Lines -> Lines
forall a b. (a -> b) -> [a] -> [b]
map (String -> String -> String
forall a. [a] -> [a] -> [a]
++String
" |") Lines
xs]
appendPipes (Lines
xs:[Lines]
xss) = (String -> String) -> Lines -> Lines
forall a b. (a -> b) -> [a] -> [b]
map ((String
"| "String -> String -> String
forall a. [a] -> [a] -> [a]
++) (String -> String) -> (String -> String) -> String -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (String -> String -> String
forall a. [a] -> [a] -> [a]
++String
" | ")) Lines
xs Lines -> [Lines] -> [Lines]
forall a. a -> [a] -> [a]
: ((Lines -> Lines) -> [Lines] -> [Lines]
forall a b. (a -> b) -> [a] -> [b]
map ((String -> String) -> Lines -> Lines
forall a b. (a -> b) -> [a] -> [b]
map (String -> String -> String
forall a. [a] -> [a] -> [a]
++String
" | ")) [Lines]
xss)

addCaption :: CaptionPos -> Caption -> String -> String
addCaption :: CaptionPos -> String -> String -> String
addCaption CaptionPos
_             [] String
s = String
s
addCaption (CaptionPos
BeforeTable) String
c  String
s = String
"Table: " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
c String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"\n\n" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
s
addCaption (CaptionPos
AfterTable)  String
c  String
s = String
s String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"\nTable: " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
c

toMarkdown :: TableType -> CaptionPos -> Table -> String
toMarkdown :: TableType -> CaptionPos -> Table -> String
toMarkdown (TableType
Simple)    = CaptionPos -> Table -> String
toSimpleMd
toMarkdown (TableType
Multiline) = CaptionPos -> Table -> String
toMultilineMd
toMarkdown (TableType
Grid)      = CaptionPos -> Table -> String
toGridMd
toMarkdown (TableType
Pipe)      = CaptionPos -> Table -> String
toPipeMd

toMultilineMd :: CaptionPos -> Table -> String
toMultilineMd :: CaptionPos -> Table -> String
toMultilineMd CaptionPos
l (Table String
c [Column]
cs (Header Row
h) [Row]
rs) = CaptionPos -> String -> String -> String
addCaption CaptionPos
l String
c (String -> String) -> String -> String
forall a b. (a -> b) -> a -> b
$
                                             TableType -> [Column] -> String
mkTableBorder TableType
Multiline [Column]
cs String -> String -> String
forall a. [a] -> [a] -> [a]
++
                                             TableType -> Row -> String
row2Md TableType
Multiline Row
h String -> String -> String
forall a. [a] -> [a] -> [a]
++
                                             TableType -> [Column] -> String
mkHeaderRowSeparator TableType
Multiline [Column]
cs String -> String -> String
forall a. [a] -> [a] -> [a]
++
                                             ((String -> String) -> Lines -> String
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (String -> String -> String
forall a. [a] -> [a] -> [a]
++String
"") (Lines -> String) -> Lines -> String
forall a b. (a -> b) -> a -> b
$
                                              TableType -> [Column] -> Lines -> Lines
insertRowSeparator TableType
Multiline [Column]
cs (Lines -> Lines) -> Lines -> Lines
forall a b. (a -> b) -> a -> b
$
                                              (Row -> String) -> [Row] -> Lines
forall a b. (a -> b) -> [a] -> [b]
map (TableType -> Row -> String
row2Md TableType
Multiline) [Row]
rs) String -> String -> String
forall a. [a] -> [a] -> [a]
++
                                             TableType -> [Column] -> String
mkTableBorder TableType
Multiline [Column]
cs
toMultilineMd CaptionPos
l (Table String
c [Column]
cs (Header
NoHeader) [Row]
rs) = CaptionPos -> String -> String -> String
addCaption CaptionPos
l String
c (String -> String) -> String -> String
forall a b. (a -> b) -> a -> b
$
                                             TableType -> [Column] -> String
mkHeaderRowSeparator TableType
Multiline [Column]
cs String -> String -> String
forall a. [a] -> [a] -> [a]
++
                                             ((String -> String) -> Lines -> String
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (String -> String -> String
forall a. [a] -> [a] -> [a]
++String
"") (Lines -> String) -> Lines -> String
forall a b. (a -> b) -> a -> b
$
                                              TableType -> [Column] -> Lines -> Lines
insertRowSeparator TableType
Multiline [Column]
cs (Lines -> Lines) -> Lines -> Lines
forall a b. (a -> b) -> a -> b
$
                                              (Row -> String) -> [Row] -> Lines
forall a b. (a -> b) -> [a] -> [b]
map (TableType -> Row -> String
row2Md TableType
Multiline) [Row]
rs) String -> String -> String
forall a. [a] -> [a] -> [a]
++
                                             TableType -> [Column] -> String
mkHeaderRowSeparator TableType
Multiline [Column]
cs

toGridMd :: CaptionPos -> Table -> String
toGridMd :: CaptionPos -> Table -> String
toGridMd CaptionPos
l (Table String
c [Column]
cs (Header Row
h) [Row]
rs) = CaptionPos -> String -> String -> String
addCaption CaptionPos
l String
c (String -> String) -> String -> String
forall a b. (a -> b) -> a -> b
$
                                        TableType -> [Column] -> String
mkTableBorder TableType
Grid [Column]
cs String -> String -> String
forall a. [a] -> [a] -> [a]
++
                                        TableType -> Row -> String
row2Md TableType
Grid Row
h String -> String -> String
forall a. [a] -> [a] -> [a]
++
                                        TableType -> [Column] -> String
mkHeaderRowSeparator TableType
Grid [Column]
cs String -> String -> String
forall a. [a] -> [a] -> [a]
++
                                        ((String -> String) -> Lines -> String
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (String -> String -> String
forall a. [a] -> [a] -> [a]
++String
"") (Lines -> String) -> Lines -> String
forall a b. (a -> b) -> a -> b
$
                                         TableType -> [Column] -> Lines -> Lines
insertRowSeparator TableType
Grid [Column]
cs (Lines -> Lines) -> Lines -> Lines
forall a b. (a -> b) -> a -> b
$
                                         (Row -> String) -> [Row] -> Lines
forall a b. (a -> b) -> [a] -> [b]
map (TableType -> Row -> String
row2Md TableType
Grid) [Row]
rs) String -> String -> String
forall a. [a] -> [a] -> [a]
++
                                        TableType -> [Column] -> String
mkTableBorder TableType
Grid [Column]
cs
toGridMd CaptionPos
l (Table String
c [Column]
cs (Header
NoHeader) [Row]
rs) = CaptionPos -> String -> String -> String
addCaption CaptionPos
l String
c (String -> String) -> String -> String
forall a b. (a -> b) -> a -> b
$
                                        TableType -> [Column] -> String
mkTableBorder TableType
Grid [Column]
cs String -> String -> String
forall a. [a] -> [a] -> [a]
++
                                        ((String -> String) -> Lines -> String
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (String -> String -> String
forall a. [a] -> [a] -> [a]
++String
"") (Lines -> String) -> Lines -> String
forall a b. (a -> b) -> a -> b
$
                                         TableType -> [Column] -> Lines -> Lines
insertRowSeparator TableType
Grid [Column]
cs (Lines -> Lines) -> Lines -> Lines
forall a b. (a -> b) -> a -> b
$
                                         (Row -> String) -> [Row] -> Lines
forall a b. (a -> b) -> [a] -> [b]
map (TableType -> Row -> String
row2Md TableType
Grid) [Row]
rs) String -> String -> String
forall a. [a] -> [a] -> [a]
++
                                        TableType -> [Column] -> String
mkTableBorder TableType
Grid [Column]
cs

toPipeMd :: CaptionPos -> Table -> String
toPipeMd :: CaptionPos -> Table -> String
toPipeMd CaptionPos
l (Table String
c [Column]
cs (Header Row
h) [Row]
rs) = CaptionPos -> String -> String -> String
addCaption CaptionPos
l String
c (String -> String) -> String -> String
forall a b. (a -> b) -> a -> b
$
                                        TableType -> Row -> String
row2Md TableType
Pipe Row
h String -> String -> String
forall a. [a] -> [a] -> [a]
++
                                        TableType -> [Column] -> String
mkHeaderRowSeparator TableType
Pipe [Column]
cs String -> String -> String
forall a. [a] -> [a] -> [a]
++
                                        ((String -> String) -> Lines -> String
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (String -> String -> String
forall a. [a] -> [a] -> [a]
++String
"") (Lines -> String) -> Lines -> String
forall a b. (a -> b) -> a -> b
$
                                         (Row -> String) -> [Row] -> Lines
forall a b. (a -> b) -> [a] -> [b]
map (TableType -> Row -> String
row2Md TableType
Pipe) [Row]
rs)
toPipeMd CaptionPos
l (Table String
c [Column]
cs (Header
NoHeader) [Row]
rs) = CaptionPos -> String -> String -> String
addCaption CaptionPos
l String
c (String -> String) -> String -> String
forall a b. (a -> b) -> a -> b
$
                                        TableType -> [Column] -> String
mkHeaderRowSeparator TableType
Pipe [Column]
cs String -> String -> String
forall a. [a] -> [a] -> [a]
++
                                        ((String -> String) -> Lines -> String
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (String -> String -> String
forall a. [a] -> [a] -> [a]
++String
"") (Lines -> String) -> Lines -> String
forall a b. (a -> b) -> a -> b
$
                                         (Row -> String) -> [Row] -> Lines
forall a b. (a -> b) -> [a] -> [b]
map (TableType -> Row -> String
row2Md TableType
Pipe) [Row]
rs)

toSimpleMd :: CaptionPos -> Table -> String
toSimpleMd :: CaptionPos -> Table -> String
toSimpleMd CaptionPos
l (Table String
c [Column]
cs (Header Row
h) [Row]
rs) = CaptionPos -> String -> String -> String
addCaption CaptionPos
l String
c (String -> String) -> String -> String
forall a b. (a -> b) -> a -> b
$
                                          TableType -> Row -> String
row2Md TableType
Simple Row
h String -> String -> String
forall a. [a] -> [a] -> [a]
++
                                          TableType -> [Column] -> String
mkHeaderRowSeparator TableType
Simple [Column]
cs String -> String -> String
forall a. [a] -> [a] -> [a]
++
                                          ((String -> String) -> Lines -> String
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (String -> String -> String
forall a. [a] -> [a] -> [a]
++String
"") (Lines -> String) -> Lines -> String
forall a b. (a -> b) -> a -> b
$
                                           (Row -> String) -> [Row] -> Lines
forall a b. (a -> b) -> [a] -> [b]
map (TableType -> Row -> String
row2Md TableType
Simple) [Row]
rs) String -> String -> String
forall a. [a] -> [a] -> [a]
++
                                          TableType -> [Column] -> String
mkHeaderRowSeparator TableType
Simple [Column]
cs
toSimpleMd CaptionPos
l (Table String
c [Column]
cs (Header
NoHeader) [Row]
rs) = CaptionPos -> String -> String -> String
addCaption CaptionPos
l String
c (String -> String) -> String -> String
forall a b. (a -> b) -> a -> b
$
                                          TableType -> [Column] -> String
mkHeaderRowSeparator TableType
Simple [Column]
cs String -> String -> String
forall a. [a] -> [a] -> [a]
++
                                          ((String -> String) -> Lines -> String
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (String -> String -> String
forall a. [a] -> [a] -> [a]
++String
"") (Lines -> String) -> Lines -> String
forall a b. (a -> b) -> a -> b
$
                                           (Row -> String) -> [Row] -> Lines
forall a b. (a -> b) -> [a] -> [b]
map (TableType -> Row -> String
row2Md TableType
Simple) [Row]
rs) String -> String -> String
forall a. [a] -> [a] -> [a]
++
                                          TableType -> [Column] -> String
mkHeaderRowSeparator TableType
Simple [Column]
cs