packages feed

fmark-0.1.1: src/Backend/Latex.hs

module Backend.Latex where

import Data.Functor ((<$>))
import Data.List (intercalate)

import Utils (trim)
import Data.Document
import Data.Text


-- | 'docToLatex' @mstyle doc@ formats a styled 'Document' @doc@ into
-- a LaTeX 'String', where @mstyle@ specifies the style 'Document'
-- used to stylize @doc@.
docToLatex :: Maybe Document -> Document -> String
docToLatex mstyle doc =
    let ps = properties doc 
        title = lookup "Title" ps
        subtitle = lookup "Subtitle" ps
        author = lookup "Author" ps
        date = lookup "Date" ps
        abstract = lookup "Abstract" ps
        maketitle = case (title, author, date) of
                      (Just _, Just _, Just _) -> def "maketitle"
                      _ -> ""
    in
      seq [comArgs "documentclass" ["a4paper"] "article",
           comArgs "usepackage" ["utf8"] "inputenc",
           fulltitle title subtitle,
           prop (com "author") author,
           prop (com "date") date,
           env "document" $ seq [maketitle,
                                 prop (env "abstract") abstract,
                                 loop 0 doc]]
    where fulltitle Nothing Nothing = ""
          fulltitle (Just t) Nothing = com "title" t
          fulltitle Nothing (Just s) = com "title" $ com "large" s
          fulltitle (Just t) (Just s) = com "title" $ nls $ t ++ "\n" ++ com "large" s

          properties (Heading _ _) = []
          properties (Paragraph _ _) = []
          properties (Content docs) = concatMap properties docs
          properties (Section doc) = properties doc
          properties (Style _ sty str) = [(sty, loopText str)]

          lit = concatMap lit'
              where lit' '#' = "\\#"
                    lit' c = [c]

          nls = concatMap nls'
              where nls' '\n' = "\\\\"
                    nls' c = [c]

          def id = '\\':lit id
          com id str = "\\" ++ lit id ++ "{" ++ lit str ++ "}"
          comArgs id args str = "\\" ++ lit id ++ "[" ++ intercalate "," (map lit args) ++ "]{" ++ lit str ++ "}"
          env id str = "\\begin{" ++ lit id ++ "}\n" ++ lit str ++ "\n\\end{" ++ lit id ++ "}"

          prop fn = maybe "" $ fn . lit

          sec lvl str
              | lvl < 3 = com (concat (replicate lvl "sub") ++ "section") $ nls str
              | lvl == 3 = com "paragraph" $ nls str
              | lvl == 4 = com "subparagraph" $ nls str

          par = lit

          seq = intercalate "\n" . filter (\ln -> trim ln /= "")

          loopText (Footnote str) = com "footnote" str
          loopText (Plain str) = lit str

          loop lvl (Heading _ lns) = sec lvl $ intercalate "\n" [ concatMap loopText txts | txts <- lns ]
          loop lvl (Paragraph _ txts) = concatMap loopText txts
          loop lvl (Content docs) = seq $ map (loop lvl) docs
          loop lvl (Section doc) = loop (lvl + 1) doc
          loop lvl Style {} = ""