-- | Defines main Markdown printer functions.
module Language.Drasil.Markdown.Print(genMDBook, pSpec) where

import Prelude hiding (print, (<>))
import qualified Prelude as P ((<>))
import Text.PrettyPrint hiding (Str)
import Data.List (transpose)
import Data.List.Utils (replace)

import qualified Language.Drasil as L

import Language.Drasil.Printing.Import (makeProject)
import Language.Drasil.Printing.AST (ItemType(Flat, Nested),  
  ListType(Ordered, Unordered, Definitions, Desc, Simple), Expr, 
  Expr(..), Spec(Quote, EmptyS, Ref, HARDNL, E, (:+:)), Label, 
  LinkType(Internal, Cite2, External), OverSymb(Hat), Fonts(Emph, Bold), 
  Spacing(Thin), Fence(Abs), Ops(Perc, Mul))
import Language.Drasil.Printing.Citation (BibRef)
import Language.Drasil.Printing.LayoutObj (Project(Project), 
  LayoutObj(..), Filename, RefMap, File(File))
import Language.Drasil.Printing.Helpers (sqbrac, pipe, bslash, unders, 
  hat, hyph, dot, ($^$), vsep)
import Language.Drasil.Printing.PrintingInformation (PrintingInformation)

import qualified Language.Drasil.TeX.Print as TeX (pExpr, fence, OpenClose(..),
  pMatrix, cases)
import Language.Drasil.TeX.Monad (runPrint, MathContext(Math), D, toMath, toText,
  hpunctuate)
import qualified Language.Drasil.HTML.Print as HTML (renderCite, pSpec)
import Language.Drasil.HTML.Helpers(BibFormatter(..))
import Language.Drasil.TeX.Helpers(commandD, command2D, mkEnv)

