project-forge-0.1.0.0: src/ProjectForge/Compile.hs
{-|
Functions for compiling Project and File Templates
-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE OverloadedStrings #-}
module ProjectForge.Compile (
-- * Compiling project templates
-- $compileTemplates
compileFileTemplate
, compileProjectTemplate
-- ** Re-exports
, module Text.Mustache.Type
) where
import Control.Exception
import Control.Monad
import Control.Monad.IO.Class
import Data.Bifunctor
import qualified Data.Set as Set
import Data.Text
import ProjectForge.ProjectTemplate
import Text.Mustache.Compile
import Text.Mustache.Type
{- $compileTemplates
Template compilation marshals @Data.Text.Text@ into @'Text.Mustache.Template'@s.
The utilities here extend the utilities provided by @Text.Mustache@
to create @'FileTemplate'@s and @'ProjectTemplate'@s.
-}
{-|
Create a @'FileTemplate'@ from a @(FilePath, Text)@ pair.
Both the @FilePath@ and @Text@ may contain mustache variables.
This function returns an error (within @'MonadIO'@) in the case that
@'Text.Mustache.compileMustacheText'@ fails to compile
either the 'fileNameTemplate' or 'fileContentsTemplate'.
For example, the following code:
@
compileFileTemplate ("{{prjId}}.md", "{{prjId}}")
@
produces the following template:
@
MkFileTemplate
{ fileNameTemplate = Template
{ templateActual = PName
{ unPName = "Filename" }
, templateCache = fromList
[
( PName
{ unPName = "Filename" }
,
[ EscapedVar
( Key
{ unKey = [ "prjId" ] }
)
, TextBlock ".md"
]
)
]
}
, fileContentsTemplate = Template
{ templateActual = PName
{ unPName = "Contents" }
, templateCache = fromList
[
( PName
{ unPName = "Contents" }
,
[ EscapedVar
( Key
{ unKey = [ "prjId" ] }
)
]
)
]
}
}
@
-}
compileFileTemplate :: MonadIO m => (FilePath, Text) -> m FileTemplate
compileFileTemplate x =
mkFileTemplate <$> (mkTemplates . bimap
(compileMustacheText "Filename" . pack)
(compileMustacheText "Contents") $ x)
where
mkTemplates = \case
(Right fn, Right ctnts) -> pure (fn, ctnts)
(Left e, _) -> liftIO $ throwIO $ MustacheParserException e
(_ , Left e) -> liftIO $ throwIO $ MustacheParserException e
mkFileTemplate = uncurry $ MkFileTemplate (fst x)
{-|
Generate all @'FileTemplate'@s for a @'ProjectTemplate'@.
-}
compileProjectTemplate :: MonadIO m => [(FilePath, Text)] -> m ProjectTemplate
compileProjectTemplate x =
MkProjectTemplate . Set.fromList <$> traverse compileFileTemplate x