-- | Defines all functions needed to print HTML files. For more information on each of the helper functions, please view the [source files](https://jacquescarette.github.io/Drasil/docs/full/drasil-printers-0.1.10.0/src/Language.Drasil.HTML.Print.html).
module Language.Drasil.HTML.Print(
  -- * Main Function
  genHTML,
  -- * Citation Renderer
  renderCite,
  -- * HTML Bib Formatter
  htmlBibFormatter,
  -- * HTML Spec Printing
  pSpec,
  -- * Term Fencing Helpers
  OpenClose(Open, Close), 
  fence) where

import Prelude hiding (print, (<>))
import Data.List (sortBy)
import Text.PrettyPrint hiding (Str)
import Numeric (showEFloat)

import qualified Language.Drasil as L

import Language.Drasil.HTML.Monad (unPH)
import Language.Drasil.HTML.Helpers (articleTitle, author, ba, body, bold,
  caption, divTag, em, h, headTag, html, image, li, ol, pa,
  paragraph, reflink, reflinkInfo, reflinkURI, refwrap, sub, sup, table, td,
  th, title, tr, ul, BibFormatter(..))
import Language.Drasil.HTML.CSS (linkCSS)

import Language.Drasil.Config (StyleGuide(APA, MLA, Chicago), bibStyleH)
import Language.Drasil.Printing.Import (makeDocument)
import Language.Drasil.Printing.AST (Spec, ItemType(Flat, Nested),  
  ListType(Ordered, Unordered, Definitions, Desc, Simple), Expr, Fence(Curly, Paren, Abs, Norm),
  Ops(..), Expr(..), Spec(Quote, EmptyS, Ref, HARDNL, Sp, S, E, (:+:)),
  Spacing(Thin), Fonts(Bold, Emph), OverSymb(Hat), Label,
  LinkType(Internal, Cite2, External))
import Language.Drasil.Printing.Citation (CiteField(Year, Number, Volume, Title, Author, 
  Editor, Pages, Type, Month, Organization, Institution, Chapter, HowPublished, School, Note,
  Journal, BookTitle, Publisher, Series, Address, Edition), HP(URL, Verb), 
  Citation(Cite), BibRef)
import Language.Drasil.Printing.LayoutObj (Document(Document), LayoutObj(..), Tags)
import Language.Drasil.Printing.Helpers (comm, dot, paren, sufxer, sqbrac, sufxPrint)
import Language.Drasil.Printing.PrintingInformation (PrintingInformation)

import qualified Language.Drasil.TeX.Print as TeX (pExpr, spec)
import Language.Drasil.TeX.Monad (runPrint, MathContext(Math), D, toMath, PrintLaTeX(PL))

-- | Referring to 'fence' (for parenthesis and brackeds). Either opened or closed.
data OpenClose = Open | Close

-- | Generate an HTML document from a Drasil 'Document'.
genHTML :: PrintingInformation -> String -> L.Document -> Doc
genHTML :: PrintingInformation -> String -> Document -> Doc
genHTML PrintingInformation
sm String
fn Document
doc = String -> Document -> Doc
build String
fn (PrintingInformation -> Document -> Document
makeDocument PrintingInformation
sm Document
doc)
--         ^^ -- should really be of type Filename, but that's not in scope

-- TODO: Use our JSON printer here to create this code snippet.
-- | Variable to include MathJax in our HTML files so we can render equations in LaTeX.
mathJaxScript :: Doc
mathJaxScript :: Doc
mathJaxScript =
  [Doc] -> Doc
vcat [String -> Doc
text String
"<script>",
        String -> Doc
text String
"MathJax = {",
        String -> Doc
text String
"  loader: {load: ['[tex]/textmacros', 'output/chtml']},",
        String -> Doc
text String
"  tex: {",
        String -> Doc
text String
"    packages: {'[+]': ['textmacros']}",
        String -> Doc
text String
"  },",
        String -> Doc
text String
"  svg: {",
        String -> Doc
text String
"    fontCache: 'global'",
        String -> Doc
text String
"  }",
        String -> Doc
text String
"};",
        String -> Doc
text String
"</script>",
        String -> Doc
text String
"<script type=\"text/javascript\" id=\"MathJax-script\" async",
        String -> Doc
text String
" src=\"https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-chtml-full.js\">",
        String -> Doc
text String
"</script>"]

-- HTML printer doesn't need to know if there is a table of contents or not.
-- | Build the HTML Document, called by 'genHTML'.
build :: String -> Document -> Doc
build :: String -> Document -> Doc
build String
fn (Document Title
t Title
a [LayoutObj]
c) =
  String -> Doc
text String
"<!DOCTYPE html>" Doc -> Doc -> Doc
$$
  Doc -> Doc
html (Doc -> Doc
headTag (String -> Doc
linkCSS String
fn Doc -> Doc -> Doc
$$ Doc -> Doc
title (Title -> Doc
titleSpec Title
t) Doc -> Doc -> Doc
$$
  String -> Doc
text String
"<meta charset=\"utf-8\">" Doc -> Doc -> Doc
$$
  Doc
mathJaxScript) Doc -> Doc -> Doc
$$
  Doc -> Doc
body (Doc -> Doc
articleTitle (Title -> Doc
pSpec Title
t) Doc -> Doc -> Doc
$$ Doc -> Doc
author (Title -> Doc
pSpec Title
a)
  Doc -> Doc -> Doc
$$ [LayoutObj] -> Doc
print [LayoutObj]
c
  ))

-- | 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)

-- | Helper for rendering layout objects ('LayoutObj's) into HTML.
printLO :: LayoutObj -> Doc
-- FIXME: could be hacky
printLO :: LayoutObj -> Doc
printLO (HDiv [String
"equation"] [LayoutObj]
layoutObs Title
EmptyS)  = [Doc] -> Doc
vcat ((LayoutObj -> Doc) -> [LayoutObj] -> [Doc]
forall a b. (a -> b) -> [a] -> [b]
map LayoutObj -> Doc
printLO [LayoutObj]
layoutObs)
-- Creates delimeters to be used for mathjax displayed equations
-- Latex print sets up a \begin{displaymath} environment instead of this
printLO (EqnBlock Title
contents)    = Doc -> Doc
mjDelimDisp (Doc -> Doc) -> Doc -> Doc
forall a b. (a -> b) -> a -> b
$ D -> Doc
printMath (D -> Doc) -> D -> Doc
forall a b. (a -> b) -> a -> b
$ D -> D
forall {a}. PrintLaTeX a -> PrintLaTeX a
toMathHelper (D -> D) -> D -> D
forall a b. (a -> b) -> a -> b
$ Title -> D
TeX.spec Title
contents
  where
    toMathHelper :: PrintLaTeX a -> PrintLaTeX a
toMathHelper (PL MathContext -> a
g) = (MathContext -> a) -> PrintLaTeX a
forall a. (MathContext -> a) -> PrintLaTeX a
PL (\MathContext
_ -> MathContext -> a
g MathContext
Math)
    mjDelimDisp :: Doc -> Doc
mjDelimDisp Doc
d = String -> Doc
text String
"\\[" Doc -> Doc -> Doc
<> Doc
d Doc -> Doc -> Doc
<> String -> Doc
text String
"\\]"
-- Non-mathjax
-- printLO (EqnBlock contents) = pSpec contents
printLO (HDiv [String]
ts [LayoutObj]
layoutObs Title
EmptyS)  = [String] -> Doc -> Doc
divTag [String]
ts ([Doc] -> Doc
vcat ((LayoutObj -> Doc) -> [LayoutObj] -> [Doc]
forall a b. (a -> b) -> [a] -> [b]
map LayoutObj -> Doc
printLO [LayoutObj]
layoutObs))
printLO (HDiv [String]
ts [LayoutObj]
layoutObs Title
l)  = Doc -> Doc -> Doc
refwrap (Title -> Doc
pSpec Title
l) (Doc -> Doc) -> Doc -> Doc
forall a b. (a -> b) -> a -> b
$
                                 [String] -> Doc -> Doc