import Language.Drasil.Markdown.Helpers (heading, image, li, reflink,
  reflinkURI, reflinkInfo, caption, bold, ul, docLength, divTag, centeredDiv, 
  em, h, h', centeredDivId)

-----------------------------------------------------------------
------------------------- mdBook SRS ----------------------------
-----------------------------------------------------------------

-- | Generate a mdBook SRS
genMDBook :: PrintingInformation -> L.Document -> [(Filename, Doc)]
genMDBook :: PrintingInformation -> Document -> [(String, Doc)]
genMDBook PrintingInformation
sm Document
doc = Project -> [(String, Doc)]
build' (Project -> [(String, Doc)]) -> Project -> [(String, Doc)]
forall a b. (a -> b) -> a -> b
$ PrintingInformation -> Document -> Project
makeProject PrintingInformation
sm Document
doc

-- | Build the mdBook Docs, called by genMD'
build' :: Project -> [(Filename, Doc)]
build' :: Project -> [(String, Doc)]
build' p :: Project
p@(Project Title
_ Title
_ RefMap
rm [File]
d) = 
  RefMap -> [File] -> (String, Doc)
printSummary RefMap
rm [File]
files (String, Doc) -> [(String, Doc)] -> [(String, Doc)]
forall a. a -> [a] -> [a]
: (File -> (String, Doc)) -> [File] -> [(String, Doc)]
forall a b. (a -> b) -> [a] -> [b]
map (RefMap -> File -> (String, Doc)
print' RefMap
rm) [File]
files
  where
    files :: [File]
files = Project -> File
createTitleFile Project
p File -> [File] -> [File]
forall a. a -> [a] -> [a]
: [File]
d

-- | Called by build', uses 'printLO' to render a File 
-- into a single Doc
print' :: RefMap -> File -> (Filename, Doc)
print' :: RefMap -> File -> (String, Doc)
print' RefMap
rm (File Title
_ String
n Int
_ [LayoutObj]
c) = (String
n, RefMap -> [LayoutObj] -> Doc
print RefMap
rm [LayoutObj]
c)

-- | Uses 'printLO' to render the layout objects 
-- into a single Doc
print :: RefMap -> [LayoutObj] -> Doc
print :: RefMap -> [LayoutObj] -> Doc
print RefMap
rm = [Doc] -> Doc
vsep ([Doc] -> Doc) -> ([LayoutObj] -> [Doc]) -> [LayoutObj] -> Doc
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (LayoutObj -> Doc) -> [LayoutObj] -> [Doc]
forall a b. (a -> b) -> [a] -> [b]
map (RefMap -> LayoutObj -> Doc
printLO RefMap
rm)

-- | Renders a 'SUMMARY.md' file
printSummary :: RefMap -> [File] -> (Filename, Doc)
printSummary :: RefMap -> [File] -> (String, Doc)
printSummary RefMap
rm [File]
f = (String
"SUMMARY", [Doc] -> Doc
vcat ([Doc] -> Doc) -> [Doc] -> Doc
forall a b. (a -> b) -> a -> b
$ (File -> Doc) -> [File] -> [Doc]
forall a b. (a -> b) -> [a] -> [b]
map (RefMap -> File -> Doc
summaryItem RefMap
rm) [File]
f)

-- | Helper for rendering a 'SUMMARY.md' item
summaryItem :: RefMap -> File -> Doc
summaryItem :: RefMap -> File -> Doc
summaryItem RefMap
rm (File Title
t String
n Int
d [LayoutObj]
_) = Doc
bullet Doc -> Doc -> Doc
<+> Doc
lbl Doc -> Doc -> Doc
<> Doc
ref
  where
    bullet :: Doc
bullet = String -> Doc
text (Int -> Char -> String
forall a. Int -> a -> [a]
replicate (Int
dInt -> Int -> Int
forall a. Num a => a -> a -> a
*Int
2) Char
' ') Doc -> Doc -> Doc
<> String -> Doc
text String
"-"
    lbl :: Doc
lbl    = Doc -> Doc
brackets (Doc -> Doc) -> Doc -> Doc
forall a b. (a -> b) -> a -> b
$ RefMap -> Title -> Doc
pSpec RefMap
rm Title
t
    ref :: Doc
ref    = Doc -> Doc
parens (Doc -> Doc) -> Doc -> Doc
forall a b. (a -> b) -> a -> b
$ String -> Doc
text (String -> Doc) -> String -> Doc
forall a b. (a -> b) -> a -> b
$ String
"./" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
n String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
".md"

-- | Create a title page file for a Project
createTitleFile :: Project -> File
createTitleFile :: Project -> File
createTitleFile (Project Title
t Title
a RefMap
_ [File]
_) = Title -> String -> Int -> [LayoutObj] -> File
File Title
t String
"title" Int
0 [LayoutObj]
cons
  where 
    cons :: [LayoutObj]
cons = [Int -> Title -> Title -> LayoutObj
Header Int
0 Title
t Title
EmptyS, Title -> LayoutObj
Paragraph Title
a]

-----------------------------------------------------------------
------------------- LAYOUT OBJECT PRINTING ----------------------
-----------------------------------------------------------------

-- | Helper for rendering LayoutObjects into Markdown
printLO :: RefMap -> LayoutObj -> Doc
printLO :: RefMap -> LayoutObj -> Doc
printLO RefMap
rm (Header Int
n Title
contents Title
l) = Int -> Doc
h (Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1) Doc -> Doc -> Doc
<+> Doc -> Doc -> Doc
heading (RefMap -> Title -> Doc
pSpec RefMap
rm Title
contents) (RefMap -> Title -> Doc
pSpec RefMap
rm Title
l)
printLO RefMap
rm (Cell [LayoutObj]
layoutObs)      = RefMap -> [LayoutObj] -> Doc
print RefMap
rm [LayoutObj]
layoutObs
printLO RefMap
rm (HDiv Tags
_ [LayoutObj]
layoutObs Title
_)  = RefMap -> [LayoutObj] -> Doc
print RefMap
rm [LayoutObj]
layoutObs
printLO RefMap
rm (Paragraph Title
contents)  = RefMap -> Title -> Doc
pSpec RefMap
rm Title
contents
printLO RefMap
rm (EqnBlock Title
contents)   = String -> Doc
text String
"\\\\[" Doc -> Doc -> Doc
<> Title -> Doc
rndr Title
contents Doc -> Doc -> Doc
<> String -> Doc
text String
"\\\\]"
  where
    rndr :: Title -> Doc
rndr (E Expr
e) = Expr -> Doc
pExpr Expr
e
    rndr Title
c = RefMap -> Title -> Doc
pSpec RefMap
rm Title
c
printLO RefMap
rm (Table Tags
_ [[Title]]
rows Title
r Bool
b Title
t)  = RefMap -> [[Title]] -> Doc -> Bool -> Doc -> Doc
makeTable RefMap
rm [[Title]]
rows (RefMap -> Title -> Doc
pSpec RefMap
rm Title
r) Bool
b (RefMap -> Title -> Doc
pSpec RefMap
rm Title
t)
printLO RefMap
rm (Definition DType
_ [(String, [LayoutObj])]
ssPs Title
l) = RefMap -> [(String, [LayoutObj])] -> Doc -> Doc
makeDefn RefMap
rm [(String, [LayoutObj])]
ssPs (RefMap -> Title -> Doc
pSpec RefMap
rm Title
l)
printLO RefMap
rm (List ListType
t)              = RefMap -> ListType -> Int -> Doc
makeList RefMap
rm ListType
t Int
0
printLO RefMap
rm (Figure Title
r Maybe Title
c String
f MaxWidthPercent
_)      = Doc -> Maybe Doc -> Doc -> Doc
makeFigure (RefMap -> Title -> Doc
pSpec RefMap
rm Title
r) ((Title -> Doc) -> Maybe Title -> Maybe Doc
forall a b. (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (RefMap -> Title -> Doc
pSpec RefMap
rm) Maybe Title
c) (String -> Doc
text String
f)
printLO RefMap
rm (Bib BibRef
bib)             = RefMap -> BibRef -> Doc
makeBib RefMap
rm BibRef
bib
printLO RefMap
_ Graph {}               = Doc
empty 
printLO RefMap
_ CodeBlock {}           = Doc
empty

-----------------------------------------------------------------
----------------------- SPEC PRINTING ---------------------------
-----------------------------------------------------------------

-- | Helper for rendering Specs into Markdown
pSpec :: RefMap -> Spec -> Doc
pSpec :: RefMap -> Title -> Doc
pSpec RefMap
_ (E Expr
e)      = String -> Doc
text String
"\\\\(" Doc -> Doc -> Doc
<> Expr -> Doc
pExpr Expr
e Doc -> Doc -> Doc
<> String -> Doc
text String
"\\\\)"
pSpec RefMap
rm (Title
a :+: Title
b) = RefMap -> Title -> Doc
pSpec RefMap
rm Title
a Doc -> Doc -> Doc
<> RefMap -> Title -> Doc
pSpec RefMap
rm Title
b
pSpec RefMap
_ Title
HARDNL     = String -> Doc
text String
"\n"
pSpec RefMap
rm (Ref LinkType
Internal       String
r Title
a) = RefMap -> String -> Doc -> Doc
reflink     RefMap
rm String
r (RefMap -> Title -> Doc
pSpec RefMap
rm Title
a)
pSpec RefMap
rm (Ref (Cite2 Title
EmptyS) String
r Title
a) = RefMap -> String -> Doc -> Doc
reflink     RefMap
rm String
r (RefMap -> Title -> Doc
pSpec RefMap
rm Title
a)
pSpec RefMap
rm (Ref (Cite2 Title
n)      String
r Title
a) = RefMap -> String -> Doc -> Doc -> Doc
reflinkInfo RefMap
rm String
r (RefMap -> Title -> Doc
pSpec RefMap
rm Title
a) (RefMap -> Title -> Doc
pSpec RefMap
rm Title
n)
pSpec RefMap
rm (Ref LinkType
External       String
r Title
a) = Doc -> Doc -> Doc
reflinkURI  (String -> Doc
text String
r) (RefMap -> Title -> Doc
pSpec RefMap
rm Title
a)
pSpec RefMap
rm (Quote Title
q) = Doc -> Doc
doubleQuotes (Doc -> Doc) -> Doc -> Doc
forall a b. (a -> b) -> a -> b
$ RefMap -> Title -> Doc
pSpec RefMap
rm Title
q
pSpec RefMap
_ Title
s          = Title -> Doc
HTML.pSpec Title
s 

-----------------------------------------------------------------
-------------------- EXPRESSION PRINTING ------------------------
-----------------------------------------------------------------

-- | Helper for rendering Exprs into mdBook compatiable Mathjax
pExpr :: Expr -> Doc
pExpr :: Expr -> Doc
pExpr (Str String
s)        = D -> Doc
printMath (D -> Doc) -> D -> Doc
forall a b. (a -> b) -> a -> b
$ D -> D
toText (D -> D) -> D -> D
forall a b. (a -> b) -> a -> b
$ Doc -> D
forall a. a -> PrintLaTeX a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Doc -> D) -> Doc -> D
forall a b. (a -> b) -> a -> b
$ Doc
lq Doc -> Doc -> Doc
<> String -> Doc
text String
s Doc -> Doc -> Doc
<> Doc
rq
  where 
    lq :: Doc
lq = String -> Doc
text String
"\\\\(\\``\\\\)"
    rq :: Doc
rq = String -> Doc
text String
"''"
pExpr (Div Expr
n Expr
d)      = D -> Doc
printMath (D -> Doc) -> D -> Doc
forall a b. (a -> b) -> a -> b
$ String -> D -> D -> D
command2D String
"frac" (Expr -> D
pExpr' Expr
n) (Expr -> D
pExpr' Expr
d)
pExpr (Case [(Expr, Expr)]
ps)      = D -> Doc
printMath (D -> Doc) -> D -> Doc
forall a b. (a -> b) -> a -> b
$ String -> (D -> D -> D) -> D -> D
mkEnv String
"cases" D -> D -> D
forall a. Semigroup a => a -> a -> a
(P.<>) D
cases
  where
    cases :: D
cases = [(Expr, Expr)] -> (Doc -> [D] -> D) -> Doc -> (Expr -> D) -> D
TeX.cases [(Expr, Expr)]
ps Doc -> [D] -> D
hpunctuate Doc
lnl Expr -> D
pExpr'
pExpr (Mtx [[Expr]]
a)        = D -> Doc
printMath (D -> Doc) -> D -> Doc
forall a b. (a -> b) -> a -> b
$ String -> (D -> D -> D) -> D -> D
mkEnv String
"bmatrix" D -> D -> D
forall a. Semigroup a => a -> a -> a
(P.<>) D
matrix
  where 
    matrix :: D
matrix = [[Expr]] -> (Doc -> [D] -> D) -> Doc -> (Expr -> D) -> D
TeX.pMatrix [[Expr]]
a Doc -> [D] -> D
hpunctuate Doc
lnl Expr -> D
pExpr'
pExpr (Row [Expr
x])      = Doc -> Doc
braces (Doc -> Doc) -> Doc -> Doc
forall a b. (a -> b) -> a -> b
$ Expr -> Doc
pExpr Expr
x 
pExpr (Row [Expr]
l)        = (Doc -> Doc -> Doc) -> [Doc] -> Doc
forall a. (a -> a -> a) -> [a] -> a
forall (t :: * -> *) a. Foldable t => (a -> a -> a) -> t a -> a
foldl1 Doc -> Doc -> Doc
(<>) ((Expr -> Doc) -> [Expr] -> [Doc]
forall a b. (a -> b) -> [a] -> [b]
map Expr -> Doc
pExpr [Expr]
l)
pExpr (Label String
s)      = D -> Doc
printMath (D -> Doc) -> D -> Doc
forall a b. (a -> b) -> a -> b
$ Expr -> D
TeX.pExpr (String -> Expr
Label String
s')
  where s' :: String
s' = String -> String -> String -> String
forall a. Eq a => [a] -> [a] -> [a] -> [a]
replace String
"*" String
"\\*" (String -> String -> String -> String
forall a. Eq a => [a] -> [a] -> [a] -> [a]
replace String
"_" String
"\\_" String
s)
pExpr (Sub Expr
e)        = Doc
bslash Doc -> Doc -> Doc
<> Doc
unders Doc -> Doc -> Doc
<> Doc -> Doc
braces (Expr -> Doc
pExpr Expr
e)
pExpr (Sup Expr
e)        = Doc
hat    Doc -> Doc -> Doc
<> Doc -> Doc
braces (Expr -> Doc
pExpr Expr
e)
pExpr (Over OverSymb
Hat Expr
s)   = D -> Doc
printMath (D -> Doc) -> D -> Doc
forall a b. (a -> b) -> a -> b
$ String -> D -> D
commandD String
"hat" (Expr -> D
pExpr' Expr
s)
pExpr (MO Ops
o)
  | Ops
o Ops -> Ops -> Bool
forall a. Eq a => a -> a -> Bool
== Ops
Perc Bool -> Bool -> Bool
|| Ops
o Ops -> Ops -> Bool
forall a. Eq a => a -> a -> Bool
== Ops
Mul = Doc
bslash Doc -> Doc -> Doc
<> D -> Doc
printMath (Expr -> D
TeX.pExpr (Ops -> Expr
MO Ops
o))
pExpr (Fenced Fence
l Fence
r Expr
m) = OpenClose -> Fence -> Doc
fence OpenClose
TeX.Open Fence
l Doc -> Doc -> Doc
<> Expr -> Doc
pExpr Expr
m Doc -> Doc -> Doc
<> OpenClose -> Fence -> Doc
fence OpenClose
TeX.Close Fence
r
  where 
    fence :: OpenClose -> Fence -> Doc
fence OpenClose
_ Fence
Abs = String -> Doc
text String
"\\|"
    fence OpenClose
a Fence
b   = D -> Doc
printMath (D -> Doc) -> D -> Doc
forall a b. (a -> b) -> a -> b
$ OpenClose -> Fence -> D
TeX.fence OpenClose
a Fence
b
pExpr (Font Fonts
Bold Expr
e)  = D -> Doc
printMath (D -> Doc) -> D -> Doc
forall a b. (a -> b) -> a -> b
$ String -> D -> D
commandD String
"boldsymbol" (Expr -> D
pExpr' Expr
e)
pExpr (Font Fonts
Emph Expr
e)  = Expr -> Doc
pExpr Expr
e
pExpr (Spc Spacing
Thin)     = String -> Doc
text String
"\\\\,"
pExpr (Sqrt Expr
e)       = D -> Doc
printMath (D -> Doc) -> D -> Doc
forall a b. (a -> b) -> a -> b
$ String -> D -> D
commandD String
"sqrt" (Expr -> D
pExpr' Expr
e)
pExpr Expr
e              = D -> Doc
printMath (D -> Doc) -> D -> Doc
forall a b. (a -> b) -> a -> b
$ Expr -> D
TeX.pExpr Expr
e

-- | Print an expression to a LaTeX D
pExpr' :: Expr -> D
pExpr' :: Expr -> D
pExpr' = Doc -> D
forall a. a -> PrintLaTeX a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Doc -> D) -> (Expr -> Doc) -> Expr -> D
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Expr -> Doc
pExpr

-- | Helper for rendering a D from LaTeX print
printMath :: D -> Doc
printMath :: D -> Doc
printMath = (D -> MathContext -> Doc
forall a. PrintLaTeX a -> MathContext -> a
`runPrint` MathContext
Math) (D -> Doc) -> (D -> D) -> D -> Doc
forall b c a. (b -> c) -> (a -> b) -> a -> c
. D -> D
toMath

-- | LaTeX newline command
lnl :: Doc
lnl :: Doc
lnl = String -> Doc
text String
"\\\\\\\\"

-----------------------------------------------------------------
-------------------- TABLE PRINTING -----------------------------
-----------------------------------------------------------------

-- | Renders Markdown table, called by 'printLO'
makeTable :: RefMap -> [[Spec]] -> Doc -> Bool -> Doc -> Doc
makeTable :: RefMap -> [[Title]] -> Doc -> Bool -> Doc -> Doc
makeTable RefMap
_  [] Doc
_ Bool
_ Doc
_  = String -> Doc
forall a. HasCallStack => String -> a
error String
"No table to print"
makeTable RefMap
rm [[Title]]
ls Doc
r Bool
b Doc
t  = 
  Doc -> Doc
divTag Doc
r Doc -> Doc -> Doc
$^$
  [Doc] -> [Int] -> Doc
makeHeaderCols ([[Doc]] -> [Doc]
forall a. HasCallStack => [a] -> a
head [[Doc]]
matrix) [Int]
sizes Doc -> Doc -> Doc
$$
  [[Doc]] -> [Int] -> Doc
makeRows ([[Doc]] -> [[Doc]]
forall a. HasCallStack => [a] -> [a]
tail [[Doc]]
matrix) [Int]
sizes Doc -> Doc -> Doc
$^$
  Doc
capt
    where
      matrix :: [[Doc]]
matrix = RefMap -> [[Title]] -> [[Doc]]
mkDocMatrix RefMap
rm [[Title]]
ls
      sizes :: [Int]
sizes = [[Doc]] -> [Int]
columnSize [[Doc]]
matrix
      capt :: Doc
capt = if Bool
b then Doc -> Doc
bold (Doc -> Doc
caption Doc
t) else Doc
empty

-- | Helper for creating a Doc matrix
mkDocMatrix :: RefMap -> [[Spec]] -> [[Doc]]
mkDocMatrix :: RefMap -> [[Title]] -> [[Doc]]
mkDocMatrix RefMap
rm = ([Title] -> [Doc]) -> [[Title]] -> [[Doc]]
forall a b. (a -> b) -> [a] -> [b]
map (([Title] -> [Doc]) -> [[Title]] -> [[Doc]])
-> ([Title] -> [Doc]) -> [[Title]] -> [[Doc]]
forall a b. (a -> b) -> a -> b
$ (Title -> Doc) -> [Title] -> [Doc]
forall a b. (a -> b) -> [a] -> [b]
map (RefMap -> Title -> Doc
pSpec RefMap
rm)

-- | Helper for getting table column size
columnSize :: [[Doc]] -> [Int]
columnSize :: [[Doc]] -> [Int]
columnSize = ([Doc] -> Int) -> [[Doc]] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map ([Int] -> Int
forall a. Ord a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
maximum ([Int] -> Int) -> ([Doc] -> [Int]) -> [Doc] -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Doc -> Int) -> [Doc] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map Doc -> Int
docLength) ([[Doc]] -> [Int]) -> ([[Doc]] -> [[Doc]]) -> [[Doc]] -> [Int]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [[Doc]] -> [[Doc]]
forall a. [[a]] -> [[a]]
transpose

