module Text.PDF.Slave.Template(
TemplateName
, TemplateInput
, TemplateBody
, TemplateBibtex
, DependencyBody
, BibTexBody
, TemplateDependency(..)
, Template(..)
, TemplateDependencyFile(..)
, TemplateFile(..)
) where
import Control.Monad (mzero, unless)
import Data.ByteString (ByteString)
import Data.Monoid
import Data.Text as T
import Data.Aeson
import GHC.Generics
import qualified Data.ByteString.Base64 as B64
import qualified Data.Map.Strict as M
import qualified Data.Text.Encoding as T
type TemplateName = Text
type TemplateInput = Value
type TemplateBody = Text
type TemplateBibtex = Text
type DependencyBody = ByteString
type BibTexBody = Text
data TemplateDependency =
BibtexDep BibTexBody
| TemplateDep Template
| TemplatePdfDep Template
| OtherDep DependencyBody
deriving (Generic, Show)
instance FromJSON TemplateDependency where
parseJSON val@(Object o) = do
depType <- o .: "type"
case T.toLower . T.strip $ depType of
"bibtex" -> BibtexDep <$> o .: "body"
"template" -> TemplateDep <$> parseJSON val
"template_pdf" -> TemplatePdfDep <$> parseJSON val
"other" -> do
(t :: Text) <- o .: "body"
either (\e -> fail $ "Cannot decode dependency body (base64): " <> e) (return . OtherDep) $
B64.decode . T.encodeUtf8 $ t
_ -> fail $ "Unknown template type " <> unpack depType
parseJSON _ = mzero
instance ToJSON TemplateDependency where
toJSON d = case d of
BibtexDep body -> object [
"type" .= ("bibtex" :: Text)
, "body" .= body
]
TemplateDep body -> let
Object o1 = object [ "type" .= ("template" :: Text) ]
Object o2 = toJSON body
in Object (o1 <> o2)
TemplatePdfDep body -> let
Object o1 = object [ "type" .= ("template_pdf" :: Text) ]
Object o2 = toJSON body
in Object (o1 <> o2)
OtherDep bs -> object [
"type" .= ("other" :: Text)
, "body" .= (T.decodeUtf8 . B64.encode $ bs)
]
data Template = Template {
templateName :: TemplateName
, templateInput :: Maybe TemplateInput
, templateBody :: TemplateBody
, templateDeps :: M.Map TemplateName TemplateDependency
, templateHaskintexOpts :: [Text]
} deriving (Generic, Show)
instance FromJSON Template where
parseJSON (Object o) = do
flag <- o .: "bundle"
unless flag $ fail "Expected bundle template format, but got ordinary template"
Template
<$> o .: "name"
<*> o .:? "input"
<*> o .: "body"
<*> o .:? "dependencies" .!= mempty
<*> o .:? "haskintex-opts" .!= mempty
parseJSON _ = mzero
instance ToJSON Template where
toJSON Template{..} = object [
"name" .= templateName
, "input" .= templateInput
, "body" .= templateBody
, "dependencies" .= templateDeps
, "haskintex-opts" .= templateHaskintexOpts
, "bundle" .= True
]
data TemplateDependencyFile =
BibtexDepFile
| TemplateDepFile TemplateFile
| TemplatePdfDepFile TemplateFile
| OtherDepFile
deriving (Generic, Show)
instance FromJSON TemplateDependencyFile where
parseJSON val@(Object o) = do
depType <- o .: "type"
case T.toLower . T.strip $ depType of
"bibtex" -> pure BibtexDepFile
"template" -> TemplateDepFile <$> parseJSON val
"template_pdf" -> TemplatePdfDepFile <$> parseJSON val
"other" -> pure OtherDepFile
_ -> fail $ "Unknown template type " <> unpack depType
parseJSON _ = mzero
instance ToJSON TemplateDependencyFile where
toJSON d = case d of
BibtexDepFile -> object [
"type" .= ("bibtex" :: Text)
]
TemplateDepFile body -> let
Object o1 = object [ "type" .= ("template" :: Text) ]
Object o2 = toJSON body
in Object (o1 <> o2)
TemplatePdfDepFile body -> let
Object o1 = object [ "type" .= ("template_pdf" :: Text) ]
Object o2 = toJSON body
in Object (o1 <> o2)
OtherDepFile -> object [
"type" .= ("other" :: Text)
]
data TemplateFile = TemplateFile {
templateFileName :: TemplateName
, templateFileInput :: Maybe Text
, templateFileBody :: Text
, templateFileDeps :: M.Map TemplateName TemplateDependencyFile
, templateFileHaskintexOpts :: [Text]
} deriving (Generic, Show)
instance FromJSON TemplateFile where
parseJSON (Object o) = do
mflag <- o .:? "bundle"
case mflag of
Just True -> fail "Expected ordinary template format, but got bundle template"
_ -> return ()
TemplateFile
<$> o .: "name"
<*> o .:? "input"
<*> o .: "body"
<*> o .:? "dependencies" .!= mempty
<*> o .:? "haskintex-opts" .!= mempty
parseJSON _ = mzero
instance ToJSON TemplateFile where
toJSON TemplateFile{..} = object [
"name" .= templateFileName
, "input" .= templateFileInput
, "body" .= templateFileBody
, "dependencies" .= templateFileDeps
, "haskintex-opts" .= templateFileHaskintexOpts
]