divTag [String]
ts ([Doc] -> Doc
vcat ((LayoutObj -> Doc) -> [LayoutObj] -> [Doc]
forall a b. (a -> b) -> [a] -> [b]
map LayoutObj -> Doc
printLO [LayoutObj]
layoutObs))
printLO (Paragraph Title
contents)   = Doc -> Doc
paragraph (Doc -> Doc) -> Doc -> Doc
forall a b. (a -> b) -> a -> b
$ Title -> Doc
pSpec Title
contents
printLO (Table [String]
ts [[Title]]
rows Title
r Bool
b Title
t)  = [String] -> [[Title]] -> Doc -> Bool -> Doc -> Doc
makeTable [String]
ts [[Title]]
rows (Title -> Doc
pSpec Title
r) Bool
b (Title -> Doc
pSpec Title
t)
printLO (Definition DType
dt [(String, [LayoutObj])]
ssPs Title
l) = DType -> [(String, [LayoutObj])] -> Doc -> Doc
makeDefn DType
dt [(String, [LayoutObj])]
ssPs (Title -> Doc
pSpec Title
l)
printLO (Header Int
n Title
contents Title
_)  = Int -> Doc -> Doc
h (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1) (Doc -> Doc) -> Doc -> Doc
forall a b. (a -> b) -> a -> b
$ Title -> Doc
pSpec Title
contents -- FIXME
printLO (List ListType
t)               = ListType -> Doc
makeList ListType
t
printLO (Figure Title
r Maybe Title
c String
f MaxWidthPercent
wp)      = Doc -> Maybe Doc -> Doc -> MaxWidthPercent -> Doc
makeFigure (Title -> Doc
pSpec 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 Title -> Doc
pSpec Maybe Title
c) (String -> Doc
text String
f) MaxWidthPercent
wp
printLO (Bib BibRef
bib)              = BibRef -> Doc
makeBib BibRef
bib
printLO Graph{}                = Doc
empty -- FIXME
printLO Cell{}                 = Doc
empty
printLO CodeBlock{}            = Doc
empty


-- | Called by build, uses 'printLO' to render the layout
-- objects in 'Doc' format.
print :: [LayoutObj] -> Doc
print :: [LayoutObj] -> Doc
print = (LayoutObj -> Doc -> Doc) -> Doc -> [LayoutObj] -> 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)
-> (LayoutObj -> Doc) -> LayoutObj -> Doc -> Doc
forall b c a. (b -> c) -> (a -> b) -> a -> c
. LayoutObj -> Doc
printLO) Doc
empty

-----------------------------------------------------------------
--------------------BEGIN SPEC PRINTING--------------------------
-----------------------------------------------------------------
-- | Renders the title of the document. Different than body rendering
-- because newline can't be rendered in an HTML title.
titleSpec :: Spec -> Doc
titleSpec :: Title -> Doc
titleSpec (Title
a :+: Title
b) = Title -> Doc
titleSpec Title
a Doc -> Doc -> Doc
<> Title -> Doc
titleSpec Title
b
titleSpec Title
HARDNL    = Doc
empty
titleSpec Title
s         = Title -> Doc
pSpec Title
s

-- | Renders the Sentences ('Spec's) in the HTML body (called by 'printLO').
pSpec :: Spec -> Doc
-- Non-mathjax
pSpec :: Title -> Doc
pSpec (E Expr
e)  = Doc -> Doc
em (Doc -> Doc) -> Doc -> Doc
forall a b. (a -> b) -> a -> b
$ Expr -> Doc
pExpr Expr
e
-- Latex based math for expressions and units
-- pSpec (E e)     = printMath $ toMath $ TeX.pExpr e
-- pSpec (Sy s)    = printMath $ TeX.pUnit s
pSpec (Title
a :+: Title
b) = Title -> Doc
pSpec Title
a Doc -> Doc -> Doc
<> Title -> Doc
pSpec Title
b
pSpec (S String
s)     = (String -> Doc) -> (String -> Doc) -> Either String String -> Doc
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either String -> Doc
forall a. HasCallStack => String -> a
error (String -> Doc
text (String -> Doc) -> (String -> String) -> String -> Doc
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Char -> String) -> String -> String
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap Char -> String
escapeChars) (Either String String -> Doc) -> Either String String -> Doc
forall a b. (a -> b) -> a -> b
$ String -> String -> Either String String
L.checkValidStr String
s String
invalid
  where
    invalid :: String
invalid = [Char
'<', Char
'>']
    escapeChars :: Char -> String
escapeChars Char
'&' = String
"\\&"
    escapeChars Char
c = [Char
c]
pSpec (Sp Special
s)    = String -> Doc
text (String -> Doc) -> String -> Doc
forall a b. (a -> b) -> a -> b
$ PrintHTML -> String
unPH (PrintHTML -> String) -> PrintHTML -> String
forall a b. (a -> b) -> a -> b
$ Special -> PrintHTML
forall r. RenderSpecial r => Special -> r
L.special Special
s
pSpec Title
HARDNL    = String -> Doc
text String
"<br />"
pSpec (Ref LinkType
Internal String
r Title
a)       = String -> Doc -> Doc
reflink     String
r (Doc -> Doc) -> Doc -> Doc
forall a b. (a -> b) -> a -> b
$ Title -> Doc
pSpec Title
a
pSpec (Ref (Cite2 Title
EmptyS) String
r Title
a) = String -> Doc -> Doc
reflink     String
r (Doc -> Doc) -> Doc -> Doc
forall a b. (a -> b) -> a -> b
$ Title -> Doc
pSpec Title
a -- no difference for citations?
pSpec (Ref (Cite2 Title
n)   String
r Title
a)    = String -> Doc -> Doc -> Doc
reflinkInfo String
r (Title -> Doc
pSpec Title
a) (Title -> Doc
pSpec Title
n) -- no difference for citations?
pSpec (Ref LinkType
External String
r Title
a)       = String -> Doc -> Doc
reflinkURI  String
r (Doc -> Doc) -> Doc -> Doc
forall a b. (a -> b) -> a -> b
$ Title -> Doc
pSpec Title
a
pSpec Title
EmptyS    = String -> Doc
text String
"" -- Expected in the output
pSpec (Quote Title
q) = Doc -> Doc
doubleQuotes (Doc -> Doc) -> Doc -> Doc
forall a b. (a -> b) -> a -> b
$ Title -> Doc
pSpec Title
q
--pSpec (Acc Grave c) = text $ '&' : c : "grave;" --Only works on vowels.
--pSpec (Acc Acute c) = text $ '&' : c : "acute;" --Only works on vowels.


-----------------------------------------------------------------
------------------BEGIN EXPRESSION PRINTING----------------------
-----------------------------------------------------------------