-- | Helper for creating table rows
makeRows :: [[Doc]] -> [Int] -> Doc
makeRows :: [[Doc]] -> [Int] -> Doc
makeRows [[Doc]]
lls [Int]
sizes = ([Doc] -> Doc -> Doc) -> Doc -> [[Doc]] -> Doc
forall a b. (a -> b -> b) -> b -> [a] -> b
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr (Doc -> Doc -> Doc
($$) (Doc -> Doc -> Doc) -> ([Doc] -> Doc) -> [Doc] -> Doc -> Doc
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ([Doc] -> [Int] -> Doc
`makeColumns` [Int]
sizes)) Doc
empty [[Doc]]
lls

-- | makeHeaderCols: Helper for creating table header row
-- | makeColumns: Helper for creating table columns
makeHeaderCols, makeColumns :: [Doc] -> [Int] -> Doc
makeHeaderCols :: [Doc] -> [Int] -> Doc
makeHeaderCols [Doc]
l [Int]
sizes = Doc
header Doc -> Doc -> Doc
$$ Doc
seperators
  where header :: Doc
header     = Doc
pipe Doc -> Doc -> Doc
<> [Doc] -> Doc
hcat (Doc -> [Doc] -> [Doc]
punctuate Doc
pipe ((Doc -> Int -> Doc) -> [Doc] -> [Int] -> [Doc]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith Doc -> Int -> Doc
makeCell [Doc]
l [Int]
sizes)) Doc -> Doc -> Doc
<> Doc
pipe        
        seperators :: Doc
