module Text.Mustache.Compile
( compileMustacheDir
, getMustacheFilesInDir
, compileMustacheFile
, compileMustacheText )
where
import Control.Monad.Catch (MonadThrow (..))
import Control.Monad.Except
import Data.Text.Lazy (Text)
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.Lazy.IO as TL
import qualified System.FilePath as F
#if !MIN_VERSION_base(4,8,0)
import Control.Applicative ((<$>))
#endif
compileMustacheDir :: (MonadIO m, MonadThrow 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 (liftIO . makeAbsolute)
compileMustacheFile :: (MonadIO m, MonadThrow m)
=> FilePath
-> m Template
compileMustacheFile path =
liftIO (TL.readFile path) >>= withException . compile
where
pname = pathToPName path
compile = fmap (Template pname . M.singleton pname) . parseMustache path
compileMustacheText
:: PName
-> Text
-> Either (ParseError Char Dec) Template
compileMustacheText pname txt =
Template pname . M.singleton pname <$> parseMustache "" txt
isMustacheFile :: MonadIO m => FilePath -> m Bool
isMustacheFile path = do
exists <- liftIO (doesFileExist path)
let rightExtension = F.takeExtension path == ".mustache"
return (exists && rightExtension)
pathToPName :: FilePath -> PName
pathToPName = PName . T.pack . F.takeBaseName
withException :: MonadThrow m
=> Either (ParseError Char Dec) Template
-> m Template
withException = either (throwM . MustacheParserException) return