-- | Renders expressions in the HTML document (called by multiple functions).
pExpr :: Expr -> Doc
pExpr :: Expr -> Doc
pExpr (Dbl Double
d)        = String -> Doc
text (String -> Doc) -> String -> Doc
forall a b. (a -> b) -> a -> b
$ Maybe Int -> Double -> String -> String
forall a. RealFloat a => Maybe Int -> a -> String -> String
showEFloat Maybe Int
forall a. Maybe a
Nothing Double
d String
""
pExpr (Int Integer
i)        = String -> Doc
text (String -> Doc) -> String -> Doc
forall a b. (a -> b) -> a -> b
$ Integer -> String
forall a. Show a => a -> String
show Integer
i
pExpr (Str String
s)        = Doc -> Doc
doubleQuotes (Doc -> Doc) -> Doc -> Doc
forall a b. (a -> b) -> a -> b
$ String -> Doc
text String
s
pExpr (Row [Expr]
l)        = [Doc] -> Doc
hcat ([Doc] -> Doc) -> [Doc] -> Doc
forall a b. (a -> b) -> a -> b
$ (Expr -> Doc) -> [Expr] -> [Doc]
forall a b. (a -> b) -> [a] -> [b]
map Expr -> Doc
pExpr [Expr]
l
pExpr (Ident String
s)      = String -> Doc
text String
s
pExpr (Label String
s)      = String -> Doc
text String
s
pExpr (Spec Special
s)       = String -> Doc
text (String -> Doc) -> String -> Doc
forall a b. (a -> b) -> a -> b
$ PrintHTML -> String
unPH (PrintHTML -> String) -> PrintHTML -> String
forall a b. (a -> b) -> a -> b
$ Special -> PrintHTML
forall r. RenderSpecial r => Special -> r
L.special Special
s
--pExpr (Gr g)         = unPH $ greek g
pExpr (Sub Expr
e)        = Doc -> Doc
sub (Doc -> Doc) -> Doc -> Doc
forall a b. (a -> b) -> a -> b
$ Expr -> Doc
pExpr Expr
e
pExpr (Sup Expr
e)        = Doc -> Doc
sup (Doc -> Doc) -> Doc -> Doc
forall a b. (a -> b) -> a -> b
$ Expr -> Doc
pExpr Expr
e
pExpr (Over OverSymb
Hat Expr
s)   = Expr -> Doc
pExpr Expr
s Doc -> Doc -> Doc
<> String -> Doc
text String
"&#770;"
pExpr (MO Ops
o)         = String -> Doc
text (String -> Doc) -> String -> Doc
forall a b. (a -> b) -> a -> b
$ Ops -> String
pOps Ops
o
pExpr (Fenced Fence
l Fence
r Expr
e) = String -> Doc
text (OpenClose -> Fence -> String
fence OpenClose
Open Fence
l) Doc -> Doc -> Doc
<> Expr -> Doc
pExpr Expr
e Doc -> Doc -> Doc
<> String -> Doc
text (OpenClose -> Fence -> String
fence OpenClose
Close Fence
r)
pExpr (Font Fonts
Bold Expr
e)  = Doc -> Doc
bold (Doc -> Doc) -> Doc -> Doc
forall a b. (a -> b) -> a -> b
$ Expr -> Doc
pExpr Expr
e
pExpr (Font Fonts
Emph Expr
e)  = String -> Doc
text String
"<em>" Doc -> Doc -> Doc
<> Expr -> Doc
pExpr Expr
e Doc -> Doc -> Doc
<> String -> Doc
text String
"</em>" -- FIXME
pExpr (Spc Spacing
Thin)     = String -> Doc
text String
"&#8239;"
-- Uses TeX for Mathjax for all other exprs
pExpr Expr
e              = Doc -> Doc
mjDelimDisp (Doc -> Doc) -> Doc -> Doc
forall a b. (a -> b) -> a -> b
$ D -> Doc
printMath (D -> Doc) -> D -> Doc
forall a b. (a -> b) -> a -> b
$ D -> D
toMath (D -> D) -> D -> D
forall a b. (a -> b) -> a -> b
$ Expr -> D
TeX.pExpr Expr
e
  where mjDelimDisp :: Doc -> Doc
mjDelimDisp Doc
d = String -> Doc
text String
"\\(" Doc -> Doc -> Doc
<> Doc
d Doc -> Doc -> Doc
<> String -> Doc
text String
"\\)"
-- Non-mathjax
{-
pExpr (Sqrt e)       = text "&radic;(" <> pExpr e <> text ")"
pExpr (Div a b)      = fraction (pExpr a) (pExpr b)
pExpr (Case ps)      = cases ps pExpr
pExpr (Mtx a)        = text "<table class=\"matrix\">\n" <> pMatrix a <> text "</table>"
-}

-- | Converts expression operators into HTML characters.
pOps :: Ops -> String
pOps :: Ops -> String
pOps Ops
IsIn       = String
"&thinsp;&isin;&thinsp;"
pOps Ops
Integer    = String
"&#8484;"
pOps Ops
Rational   = String
"&#8474;"
pOps Ops
Real       = String
"&#8477;"
pOps Ops
Natural    = String
"&#8469;"
pOps Ops
Boolean    = String
"&#120121;"
pOps Ops
Comma      = String
","
pOps Ops
Prime      = String
"&prime;"
pOps Ops
Log        = String
"log"
pOps Ops
Ln         = String
"ln"
pOps Ops
Sin        = String
"sin"
pOps Ops
Cos        = String
"cos"
pOps Ops
Tan        = String
"tan"
pOps Ops
Sec        = String
"sec"
pOps Ops
Csc        = String
"csc"
pOps Ops
Cot        = String
"cot"
pOps Ops
Arcsin     = String
"arcsin"
pOps Ops
Arccos     = String
"arccos"
pOps Ops
Arctan     = String
"arctan"
pOps Ops
Not        = String
"&not;"
pOps Ops
Dim        = String
"dim"
pOps Ops
Exp        = String
"e"
pOps Ops
Neg        = String
"&minus;"
pOps Ops
Cross      = String
"&#10799;"
pOps Ops
VAdd       = String
"&plus;"
pOps Ops
VSub       = String
"&minus;"
pOps Ops
Dot        = String
"&sdot;"
pOps Ops
Scale      = String
"&#8239;" -- same as Mul
pOps Ops
Eq         = String
" = " -- with spaces?
pOps Ops
NEq        = String
"&ne;"
pOps Ops
Lt         = String
"&thinsp;&lt;&thinsp;" --thin spaces make these more readable
pOps Ops
Gt         = String
"&thinsp;&gt;&thinsp;"
pOps Ops
LEq        = String
"&thinsp;&le;&thinsp;"
pOps Ops
GEq        = String
"&thinsp;&ge;&thinsp;"
pOps Ops
Impl       = String
" &rArr; "
pOps Ops
Iff        = String
" &hArr; "
pOps Ops
Subt       = String
"&minus;"
pOps Ops
And        = String
" &and; "
pOps Ops
Or         = String
" &or; "
pOps Ops
Add        = String
"&plus;"
pOps Ops
Mul        = String
"&#8239;"
pOps Ops
Summ       = String
"&sum;"
pOps Ops
Inte       = String
"&int;"
pOps Ops
Prod       = String
"&prod;"
pOps Ops
Point      = String
"."
pOps Ops
Perc       = String
"%"
pOps Ops
LArrow     = String
" &larr; "
pOps Ops
RArrow     = String
" &rarr; "
pOps Ops
ForAll     = String
" &forall; "
pOps Ops
Partial    = String
"&part;"
pOps Ops
SAdd       = String
" + "
pOps Ops
SRemove    = String
" - "
pOps Ops
SContains  = String
" in "
pOps Ops
SUnion     = String
" and "

-- | Allows for open/closed variants of parenthesis, curly brackets, absolute value symbols, and normal symbols.
fence :: OpenClose -> Fence -> String
fence :: OpenClose -> Fence -> String
fence OpenClose
Open  Fence
Paren = String
"("
fence OpenClose
Close Fence
Paren = String
")"
fence OpenClose
Open  Fence
Curly = String
"{"
fence OpenClose
Close Fence
Curly = String
"}"
fence OpenClose
_     Fence
Abs   = String
"|"
fence OpenClose
_     Fence
Norm  = String
"||"

-- Not used since we use MathJax handles this
-- pMatrix :: [[Expr]] -> Doc
-- pMatrix [] = text ""
-- pMatrix [x] = text "<tr>" <> pIn x <> text "</tr>\n"
-- pMatrix (x:xs) = pMatrix [x] <> pMatrix xs

-- Not used since we use MathJax handles this
-- pIn :: [Expr] -> Doc
-- pIn [] = text ""
-- pIn [x] = text "<td>" <> pExpr x <> text "</td>"
-- pIn (x:xs) = pIn [x] <> pIn xs

-----------------------------------------------------------------
------------------BEGIN TABLE PRINTING---------------------------
-----------------------------------------------------------------