seperators = Doc
pipe Doc -> Doc -> Doc
<> [Doc] -> Doc
hcat (Doc -> [Doc] -> [Doc]
punctuate Doc
pipe ((Int -> Doc) -> [Int] -> [Doc]
forall a b. (a -> b) -> [a] -> [b]
map Int -> Doc
makeDashCell [Int]
sizes))   Doc -> Doc -> Doc
<> Doc
pipe

makeColumns :: [Doc] -> [Int] -> Doc
makeColumns [Doc]
ls [Int]
sizes = Doc
pipe Doc -> Doc -> Doc
<> [Doc] -> Doc
hcat (Doc -> [Doc] -> [Doc]
punctuate Doc
pipe ((Doc -> Int -> Doc) -> [Doc] -> [Int] -> [Doc]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith Doc -> Int -> Doc
makeCell [Doc]
ls [Int]
sizes)) Doc -> Doc -> Doc
<> Doc
pipe

-- | Helper for making table seperation row
makeDashCell :: Int -> Doc
makeDashCell :: Int -> Doc
makeDashCell Int
size = String -> Doc
text String
":" Doc -> Doc -> Doc
<> String -> Doc
text (Int -> Char -> String
forall a. Int -> a -> [a]
replicate (Int
size Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1) Char
'-')

