module Text.Mustache.Compile
( compileMustacheDir
, getMustacheFilesInDir
, compileMustacheFile
, compileMustacheText )
where
import Control.Exception
import Control.Monad.Except
import Data.Text (Text)
import Data.Void
import System.Directory
import Text.Megaparsec
import Text.Mustache.Parser
import Text.Mustache.Type
import qualified Data.Map as M
import qualified Data.Text as T
import qualified Data.Text.IO as T
import qualified System.FilePath as F
#if !MIN_VERSION_base(4,8,0)
import Control.Applicative
#endif
compileMustacheDir :: MonadIO m
=> PName
-> FilePath
-> m Template
compileMustacheDir pname path =
getMustacheFilesInDir path >>=
liftM selectKey . foldM f (Template undefined M.empty)
where
selectKey t = t { templateActual = pname }
f (Template _ old) fp = do
Template _ new <- compileMustacheFile fp
return (Template undefined (M.union new old))
getMustacheFilesInDir :: MonadIO m
=> FilePath
-> m [FilePath]
getMustacheFilesInDir path = liftIO $
getDirectoryContents path >>=
filterM isMustacheFile . fmap (F.combine path) >>=
mapM makeAbsolute
compileMustacheFile :: MonadIO m
=> FilePath
-> m Template
compileMustacheFile path = liftIO $ do
input <- T.readFile path
withException input (compile input)
where
pname = pathToPName path
compile = fmap (Template pname . M.singleton pname) . parseMustache path
compileMustacheText
:: PName
-> Text
-> Either (ParseError Char Void) Template
compileMustacheText pname txt =
Template pname . M.singleton pname <$> parseMustache "" txt
isMustacheFile :: FilePath -> IO Bool
isMustacheFile path = do
exists <- doesFileExist path
let rightExtension = F.takeExtension path == ".mustache"
return (exists && rightExtension)
pathToPName :: FilePath -> PName
pathToPName = PName . T.pack . F.takeBaseName
withException
:: Text
-> Either (ParseError Char Void) Template
-> IO Template
withException input = either (throwIO . MustacheParserException input) return