-- | Renders an HTML table, called by 'printLO'.
makeTable :: Tags -> [[Spec]] -> Doc -> Bool -> Doc -> Doc
makeTable :: [String] -> [[Title]] -> Doc -> Bool -> Doc -> Doc
makeTable [String]
_ [] Doc
_ Bool
_ Doc
_       = String -> Doc
forall a. HasCallStack => String -> a
error String
"No table to print (see PrintHTML)"
makeTable [String]
ts ([Title]
l:[[Title]]
lls) Doc
r Bool
b Doc
t = Doc -> Doc -> Doc
refwrap Doc
r ([String] -> Doc -> Doc
table [String]
ts (
    Doc -> Doc
tr ([Title] -> Doc
makeHeaderCols [Title]
l) Doc -> Doc -> Doc
$$ [[Title]] -> Doc
makeRows [[Title]]
lls) Doc -> Doc -> Doc
$$ if Bool
b then Doc -> Doc
caption Doc
t else Doc
empty)

-- | Helper for creating table rows.
makeRows :: [[Spec]] -> Doc
makeRows :: [[Title]] -> Doc
makeRows = ([Title] -> Doc -> Doc) -> Doc -> [[Title]] -> 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) -> ([Title] -> Doc) -> [Title] -> Doc -> Doc
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Doc -> Doc
tr (Doc -> Doc) -> ([Title] -> Doc) -> [Title] -> Doc
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Title] -> Doc
makeColumns) Doc
empty

makeColumns, makeHeaderCols :: [Spec] -> Doc
-- | Helper for creating table header row (each of the column header cells).
makeHeaderCols :: [Title] -> Doc
makeHeaderCols = [Doc] -> Doc
vcat ([Doc] -> Doc) -> ([Title] -> [Doc]) -> [Title] -> Doc
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Title -> Doc) -> [Title] -> [Doc]
forall a b. (a -> b) -> [a] -> [b]
map (Doc -> Doc
th (Doc -> Doc) -> (Title -> Doc) -> Title -> Doc
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Title -> Doc
pSpec)

-- | Helper for creating table columns.
makeColumns :: [Title] -> Doc
makeColumns = [Doc] -> Doc
vcat ([Doc] -> Doc) -> ([Title] -> [Doc]) -> [Title] -> Doc
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Title -> Doc) -> [Title] -> [Doc]
forall a b. (a -> b) -> [a] -> [b]
map (Doc -> Doc
td (Doc -> Doc) -> (Title -> Doc) -> Title -> Doc
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Title -> Doc
pSpec)

-----------------------------------------------------------------
------------------BEGIN DEFINITION PRINTING----------------------
-----------------------------------------------------------------

-- | Renders definition tables (Data, General, Theory, etc.).
makeDefn :: L.DType -> [(String,[LayoutObj])] -> Doc -> Doc
makeDefn :: DType -> [(String, [LayoutObj])] -> Doc -> Doc
makeDefn DType
_ [] Doc
_  = String -> Doc
forall a. HasCallStack => String -> a
error String
"L.Empty definition"
makeDefn DType
dt [(String, [LayoutObj])]
ps Doc
l = Doc -> Doc -> Doc
refwrap Doc
l (Doc -> Doc) -> Doc -> Doc
forall a b. (a -> b) -> a -> b
$ [String] -> Doc -> Doc
table [DType -> String
dtag DType
dt]
  (Doc -> Doc
tr (Doc -> Doc
th (String -> Doc
text String
"Refname") Doc -> Doc -> Doc
$$ Doc -> Doc
td (Doc -> Doc
bold Doc
l)) Doc -> Doc -> Doc
$$ [(String, [LayoutObj])] -> Doc
makeDRows [(String, [LayoutObj])]
ps)
  where dtag :: DType -> String
dtag DType
L.General  = String
"gdefn"
        dtag DType
L.Instance = String
"idefn"
        dtag DType
L.Theory   = String
"tdefn"
        dtag DType
L.Data     = String
"ddefn"

-- | Helper for making the definition table rows.
makeDRows :: [(String,[LayoutObj])] -> Doc
makeDRows :: [(String, [LayoutObj])] -> Doc
makeDRows []         = String -> Doc
forall a. HasCallStack => String -> a
error String
"No fields to create defn table"
makeDRows [(String
f,[LayoutObj]
d)] = Doc -> Doc
tr (Doc -> Doc
th (String -> Doc
text String
f) Doc -> Doc -> Doc
$$ Doc -> Doc
td ([Doc] -> Doc
vcat ([Doc] -> Doc) -> [Doc] -> Doc
forall a b. (a -> b) -> a -> b
$ (LayoutObj -> Doc) -> [LayoutObj] -> [Doc]
forall a b. (a -> b) -> [a] -> [b]
map LayoutObj -> Doc
printLO [LayoutObj]
d))
makeDRows ((String
f,[LayoutObj]
d):[(String, [LayoutObj])]
ps) = Doc -> Doc
tr (Doc -> Doc
th (String -> Doc
text String
f) Doc -> Doc -> Doc
$$ Doc -> Doc
td ([Doc] -> Doc
vcat ([Doc] -> Doc) -> [Doc] -> Doc
forall a b. (a -> b) -> a -> b
$ (LayoutObj -> Doc) -> [LayoutObj] -> [Doc]
forall a b. (a -> b) -> [a] -> [b]
map LayoutObj -> Doc
printLO [LayoutObj]
d)) Doc -> Doc -> Doc
$$ [(String, [LayoutObj])] -> Doc
makeDRows [(String, [LayoutObj])]
ps

-----------------------------------------------------------------
------------------BEGIN LIST PRINTING----------------------------
-----------------------------------------------------------------

-- | Renders lists in HTML.
makeList :: ListType -> Doc -- FIXME: ref id's should be folded into the li
makeList :: ListType -> Doc
makeList (Simple [(Title, ItemType, Maybe Title)]
items) = [String] -> Doc -> Doc
divTag [String
"list"] (Doc -> Doc) -> Doc -> Doc
forall a b. (a -> b) -> a -> b
$
  [Doc] -> Doc
vcat ([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
l) -> Doc -> Doc
pa (Doc -> Doc) -> Doc -> Doc
forall a b. (a -> b) -> a -> b
$ Maybe Title -> Doc -> Doc
mlref Maybe Title
l (Doc -> Doc) -> Doc -> Doc
forall a b. (a -> b) -> a -> b
$ Title -> Doc
pSpec Title
b Doc -> Doc -> Doc
<> String -> Doc
text String
": "
  Doc -> Doc -> Doc
<> ItemType -> Doc
pItem ItemType
e) [(Title, ItemType, Maybe Title)]
items
makeList (Desc [(Title, ItemType, Maybe Title)]
items)   = [String] -> Doc -> Doc
divTag [String
"list"] (Doc -> Doc) -> Doc -> Doc
forall a b. (a -> b) -> a -> b
$
  [Doc] -> Doc