-- | Helper for rendering a table cell
makeCell :: Doc -> Int -> Doc
makeCell :: Doc -> Int -> Doc
makeCell Doc
content Int
size = Doc
content Doc -> Doc -> Doc
<> Doc
spaces
  where
    numOfSpaces :: Int
numOfSpaces = Int
size Int -> Int -> Int
forall a. Num a => a -> a -> a
- Doc -> Int
docLength Doc
content
    spaces :: Doc
spaces      = String -> Doc
text (String -> Doc) -> String -> Doc
forall a b. (a -> b) -> a -> b
$ Int -> Char -> String
forall a. Int -> a -> [a]
replicate Int
numOfSpaces Char
' '

-----------------------------------------------------------------
-------------------- DEFINITION PRINTING ------------------------
-----------------------------------------------------------------

-- | Renders definition tables (Data, General, Theory, etc.)
makeDefn :: RefMap -> [(String,[LayoutObj])] -> Doc -> Doc
makeDefn :: RefMap -> [(String, [LayoutObj])] -> Doc -> Doc
makeDefn RefMap
_  [] Doc
_ = String -> Doc
forall a. HasCallStack => String -> a
error String
"L.Empty definition"
makeDefn RefMap
rm [(String, [LayoutObj])]
ps Doc
l = 
  RefMap -> [(String, [LayoutObj])] -> Doc -> Doc
