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