vcat ([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
l) -> Doc -> Doc
pa (Doc -> Doc) -> Doc -> Doc
forall a b. (a -> b) -> a -> b
$ Maybe Title -> Doc -> Doc
mlref Maybe Title
l (Doc -> Doc) -> Doc -> Doc
forall a b. (a -> b) -> a -> b
$ Doc -> Doc
ba (Doc -> Doc) -> Doc -> Doc
forall a b. (a -> b) -> a -> b
$ Title -> Doc
pSpec Title
b
  Doc -> Doc -> Doc
<> String -> Doc
text String
": " Doc -> Doc -> Doc
<> ItemType -> Doc
pItem ItemType
e) [(Title, ItemType, Maybe Title)]
items
makeList (Ordered [(ItemType, Maybe Title)]
items) = [String] -> Doc -> Doc
ol [String
"list"] ([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
  (Doc -> Doc
li (Doc -> Doc)
-> ((ItemType, Maybe Title) -> Doc)
-> (ItemType, Maybe Title)
-> Doc
forall b c a. (b -> c) -> (a -> b) -> a -> c
. \(ItemType
i,Maybe Title
l) -> Maybe Title -> Doc -> Doc
mlref Maybe Title
l (Doc -> Doc) -> Doc -> Doc
forall a b. (a -> b) -> a -> b
$ ItemType -> Doc
pItem ItemType
i) [(ItemType, Maybe Title)]
items)
makeList (Unordered [(ItemType, Maybe Title)]
items) = [String] -> Doc -> Doc
ul [String
"list"] ([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
  (Doc -> Doc
li (Doc -> Doc)
-> ((ItemType, Maybe Title) -> Doc)
-> (ItemType, Maybe Title)
-> Doc
forall b c a. (b -> c) -> (a -> b) -> a -> c
. \(ItemType
i,Maybe Title
l) -> Maybe Title -> Doc -> Doc
mlref Maybe Title
l (Doc -> Doc) -> Doc -> Doc
forall a b. (a -> b) -> a -> b
$ ItemType -> Doc
pItem ItemType
i) [(ItemType, Maybe Title)]
items)
makeList (Definitions [(Title, ItemType, Maybe Title)]
items) = [String] -> Doc -> Doc
ul [String
"hide-list-style-no-indent"] (Doc -> Doc) -> Doc -> Doc
forall a b. (a -> b) -> a -> b
$
  [Doc] -> Doc
vcat ([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
l) -> Doc -> Doc
li (Doc -> Doc) -> Doc -> Doc
forall a b. (a -> b) -> a -> b
$ Maybe Title -> Doc -> Doc
mlref Maybe Title
l (Doc -> Doc) -> Doc -> Doc
forall a b. (a -> b) -> a -> b
$ Title -> Doc
pSpec Title
b Doc -> Doc -> Doc
<> String -> Doc
text String
" is the"
  Doc -> Doc -> Doc
<+> ItemType -> Doc
pItem ItemType
e) [(Title, ItemType, Maybe Title)]
items

-- | Helper for setting up references.
mlref :: Maybe Label -> Doc -> Doc
mlref :: Maybe Title -> Doc -> Doc
mlref = (Doc -> Doc) -> (Title -> Doc -> Doc) -> Maybe Title -> Doc -> Doc
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Doc -> Doc
forall a. a -> a
id ((Title -> Doc -> Doc) -> Maybe Title -> Doc -> Doc)
-> (Title -> Doc -> Doc) -> Maybe Title -> Doc -> Doc
forall a b. (a -> b) -> a -> b
$ Doc -> Doc -> Doc
refwrap (Doc -> Doc -> Doc) -> (Title -> Doc) -> Title -> Doc -> Doc
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Title -> Doc
pSpec

-- | Helper for rendering list items.
pItem :: ItemType -> Doc
pItem :: ItemType -> Doc
pItem (Flat Title
s)     = Title -> Doc
pSpec Title
s
pItem (Nested Title
s ListType
l) = [Doc] -> Doc
vcat [Title -> Doc
pSpec Title
s, ListType -> Doc
makeList ListType
l]

-----------------------------------------------------------------
------------------BEGIN FIGURE PRINTING--------------------------
-----------------------------------------------------------------
-- | Renders figures in HTML.
makeFigure :: Doc -> Maybe Doc -> Doc -> L.MaxWidthPercent -> Doc
makeFigure :: Doc -> Maybe Doc -> Doc -> MaxWidthPercent -> Doc
makeFigure Doc
r Maybe Doc
c Doc
f MaxWidthPercent
wp = Doc -> Doc -> Doc
refwrap Doc
r (Doc -> Maybe Doc -> MaxWidthPercent -> Doc
image Doc
f Maybe Doc
c MaxWidthPercent
wp)

-- | Renders assumptions, requirements, likely changes.
makeRefList :: Doc -> Doc -> Doc -> Doc
makeRefList :: Doc -> Doc -> Doc -> Doc
makeRefList Doc
a Doc
l Doc
i = Doc -> Doc
li (Doc -> Doc -> Doc
refwrap Doc
l (Doc
i Doc -> Doc -> Doc
<> String -> Doc
text String
": " Doc -> Doc -> Doc
<> Doc
a))

---------------------
--HTML bibliography--
---------------------
-- **THE MAIN FUNCTION**

-- | Makes a bilbliography for the document.
makeBib :: BibRef -> Doc
makeBib :: BibRef -> Doc
makeBib = [String] -> Doc -> Doc
ul [String
"hide-list-style"] (Doc -> Doc) -> (BibRef -> Doc) -> BibRef -> Doc
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Doc] -> Doc
vcat ([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)
renderCite BibFormatter
htmlBibFormatter)

-- | HTML specific bib rendering functions
htmlBibFormatter :: BibFormatter
htmlBibFormatter :: BibFormatter
htmlBibFormatter = BibFormatter {
  emph :: Doc -> Doc
emph = Doc -> Doc
em,
  spec :: Title -> Doc
spec = Title -> Doc
pSpec
}

-- | For when we add other things to reference like website, newspaper
renderCite :: BibFormatter -> Citation -> (Doc, Doc)
renderCite :: BibFormatter -> Citation -> (Doc, Doc)
renderCite BibFormatter
f (Cite String
e CitationKind
L.Book [CiteField]
cfs)      = (String -> Doc
text String
e, [CiteField] -> (StyleGuide -> CiteField -> Doc) -> Doc
renderF [CiteField]
cfs (BibFormatter -> StyleGuide -> CiteField -> Doc
useStyleBk    BibFormatter
f)  Doc -> Doc -> Doc
<> String -> Doc
text ([CiteField] -> String
sufxPrint [CiteField]
cfs))
renderCite BibFormatter
f (Cite String
e CitationKind
L.Article [CiteField]
cfs)   = (String -> Doc
text String
e, [CiteField] -> (StyleGuide -> CiteField -> Doc) -> Doc
renderF [CiteField]
cfs (BibFormatter -> StyleGuide -> CiteField -> Doc
useStyleArtcl BibFormatter
f)  Doc -> Doc -> Doc
<> String -> Doc
text ([CiteField] -> String
sufxPrint [CiteField]
cfs))
renderCite BibFormatter
f (Cite String
e CitationKind
L.MThesis [CiteField]
cfs)   = (String -> Doc
text String
e, [CiteField] -> (StyleGuide -> CiteField -> Doc) -> Doc
renderF [CiteField]
cfs (BibFormatter -> StyleGuide -> CiteField -> Doc
useStyleBk    BibFormatter
f)  Doc -> Doc -> Doc
<> String -> Doc
text ([CiteField] -> String
sufxPrint [CiteField]
cfs))
renderCite BibFormatter
f (Cite String
e CitationKind
L.PhDThesis [CiteField]
cfs) = (String -> Doc
text String
e, [CiteField] -> (StyleGuide -> CiteField -> Doc) -> Doc
renderF [CiteField]
cfs (BibFormatter -> StyleGuide -> CiteField -> Doc
useStyleBk    BibFormatter
f)  Doc -> Doc -> Doc
<> String -> Doc
text ([CiteField] -> String
sufxPrint [CiteField]
cfs))
renderCite BibFormatter
f (Cite String
e CitationKind
L.Misc [CiteField]
cfs)      = (String -> Doc
text String
e, [CiteField] -> (StyleGuide -> CiteField -> Doc) -> Doc
renderF [CiteField]
cfs (BibFormatter -> StyleGuide -> CiteField -> Doc
useStyleBk    BibFormatter
f))
renderCite BibFormatter
f (Cite String
e CitationKind
_ [CiteField]
cfs)           = (String -> Doc
text String
e, [CiteField] -> (StyleGuide -> CiteField -> Doc) -> Doc
renderF [CiteField]
cfs (BibFormatter -> StyleGuide -> CiteField -> Doc
useStyleArtcl BibFormatter
f)) --FIXME: Properly render these later.

-- | Render fields to be used in the document.
renderF :: [CiteField] -> (StyleGuide -> (CiteField -> Doc)) -> Doc
renderF :: [CiteField] -> (StyleGuide -> CiteField -> Doc) -> Doc
renderF [CiteField]
fields StyleGuide -> CiteField -> Doc
styl = [Doc] -> Doc
hsep ([Doc] -> Doc) -> [Doc] -> Doc
forall a b. (a -> b) -> a -> b
$ (CiteField -> Doc) -> [CiteField] -> [Doc]
forall a b. (a -> b) -> [a] -> [b]
map (StyleGuide -> CiteField -> Doc
styl StyleGuide
bibStyleH) ((CiteField -> CiteField -> Ordering) -> [CiteField] -> [CiteField]
forall a. (a -> a -> Ordering) -> [a] -> [a]
sortBy CiteField -> CiteField -> Ordering
compCiteField [CiteField]
fields)

-- | Compares two cite fields.
compCiteField :: CiteField -> CiteField -> Ordering
compCiteField :: CiteField -> CiteField -> Ordering
compCiteField (Institution Title
_) CiteField
_ = Ordering
LT
compCiteField CiteField
_ (Institution Title
_) = Ordering
GT
compCiteField (Organization Title
_) CiteField
_ = Ordering
LT
compCiteField CiteField
_ (Organization Title
_) = Ordering
GT
compCiteField (Author     People
_) CiteField
_ = Ordering
LT
compCiteField CiteField
_ (Author     People
_) = Ordering
GT
compCiteField (Title      Title
_) CiteField
_ = Ordering
LT
compCiteField CiteField
_ (Title      Title
_) = Ordering
GT
compCiteField (Series     Title
_) CiteField
_ = Ordering
LT
compCiteField CiteField
_ (Series     Title
_) = Ordering
GT
compCiteField (BookTitle Title
_) CiteField
_  = Ordering
LT
compCiteField CiteField
_ (BookTitle Title
_)  = Ordering
GT
compCiteField (Editor     People
_) CiteField
_ = Ordering
LT
compCiteField CiteField
_ (Editor     People
_) = Ordering
GT
compCiteField (Journal    Title
_) CiteField
_ = Ordering
LT
compCiteField CiteField
_ (Journal    Title
_) = Ordering
GT
compCiteField (Volume     Int
_) CiteField
_ = Ordering
LT
compCiteField CiteField
_ (Volume     Int
_) = Ordering
GT
compCiteField (Number     Int
_) CiteField
_ = Ordering
LT
compCiteField CiteField
_ (Number     Int
_) = Ordering
GT
compCiteField (Edition    Int
_) CiteField
_ = Ordering
LT
compCiteField CiteField
_ (Edition    Int
_) = Ordering
GT
compCiteField (HowPublished (Verb Title
_)) CiteField
_ = Ordering
LT
compCiteField CiteField
_ (HowPublished (Verb Title
_)) = Ordering
GT
compCiteField (School     Title
_) CiteField
_ = Ordering
LT
compCiteField CiteField
_ (School     Title
_) = Ordering
GT
compCiteField (Address      Title
_) CiteField
_ = Ordering
LT
compCiteField CiteField
_ (Address      Title
_) = Ordering
GT
compCiteField (Publisher  Title
_) CiteField
_ = Ordering
LT
compCiteField CiteField
_ (Publisher  Title
_) = Ordering
GT
compCiteField (Month      Month
_) CiteField
_ = Ordering
LT
compCiteField CiteField
_ (Month      Month
_) = Ordering
GT
compCiteField (Year       Int
_) CiteField
_ = Ordering
LT
compCiteField CiteField
_ (Year       Int
_) = Ordering
GT
compCiteField (HowPublished (URL Title
_)) CiteField
_ = Ordering
LT
compCiteField CiteField
_ (HowPublished (URL Title
_)) = Ordering
GT
compCiteField (Chapter    Int
_) CiteField
_ = Ordering
LT
compCiteField CiteField
_ (Chapter    Int
_) = Ordering
GT
compCiteField (Pages      [Int]
_) CiteField
_ = Ordering
LT
compCiteField CiteField
_ (Pages      [Int]
_) = Ordering
GT
compCiteField (Note       Title
_) CiteField
_ = Ordering
LT
compCiteField CiteField
_ (Note       Title
_) = Ordering
GT
compCiteField (Type       Title
_) CiteField
_ = Ordering
LT

-- Config helpers --
-- | Renders citation as a book style.
useStyleBk :: BibFormatter -> StyleGuide -> (CiteField -> Doc)
useStyleBk :: BibFormatter -> StyleGuide -> CiteField -> Doc
useStyleBk BibFormatter
f StyleGuide
MLA     = BibFormatter -> CiteField -> Doc
bookMLA BibFormatter
f
useStyleBk BibFormatter
f StyleGuide
APA     = BibFormatter -> CiteField -> Doc
bookAPA BibFormatter
f
useStyleBk BibFormatter
f StyleGuide
Chicago = BibFormatter -> CiteField -> Doc
bookChicago BibFormatter
f

-- | Renders citation as an article style.
useStyleArtcl :: BibFormatter -> StyleGuide -> (CiteField -> Doc)
useStyleArtcl :: BibFormatter -> StyleGuide -> CiteField -> Doc
useStyleArtcl BibFormatter
f StyleGuide
MLA     = BibFormatter -> CiteField -> Doc
artclMLA BibFormatter
f
useStyleArtcl BibFormatter
f StyleGuide
APA     = BibFormatter -> CiteField -> Doc
artclAPA BibFormatter
f
useStyleArtcl BibFormatter
f StyleGuide
Chicago = BibFormatter -> CiteField -> Doc
artclChicago BibFormatter
f

-- FIXME: move these show functions and use tags, combinators
-- | Cite books in MLA format.
bookMLA :: BibFormatter -> CiteField -> Doc
bookMLA :: BibFormatter -> CiteField -> Doc
bookMLA BibFormatter
f (Address   Title
s) = BibFormatter -> Title -> Doc
spec BibFormatter
f Title
s Doc -> Doc -> Doc
<> String -> Doc
text String
":"
bookMLA BibFormatter
_ (Edition   Int
s) = Doc -> Doc
comm (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
$ Int -> String
forall a. Show a => a -> String
show Int
s String -> String -> String
forall a. [a] -> [a] -> [a]
++ Int -> String
sufxer Int
s String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" ed."
bookMLA BibFormatter
f (Series    Title
s) = Doc -> Doc
dot (Doc -> Doc) -> Doc -> Doc
forall a b. (a -> b) -> a -> b
$ BibFormatter -> Doc -> Doc
emph BibFormatter
f (Doc -> Doc) -> Doc -> Doc
forall a b. (a -> b) -> a -> b
$ BibFormatter -> Title -> Doc
spec BibFormatter
f Title
s
bookMLA BibFormatter
f (Title     Title
s) = Doc -> Doc
dot (Doc -> Doc) -> Doc -> Doc
forall a b. (a -> b) -> a -> b
$ BibFormatter -> Doc -> Doc
emph BibFormatter
f (Doc -> Doc) -> Doc -> Doc
forall a b. (a -> b) -> a -> b
$ BibFormatter -> Title -> Doc
spec BibFormatter
f Title
s --If there is a series or collection, this should be in quotes, not italics
bookMLA BibFormatter
_ (Volume    Int
s) = Doc -> Doc
comm (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
"vol. " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Int -> String
forall a. Show a => a -> String
show Int
s
bookMLA BibFormatter
f (Publisher Title
s) = Doc -> Doc
comm (Doc -> Doc) -> Doc -> Doc
forall a b. (a -> b) -> a -> b
$ BibFormatter -> Title -> Doc
spec BibFormatter
f Title
s
bookMLA BibFormatter
f (Author    People
p) = Doc -> Doc
dot (Doc -> Doc) -> Doc -> Doc
forall a b. (a -> b) -> a -> b
$ BibFormatter -> Title -> Doc
spec BibFormatter
f (People -> Title
rendPeople' People
p)
bookMLA BibFormatter
_ (Year      Int
y) = Doc -> Doc
dot (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
$ Int -> String
forall a. Show a => a -> String
show Int
y
--bookMLA _ (Date    d m y) = dot $ unwords [show d, show m, show y]
--bookMLA f (URLdate d m y) = "Web. " ++ bookMLA f (Date d m y) sm
bookMLA BibFormatter
f (BookTitle Title
s) = Doc -> Doc
dot (Doc -> Doc) -> Doc -> Doc
forall a b. (a -> b) -> a -> b
$ BibFormatter -> Doc -> Doc
emph BibFormatter
f (Doc -> Doc) -> Doc -> Doc
forall a b. (a -> b) -> a -> b
$ BibFormatter -> Title -> Doc
spec BibFormatter
f Title
s
bookMLA BibFormatter
f (Journal   Title
s) = Doc -> Doc
comm (Doc -> Doc) -> Doc -> Doc
forall a b. (a -> b) -> a -> b
$ BibFormatter -> Doc -> Doc
emph BibFormatter
f (Doc -> Doc) -> Doc -> Doc
forall a b. (a -> b) -> a -> b
$ BibFormatter -> Title -> Doc
spec BibFormatter
f Title
s
bookMLA BibFormatter
_ (Pages   [Int
p]) = Doc -> Doc
dot (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
"pg. " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Int -> String
forall a. Show a => a -> String
show Int
p
bookMLA BibFormatter
_ (Pages     [Int]
p) = Doc -> Doc
dot (Doc -> Doc) -> Doc -> Doc
forall a b. (a -> b) -> a -> b
$ String -> Doc
text String
"pp. " Doc -> Doc -> Doc
<> [Int] -> Doc
foldPages [Int]
p
bookMLA BibFormatter
f (Note      Title
s) = BibFormatter -> Title -> Doc
spec BibFormatter
f Title
s
bookMLA BibFormatter
_ (Number    Int
n) = Doc -> Doc
comm (Doc -> Doc) -> Doc -> Doc
forall a b. (a -> b) -> a -> b
$ String -> Doc
text (String
"no. " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Int -> String
forall a. Show a => a -> String
show Int
n)
bookMLA BibFormatter
f (School    Title
s) = Doc -> Doc
comm (Doc -> Doc) -> Doc -> Doc
forall a b. (a -> b) -> a -> b
$ BibFormatter -> Title -> Doc
spec BibFormatter
f Title
s
--bookMLA _ (Thesis     t)  = comm $ show t
--bookMLA f (URL        s)  = dot $ spec f s
bookMLA BibFormatter
f (HowPublished (Verb Title
s))      = Doc -> Doc
comm (Doc -> Doc) -> Doc -> Doc
forall a b. (a -> b) -> a -> b
$ BibFormatter -> Title -> Doc
spec BibFormatter
f Title
s
bookMLA BibFormatter
f (HowPublished (URL l :: Title
l@(S String
s))) = Doc -> Doc
dot  (Doc -> Doc) -> Doc -> Doc
forall a b. (a -> b) -> a -> b
$ BibFormatter -> Title -> Doc
spec BibFormatter
f (Title -> Doc) -> Title -> Doc
forall a b. (a -> b) -> a -> b
$ LinkType -> String -> Title -> Title
Ref LinkType
External String
s Title
l
bookMLA BibFormatter
f (HowPublished (URL Title
s))       = Doc -> Doc
dot  (Doc -> Doc) -> Doc -> Doc
forall a b. (a -> b) -> a -> b
$ BibFormatter -> Title -> Doc
spec BibFormatter
f Title
s
bookMLA BibFormatter
_ (Editor       People
p) = Doc -> Doc
comm (Doc -> Doc) -> Doc -> Doc
forall a b. (a -> b) -> a -> b
$ String -> Doc
text String
"Edited by " Doc -> Doc -> Doc
<> People -> Doc
foldPeople People
p
bookMLA BibFormatter
_ (Chapter      Int
_) = String -> Doc
text String
""
bookMLA BibFormatter
f (Institution  Title
i) = Doc -> Doc
comm (Doc -> Doc) -> Doc -> Doc
forall a b. (a -> b) -> a -> b
$ BibFormatter -> Title -> Doc
spec BibFormatter
f Title
i
bookMLA BibFormatter
f (Organization Title
i) = Doc -> Doc
comm (Doc -> Doc) -> Doc -> Doc
forall a b. (a -> b) -> a -> b
$ BibFormatter -> Title -> Doc
spec BibFormatter
f Title
i
bookMLA BibFormatter
_ (Month        Month
m) = Doc -> Doc
comm (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
$ Month -> String
forall a. Show a => a -> String
show Month
m
bookMLA BibFormatter
f (Type         Title
t) = Doc -> Doc
comm (Doc -> Doc) -> Doc -> Doc
forall a b. (a -> b) -> a -> b
$ BibFormatter -> Title -> Doc
spec BibFormatter
f Title
t

-- | Cite books in APA format.
bookAPA :: BibFormatter -> CiteField -> Doc --FIXME: year needs to come after author in L.APA
bookAPA :: BibFormatter -> CiteField -> Doc
bookAPA BibFormatter
f (Author   People
p) = BibFormatter -> Title -> Doc
spec BibFormatter
f ((Person -> String) -> People -> Title
rendPeople Person -> String
L.rendPersLFM' People
p) --L.APA uses initals rather than full name
bookAPA BibFormatter
_ (Year     Int
y) = Doc -> Doc
dot (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
paren (String -> String) -> String -> String
forall a b. (a -> b) -> a -> b
$ Int -> String
forall a. Show a => a -> String
show Int
y --L.APA puts "()" around the year
--bookAPA _ (Date _ _ y) = bookAPA (Year y) --L.APA doesn't care about the day or month
--bookAPA _ (URLdate d m y) = "Retrieved, " ++ (comm $ unwords [show d, show m, show y])
bookAPA BibFormatter
_ (Pages    [Int]
p) = Doc -> Doc
dot (Doc -> Doc) -> Doc -> Doc
forall a b. (a -> b) -> a -> b
$ [Int] -> Doc
foldPages [Int]
p
bookAPA BibFormatter
_ (Editor   People
p) = Doc -> Doc
dot (Doc -> Doc) -> Doc -> Doc
forall a b. (a -> b) -> a -> b
$ People -> Doc
foldPeople People
p Doc -> Doc -> Doc
<> String -> Doc
text String
" (Ed.)"
bookAPA BibFormatter
f CiteField
i = BibFormatter -> CiteField -> Doc
bookMLA BibFormatter
f CiteField
i --Most items are rendered the same as L.MLA

-- | Cite books in Chicago format.
bookChicago :: BibFormatter -> CiteField -> Doc
bookChicago :: BibFormatter -> CiteField -> Doc
bookChicago BibFormatter
f (Author   People
p) = BibFormatter -> Title -> Doc
spec BibFormatter
f ((Person -> String) -> People -> Title
rendPeople Person -> String
L.rendPersLFM'' People
p) --L.APA uses middle initals rather than full name
bookChicago BibFormatter
_ (Pages    [Int]
p) = Doc -> Doc
dot (Doc -> Doc) -> Doc -> Doc
forall a b. (a -> b) -> a -> b
$ [Int] -> Doc
foldPages [Int]
p
bookChicago BibFormatter
_ (Editor   People
p) = Doc -> Doc
dot (Doc -> Doc) -> Doc -> Doc
forall a b. (a -> b) -> a -> b
$ People -> Doc
foldPeople People
p Doc -> Doc -> Doc
<> String -> Doc
text (People -> String -> String
toPlural People
p String
" ed")
bookChicago BibFormatter
f CiteField
i = BibFormatter -> CiteField -> Doc
bookMLA BibFormatter
f CiteField
i --Most items are rendered the same as L.MLA

-- for article renderings
-- | Cite articles in MLA format.
artclMLA :: BibFormatter -> CiteField -> Doc
artclMLA :: BibFormatter -> CiteField -> Doc
artclMLA BibFormatter
f (Title Title
s) = Doc -> Doc
doubleQuotes (Doc -> Doc) -> Doc -> Doc
forall a b. (a -> b) -> a -> b
$ Doc -> Doc
dot (Doc -> Doc) -> Doc -> Doc
forall a b. (a -> b) -> a -> b
$ BibFormatter -> Title -> Doc
spec BibFormatter
f Title
s
artclMLA BibFormatter
f CiteField
i         = BibFormatter -> CiteField -> Doc
bookMLA BibFormatter
f CiteField
i

-- | Cite articles in APA format.
artclAPA :: BibFormatter -> CiteField -> Doc
artclAPA :: BibFormatter -> CiteField -> Doc
artclAPA BibFormatter
f (Title  Title
s)  = Doc -> Doc
dot (Doc -> Doc) -> Doc -> Doc
forall a b. (a -> b) -> a -> b
$ BibFormatter -> Title -> Doc
spec BibFormatter
f Title
s
artclAPA BibFormatter
_ (Volume Int
n)  = Doc -> Doc
em (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
$ Int -> String
forall a. Show a => a -> String
show Int
n
artclAPA BibFormatter
_ (Number  Int
n) = Doc -> Doc
comm (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
paren (String -> String) -> String -> String
forall a b. (a -> b) -> a -> b
$ Int -> String
forall a. Show a => a -> String
show Int
n
artclAPA BibFormatter
f CiteField
i           = BibFormatter -> CiteField -> Doc
bookAPA BibFormatter
f CiteField
i

-- | Cite articles in Chicago format.
artclChicago :: BibFormatter -> CiteField -> Doc
artclChicago :: BibFormatter -> CiteField -> Doc
artclChicago BibFormatter
f i :: CiteField
i@(Title    Title
_) = BibFormatter -> CiteField -> Doc
artclMLA BibFormatter
f CiteField
i
artclChicago BibFormatter
_ (Volume     Int
n) = Doc -> Doc
comm (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
$ Int -> String
forall a. Show a => a -> String
show Int
n
artclChicago BibFormatter
_ (Number      Int
n) = String -> Doc
text (String -> Doc) -> String -> Doc
forall a b. (a -> b) -> a -> b
$ String
"no. " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Int -> String
forall a. Show a => a -> String
show Int
n
artclChicago BibFormatter
f i :: CiteField
i@(Year     Int
_) = BibFormatter -> CiteField -> Doc
bookAPA BibFormatter
f CiteField
i
--artclChicago f i@(Date _ _ _) = bookAPA f i
artclChicago BibFormatter
f CiteField
i = BibFormatter -> CiteField -> Doc
bookChicago BibFormatter
f CiteField
i

-- PEOPLE RENDERING --
-- | Render a list of people (after applying a given function).
rendPeople :: (L.Person -> String) -> L.People -> Spec
rendPeople :: (Person -> String) -> People -> Title
rendPeople Person -> String
_ []  = String -> Title
S String
"N.a." -- "No authors given"
rendPeople Person -> String
f People
people = String -> Title
S (String -> Title) -> ([String] -> String) -> [String] -> Title
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [String] -> String
foldlList ([String] -> Title) -> [String] -> Title
forall a b. (a -> b) -> a -> b
$ (Person -> String) -> People -> [String]
forall a b. (a -> b) -> [a] -> [b]
map Person -> String
f People
people --foldlList is in drasil-utils

-- | Render a list of people (of form FirstName LastName).
rendPeople' :: L.People -> Spec
rendPeople' :: People -> Title
rendPeople' []  = String -> Title
S String
"N.a." -- "No authors given"
rendPeople' People
people = String -> Title
S (String -> Title) -> ([String] -> String) -> [String] -> Title
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [String] -> String
foldlList ([String] -> Title) -> [String] -> Title
forall a b. (a -> b) -> a -> b
$ (Person -> String) -> People -> [String]
forall a b. (a -> b) -> [a] -> [b]
map Person -> String
rendPers (People -> People
forall a. HasCallStack => [a] -> [a]
init People
people) [String] -> [String] -> [String]
forall a. [a] -> [a] -> [a]
++  [Person -> String
rendPersL (People -> Person
forall a. HasCallStack => [a] -> a
last People
people)]

-- | Organize a list of pages.
foldPages :: [Int] -> Doc
foldPages :: [Int] -> Doc
foldPages = String -> Doc
text (String -> Doc) -> ([Int] -> String) -> [Int] -> Doc
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [String] -> String
foldlList ([String] -> String) -> ([Int] -> [String]) -> [Int] -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> [Int] -> [String]
L.numList String
"&ndash;"

-- | Organize a list of people.
foldPeople :: L.People -> Doc
foldPeople :: People -> Doc
foldPeople People
p = String -> Doc
text (String -> Doc) -> ([String] -> String) -> [String] -> Doc
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [String] -> String
foldlList ([String] -> Doc) -> [String] -> Doc
forall a b. (a -> b) -> a -> b
$ (Person -> String) -> People -> [String]
forall a b. (a -> b) -> [a] -> [b]
map Person -> String
forall p. HasName p => p -> String
L.nameStr People
p

-- | Organize a list of Strings, separated by commas and inserting "and" before the last item.
foldlList :: [String] -> String
foldlList :: [String] -> String
foldlList []    = String
""
foldlList [String
a,String
b] = String
a String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" and " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
b
foldlList [String]
lst   = (String -> String -> String)
-> (String -> String -> String) -> [String] -> String
forall a. (a -> a -> a) -> (a -> a -> a) -> [a] -> a
foldle1 (\String
a String
b -> String
a String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
", " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
b) (\String
a String
b -> String
a String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
", and " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
b) [String]
lst

-- | Similar to foldl, but applies a function to two arguments at a time.
foldle1 :: (a -> a -> a) -> (a -> a -> a) -> [a] -> a
foldle1 :: forall a. (a -> a -> a) -> (a -> a -> a) -> [a] -> a
foldle1 a -> a -> a
_ a -> a -> a
_ []       = String -> a
forall a. HasCallStack => String -> a
error String
"foldle1 cannot be used with empty list"
foldle1 a -> a -> a
_ a -> a -> a
_ [a
x]      = a
x
foldle1 a -> a -> a
_ a -> a -> a
g [a
x,a
y]    = a -> a -> a
g a
x a
y
foldle1 a -> a -> a
f a -> a -> a
g (a
x:a
y:[a]
xs) = (a -> a -> a) -> (a -> a -> a) -> [a] -> a
forall a. (a -> a -> a) -> (a -> a -> a) -> [a] -> a
foldle1 a -> a -> a
f a -> a -> a
g (a -> a -> a
f a
x a
y a -> [a] -> [a]
forall a. a -> [a] -> [a]
: [a]
xs)

-- | Renders a 'Person' as Last, First Middle.
rendPers :: L.Person -> String
rendPers :: Person -> String
rendPers = Person -> String
L.rendPersLFM

-- | Renders a person's last name.
rendPersL :: L.Person -> String
rendPersL :: Person -> String
rendPersL =
  (\String
n -> (if Bool -> Bool
not (String -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null String
n) Bool -> Bool -> Bool
&& String -> Char
forall a. HasCallStack => [a] -> a
last String
n Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'.' then String -> String
forall a. HasCallStack => [a] -> [a]
init else String -> String
forall a. a -> a
id) String
n) (String -> String) -> (Person -> String) -> Person -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Person -> String
rendPers

-- | adds an 's' if there is more than one person in a list.
toPlural :: L.People -> String -> String
toPlural :: People -> String -> String
toPlural (Person
_:People
_) String
str = String
str String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"s"
toPlural People
_     String
str = String
str