makeDHeaderText RefMap
rm [(String, [LayoutObj])]
ps Doc
l Doc -> Doc -> Doc
$^$ 
  [Doc] -> [Int] -> Doc
makeHeaderCols [String -> Doc
text String
"Refname", Doc
l] [Int]
size Doc -> Doc -> Doc
$$ 
  [[Doc]] -> [Int] -> Doc
makeRows [[Doc]]
docDefn [Int]
size
  where
    docDefn :: [[Doc]]
docDefn = RefMap -> [(String, [LayoutObj])] -> [[Doc]]
mkDocDefn RefMap
rm [(String, [LayoutObj])]
ps
    size :: [Int]
size = [[Doc]] -> [Int]
columnSize [[Doc]]
docDefn

-- | Helper for convering definition to Doc matrix
mkDocDefn :: RefMap -> [(String,[LayoutObj])] -> [[Doc]]
mkDocDefn :: RefMap -> [(String, [LayoutObj])] -> [[Doc]]
mkDocDefn RefMap
rm = ((String, [LayoutObj]) -> [Doc])
-> [(String, [LayoutObj])] -> [[Doc]]
forall a b. (a -> b) -> [a] -> [b]
map (\(String
f, [LayoutObj]
d) -> [String -> Doc
text String
f, RefMap -> (String, [LayoutObj]) -> Doc
makeLO RefMap
rm (String
f,[LayoutObj]
d)])

-- | Renders the title/header of the definition table
makeDHeaderText :: RefMap -> [(String, [LayoutObj])] -> Doc -> Doc
makeDHeaderText :: RefMap -> [(String, [LayoutObj])] -> Doc -> Doc
makeDHeaderText RefMap
rm [(String, [LayoutObj])]
ps Doc
l = Doc -> Doc
centeredDiv Doc
header
  where
    lo :: Maybe [LayoutObj]
lo = String -> [(String, [LayoutObj])] -> Maybe [LayoutObj]
forall a b. Eq a => a -> [(a, b)] -> Maybe b
lookup String
"Label" [(String, [LayoutObj])]
ps
    c :: Doc
