packages feed

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