c = Doc -> ([LayoutObj] -> Doc) -> Maybe [LayoutObj] -> Doc
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Doc
l (\[LayoutObj]
lo' -> RefMap -> (String, [LayoutObj]) -> Doc
makeLO RefMap
rm (String
"Label", [LayoutObj]
lo')) Maybe [LayoutObj]
lo 
    header :: Doc
header = Int -> Doc
h' Int
2 Doc -> Doc -> Doc
<+> Doc -> Doc -> Doc
heading Doc
c Doc
l

-- | Converts the [LayoutObj] to a Doc
makeLO :: RefMap -> (String, [LayoutObj]) -> Doc
makeLO :: RefMap -> (String, [LayoutObj]) -> Doc
makeLO RefMap
rm (String
f,[LayoutObj]
d) =
      if String
fString -> String -> Bool
forall a. Eq a => a -> a -> Bool
==String
"Notes" then Doc -> Doc
ul ([Doc] -> Doc
hcat ([Doc] -> Doc) -> [Doc] -> Doc
forall a b. (a -> b) -> a -> b
$ (LayoutObj -> Doc) -> [LayoutObj] -> [Doc]
forall a b. (a -> b) -> [a] -> [b]
map (RefMap -> String -> LayoutObj -> Doc
processDefnLO RefMap
rm String
f) [LayoutObj]
d) 
      else [Doc] -> Doc
hcat ([Doc] -> Doc) -> [Doc] -> Doc
forall a b. (a -> b) -> a -> b
$ (LayoutObj -> Doc) -> [LayoutObj] -> [Doc]
forall a b. (a -> b) -> [a] -> [b]
map (RefMap -> String -> LayoutObj -> Doc
processDefnLO RefMap
rm String
f) [LayoutObj]
d

-- | Processes the LayoutObjs in the defn
processDefnLO :: RefMap -> String -> LayoutObj -> Doc
processDefnLO :: RefMap -> String -> LayoutObj -> Doc
processDefnLO RefMap
rm String
"Notes" (Paragraph Title
con) = Doc -> Doc
li (Doc -> Doc) -> Doc -> Doc
forall a b. (a -> b) -> a -> b
$ RefMap -> Title -> Doc
pSpec RefMap
rm Title
con
processDefnLO RefMap
rm String
_       LayoutObj
lo              = RefMap -> LayoutObj -> Doc
printLO RefMap
rm LayoutObj
lo

-----------------------------------------------------------------
----------------------- LIST PRINTING ---------------------------
-----------------------------------------------------------------

-- | Renders lists into Markdown
makeList :: RefMap -> ListType -> Int -> Doc
makeList :: RefMap -> ListType -> Int -> Doc
makeList RefMap
rm (Simple      [(Title, ItemType, Maybe Title)]
items) Int
_  = [Doc] -> Doc
vsep ([Doc] -> Doc) -> [Doc] -> Doc
forall a b. (a -> b) -> a -> b
$ ((Title, ItemType, Maybe Title) -> Doc)
-> [(Title, ItemType, Maybe Title)] -> [Doc]
forall a b. (a -> b) -> [a] -> [b]
map (RefMap -> (Title, ItemType, Maybe Title) -> Doc
sItem RefMap
rm) [(Title, ItemType, Maybe Title)]
items
makeList RefMap
rm (Desc        [(Title, ItemType, Maybe Title)]
items) Int
_  = [Doc] -> Doc
vsep ([Doc] -> Doc) -> [Doc] -> Doc
forall a b. (a -> b) -> a -> b
$ ((Title, ItemType, Maybe Title) -> Doc)
-> [(Title, ItemType, Maybe Title)] -> [Doc]
forall a b. (a -> b) -> [a] -> [b]
map (RefMap -> (Title, ItemType, Maybe Title) -> Doc
descItem RefMap
rm) [(Title, ItemType, Maybe Title)]
items
makeList RefMap
rm (Ordered     [(ItemType, Maybe Title)]
items) Int
bl = [Doc] -> Doc
vcat ([Doc] -> Doc) -> [Doc] -> Doc
forall a b. (a -> b) -> a -> b
$ 
  ((ItemType, Maybe Title) -> Int -> Doc)
-> [(ItemType, Maybe Title)] -> [Int] -> [Doc]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith (\(ItemType
i,Maybe Title
_) Int
n -> RefMap -> ItemType -> Int -> Int -> Doc
oItem RefMap
rm ItemType
i Int
bl Int
n) [(ItemType, Maybe Title)]
items [Int
1..]
makeList RefMap
rm (Unordered   [(ItemType, Maybe Title)]
items) Int
bl = [Doc] -> Doc
vcat ([Doc] -> Doc) -> [Doc] -> Doc
forall a b. (a -> b) -> a -> b
$ 
  ((ItemType, Maybe Title) -> Doc)
-> [(ItemType, Maybe Title)] -> [Doc]
forall a b. (a -> b) -> [a] -> [b]
map (\(ItemType
i,Maybe Title
_) -> RefMap -> ItemType -> Int -> Doc
uItem RefMap
rm ItemType
i Int
bl) [(ItemType, Maybe Title)]
items
makeList RefMap
rm (Definitions [(Title, ItemType, Maybe Title)]
items) Int
_  = Doc -> Doc
ul (Doc -> Doc) -> Doc -> Doc
forall a b. (a -> b) -> a -> b
$ [Doc] -> Doc
hcat ([Doc] -> Doc) -> [Doc] -> Doc
forall a b. (a -> b) -> a -> b
$ 
  ((Title, ItemType, Maybe Title) -> Doc)
-> [(Title, ItemType, Maybe Title)] -> [Doc]
forall a b. (a -> b) -> [a] -> [b]
map (\(Title
b,ItemType
e,Maybe Title
_) -> Doc -> Doc
li (Doc -> Doc) -> Doc -> Doc
forall a b. (a -> b) -> a -> b
$ RefMap -> Title -> Doc
pSpec RefMap
rm Title
b Doc -> Doc -> Doc
<> String -> Doc
text String
" is the" Doc -> Doc -> Doc
<+> RefMap -> ItemType -> Doc
item RefMap
rm ItemType
e) [(Title, ItemType, Maybe Title)]
items

-- | Helper for setting up reference anchors
mlref :: RefMap -> Maybe Label -> Doc -> Doc
mlref :: RefMap -> Maybe Title -> Doc -> Doc
mlref RefMap
_ Maybe Title
Nothing = (Doc
empty Doc -> Doc -> Doc
$$)
mlref RefMap
rm (Just Title
l) = (Doc -> Doc
divTag (RefMap -> Title -> Doc
pSpec RefMap
rm Title
l) Doc -> Doc -> Doc
$^$)

-- | Helper for rendering unordered list items
uItem :: RefMap -> ItemType -> Int -> Doc
uItem :: RefMap -> ItemType -> Int -> Doc
uItem RefMap
rm (Flat   Title
s)   Int
i = String -> Doc
text (Int -> Char -> String
forall a. Int -> a -> [a]
replicate Int
i Char
' ') 
  Doc -> Doc -> Doc
<> Doc
hyph Doc -> Doc -> Doc
<+> RefMap -> Title -> Doc
pSpec RefMap
rm Title
s
uItem RefMap
rm (Nested Title
s ListType
l) Int
i = [Doc] -> Doc
vcat [
  String -> Doc
text (Int -> Char -> String
forall a. Int -> a -> [a]
replicate Int
i Char
' ') Doc -> Doc -> Doc
<> Doc
hyph Doc -> Doc -> Doc
<+> RefMap -> Title -> Doc
pSpec RefMap
rm Title
s, 
  RefMap -> ListType -> Int -> Doc
makeList RefMap
rm ListType
l (Int
iInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
2)
  ]

-- | Helper for rendering ordered list items
oItem :: RefMap -> ItemType -> Int -> Int -> Doc
oItem :: RefMap -> ItemType -> Int -> Int -> Doc
oItem RefMap
rm (Flat   Title
s)   Int
i Int
n = String -> Doc
text (Int -> Char -> String
forall a. Int -> a -> [a]
replicate Int
i Char
' ') 
  Doc -> Doc -> Doc
<> Doc -> Doc
dot (String -> Doc
text (String -> Doc) -> String -> Doc
forall a b. (a -> b) -> a -> b
$ Int -> String
forall a. Show a => a -> String
show Int
n) Doc -> Doc -> Doc
<+> RefMap -> Title -> Doc
pSpec RefMap
rm Title
s
oItem RefMap
rm (Nested Title
s ListType
l) Int
i Int
n = [Doc] -> Doc
vcat [
  String -> Doc
text (Int -> Char -> String
forall a. Int -> a -> [a]
replicate Int
i Char
' ') Doc -> Doc -> Doc
<> Doc -> Doc
dot (String -> Doc
text (String -> Doc) -> String -> Doc
forall a b. (a -> b) -> a -> b
$ Int -> String
forall a. Show a => a -> String
show Int
n) Doc -> Doc -> Doc
<+> RefMap -> Title -> Doc
pSpec RefMap
rm Title
s, 
  RefMap -> ListType -> Int -> Doc
makeList RefMap
rm ListType
l (Int
iInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
3)
  ]

-- | Helper for Desc list items
descItem :: RefMap -> (Spec, ItemType, Maybe Label) -> Doc
descItem :: RefMap -> (Title, ItemType, Maybe Title) -> Doc
descItem RefMap
rm (Title
b,ItemType
e,Maybe Title
l) = RefMap -> Maybe Title -> Doc -> Doc
mlref RefMap
rm Maybe Title
l (Doc -> Doc
bold (RefMap -> Title -> Doc
pSpec RefMap
rm Title
b) Doc -> Doc -> Doc
<> String -> Doc
text String
":" Doc -> Doc -> Doc
<+> RefMap -> ItemType -> Doc
item RefMap
rm ItemType
e)

-- | Helper for Simple list items
sItem :: RefMap -> (Spec, ItemType, Maybe Label) -> Doc
sItem :: RefMap -> (Title, ItemType, Maybe Title) -> Doc
sItem RefMap
rm (Title
b,ItemType
e,Maybe Title
l) = RefMap -> Maybe Title -> Doc -> Doc
mlref RefMap
rm Maybe Title
l (RefMap -> Title -> Doc
pSpec RefMap
rm Title
b Doc -> Doc -> Doc
<> String -> Doc
text String
":" Doc -> Doc -> Doc
<+> RefMap -> ItemType -> Doc
item RefMap
rm ItemType
e)

-- | Helper for Markdown list items
item :: RefMap -> ItemType -> Doc
item :: RefMap -> ItemType -> Doc
item RefMap
rm (Flat   Title
s)   = RefMap -> Title -> Doc
pSpec RefMap
rm Title
s
item RefMap
rm (Nested Title
s ListType
l) = [Doc] -> Doc
vcat [RefMap -> Title -> Doc
pSpec RefMap
rm Title
s, RefMap -> ListType -> Int -> Doc
makeList RefMap
rm ListType
l Int
0]

-----------------------------------------------------------------
---------------------- FIGURE PRINTING --------------------------
-----------------------------------------------------------------

-- | Renders figures in Markdown
makeFigure :: Doc -> Maybe Doc -> Doc -> Doc
makeFigure :: Doc -> Maybe Doc -> Doc -> Doc
makeFigure Doc
r Maybe Doc
c Doc
f = Doc -> Doc -> Doc
centeredDivId Doc
r (Doc -> Maybe Doc -> Doc
image Doc
f Maybe Doc
c)

-----------------------------------------------------------------
------------------ Bibliography Printing ------------------------
-----------------------------------------------------------------

-- | Markdown specific bib rendering functions
mdBibFormatter :: RefMap -> BibFormatter
mdBibFormatter :: RefMap -> BibFormatter
mdBibFormatter RefMap
rm = BibFormatter {
  emph :: Doc -> Doc
emph = Doc -> Doc
em,
  spec :: Title -> Doc
spec = RefMap -> Title -> Doc
pSpec RefMap
rm
}

-- | Renders the reference list
makeRefList :: Doc -> Doc -> Doc -> Doc
makeRefList :: Doc -> Doc -> Doc -> Doc
makeRefList Doc
a Doc
l Doc
i = Doc -> Doc
divTag Doc
l Doc -> Doc -> Doc
$^$ (Doc
i Doc -> Doc -> Doc
<> String -> Doc
text String
": " Doc -> Doc -> Doc
<> Doc
a)

-- | Renders the bibliography
makeBib :: RefMap -> BibRef -> Doc
makeBib :: RefMap -> BibRef -> Doc
makeBib RefMap
rm = [Doc] -> Doc
vsep ([Doc] -> Doc) -> (BibRef -> [Doc]) -> BibRef -> Doc
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
  (Doc -> (Doc, Doc) -> Doc) -> [Doc] -> [(Doc, Doc)] -> [Doc]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith (((Doc, (Doc, Doc)) -> Doc) -> Doc -> (Doc, Doc) -> Doc
forall a b c. ((a, b) -> c) -> a -> b -> c
curry (\(Doc
x,(Doc
y,Doc
z)) -> Doc -> Doc -> Doc -> Doc
makeRefList Doc
z Doc
y Doc
x))
  [String -> Doc
text (String -> Doc) -> String -> Doc
forall a b. (a -> b) -> a -> b
$ String -> String
sqbrac (String -> String) -> String -> String
forall a b. (a -> b) -> a -> b
$ Int -> String
forall a. Show a => a -> String
show Int
x | Int
x <- [Int
1..] :: [Int]] ([(Doc, Doc)] -> [Doc])
-> (BibRef -> [(Doc, Doc)]) -> BibRef -> [Doc]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Citation -> (Doc, Doc)) -> BibRef -> [(Doc, Doc)]
forall a b. (a -> b) -> [a] -> [b]
map (BibFormatter -> Citation -> (Doc, Doc)
HTML.renderCite (RefMap -> BibFormatter
mdBibFormatter RefMap
rm))