module Text.Mustache.Compile
( compileMustacheDir,
compileMustacheDir',
getMustacheFilesInDir,
getMustacheFilesInDir',
isMustacheFile,
compileMustacheFile,
compileMustacheText,
)
where
import Control.Exception
import Control.Monad (filterM, foldM)
import Control.Monad.IO.Class (MonadIO (..))
import qualified Data.Map as M
import Data.Text (Text)
import qualified Data.Text as T
import qualified Data.Text.IO as T
import Data.Void
import System.Directory
import qualified System.FilePath as F
import Text.Megaparsec
import Text.Mustache.Parser
import Text.Mustache.Type
compileMustacheDir ::
MonadIO m =>
PName ->
FilePath ->
m Template
compileMustacheDir :: PName -> FilePath -> m Template
compileMustacheDir = (FilePath -> Bool) -> PName -> FilePath -> m Template
forall (m :: * -> *).
MonadIO m =>
(FilePath -> Bool) -> PName -> FilePath -> m Template
compileMustacheDir' FilePath -> Bool
isMustacheFile
compileMustacheDir' ::
MonadIO m =>
(FilePath -> Bool) ->
PName ->
FilePath ->
m Template
compileMustacheDir' :: (FilePath -> Bool) -> PName -> FilePath -> m Template
compileMustacheDir' FilePath -> Bool
predicate PName
pname FilePath
path =
(FilePath -> Bool) -> FilePath -> m [FilePath]
forall (m :: * -> *).
MonadIO m =>
(FilePath -> Bool) -> FilePath -> m [FilePath]
getMustacheFilesInDir' FilePath -> Bool
predicate FilePath
path
m [FilePath] -> ([FilePath] -> m Template) -> m Template
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (Template -> Template) -> m Template -> m Template
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Template -> Template
selectKey (m Template -> m Template)
-> ([FilePath] -> m Template) -> [FilePath] -> m Template
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Template -> FilePath -> m Template)
-> Template -> [FilePath] -> m Template
forall (t :: * -> *) (m :: * -> *) b a.
(Foldable t, Monad m) =>
(b -> a -> m b) -> b -> t a -> m b
foldM Template -> FilePath -> m Template
forall (m :: * -> *).
MonadIO m =>
Template -> FilePath -> m Template
f (PName -> Map PName [Node] -> Template
Template PName
forall a. HasCallStack => a
undefined Map PName [Node]
forall k a. Map k a
M.empty)
where
selectKey :: Template -> Template
selectKey Template
t = Template
t {templateActual :: PName
templateActual = PName
pname}
f :: Template -> FilePath -> m Template
f (Template PName
_ Map PName [Node]
old) FilePath
fp = do
Template PName
_ Map PName [Node]
new <- FilePath -> m Template
forall (m :: * -> *). MonadIO m => FilePath -> m Template
compileMustacheFile FilePath
fp
Template -> m Template
forall (m :: * -> *) a. Monad m => a -> m a
return (PName -> Map PName [Node] -> Template
Template PName
forall a. HasCallStack => a
undefined (Map PName [Node] -> Map PName [Node] -> Map PName [Node]
forall k a. Ord k => Map k a -> Map k a -> Map k a
M.union Map PName [Node]
new Map PName [Node]
old))
getMustacheFilesInDir ::
MonadIO m =>
FilePath ->
m [FilePath]
getMustacheFilesInDir :: FilePath -> m [FilePath]
getMustacheFilesInDir = (FilePath -> Bool) -> FilePath -> m [FilePath]
forall (m :: * -> *).
MonadIO m =>
(FilePath -> Bool) -> FilePath -> m [FilePath]
getMustacheFilesInDir' FilePath -> Bool
isMustacheFile
getMustacheFilesInDir' ::
MonadIO m =>
(FilePath -> Bool) ->
FilePath ->
m [FilePath]
getMustacheFilesInDir' :: (FilePath -> Bool) -> FilePath -> m [FilePath]
getMustacheFilesInDir' FilePath -> Bool
predicate FilePath
path =
IO [FilePath] -> m [FilePath]
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO [FilePath] -> m [FilePath]) -> IO [FilePath] -> m [FilePath]
forall a b. (a -> b) -> a -> b
$
FilePath -> IO [FilePath]
getDirectoryContents FilePath
path
IO [FilePath] -> ([FilePath] -> IO [FilePath]) -> IO [FilePath]
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (FilePath -> IO Bool) -> [FilePath] -> IO [FilePath]
forall (m :: * -> *) a.
Applicative m =>
(a -> m Bool) -> [a] -> m [a]
filterM FilePath -> IO Bool
f ([FilePath] -> IO [FilePath])
-> ([FilePath] -> [FilePath]) -> [FilePath] -> IO [FilePath]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (FilePath -> FilePath) -> [FilePath] -> [FilePath]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (FilePath -> FilePath -> FilePath
F.combine FilePath
path)
IO [FilePath] -> ([FilePath] -> IO [FilePath]) -> IO [FilePath]
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (FilePath -> IO FilePath) -> [FilePath] -> IO [FilePath]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM FilePath -> IO FilePath
makeAbsolute
where
f :: FilePath -> IO Bool
f FilePath
p = (Bool -> Bool -> Bool
&& FilePath -> Bool
predicate FilePath
p) (Bool -> Bool) -> IO Bool -> IO Bool
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> FilePath -> IO Bool
doesFileExist FilePath
p
isMustacheFile :: FilePath -> Bool
isMustacheFile :: FilePath -> Bool
isMustacheFile FilePath
path = FilePath -> FilePath
F.takeExtension FilePath
path FilePath -> FilePath -> Bool
forall a. Eq a => a -> a -> Bool
== FilePath
".mustache"
compileMustacheFile ::
MonadIO m =>
FilePath ->
m Template
compileMustacheFile :: FilePath -> m Template
compileMustacheFile FilePath
path = IO Template -> m Template
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO Template -> m Template) -> IO Template -> m Template
forall a b. (a -> b) -> a -> b
$ do
Text
input <- FilePath -> IO Text
T.readFile FilePath
path
Either (ParseErrorBundle Text Void) Template -> IO Template
withException (Text -> Either (ParseErrorBundle Text Void) Template
compile Text
input)
where
pname :: PName
pname = FilePath -> PName
pathToPName FilePath
path
compile :: Text -> Either (ParseErrorBundle Text Void) Template
compile = ([Node] -> Template)
-> Either (ParseErrorBundle Text Void) [Node]
-> Either (ParseErrorBundle Text Void) Template
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (PName -> Map PName [Node] -> Template
Template PName
pname (Map PName [Node] -> Template)
-> ([Node] -> Map PName [Node]) -> [Node] -> Template
forall b c a. (b -> c) -> (a -> b) -> a -> c
. PName -> [Node] -> Map PName [Node]
forall k a. k -> a -> Map k a
M.singleton PName
pname) (Either (ParseErrorBundle Text Void) [Node]
-> Either (ParseErrorBundle Text Void) Template)
-> (Text -> Either (ParseErrorBundle Text Void) [Node])
-> Text
-> Either (ParseErrorBundle Text Void) Template
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> Text -> Either (ParseErrorBundle Text Void) [Node]
parseMustache FilePath
path
compileMustacheText ::
PName ->
Text ->
Either (ParseErrorBundle Text Void) Template
compileMustacheText :: PName -> Text -> Either (ParseErrorBundle Text Void) Template
compileMustacheText PName
pname Text
txt =
PName -> Map PName [Node] -> Template
Template PName
pname (Map PName [Node] -> Template)
-> ([Node] -> Map PName [Node]) -> [Node] -> Template
forall b c a. (b -> c) -> (a -> b) -> a -> c
. PName -> [Node] -> Map PName [Node]
forall k a. k -> a -> Map k a
M.singleton PName
pname ([Node] -> Template)
-> Either (ParseErrorBundle Text Void) [Node]
-> Either (ParseErrorBundle Text Void) Template
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> FilePath -> Text -> Either (ParseErrorBundle Text Void) [Node]
parseMustache FilePath
"" Text
txt
pathToPName :: FilePath -> PName
pathToPName :: FilePath -> PName
pathToPName = Text -> PName
PName (Text -> PName) -> (FilePath -> Text) -> FilePath -> PName
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> Text
T.pack (FilePath -> Text) -> (FilePath -> FilePath) -> FilePath -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> FilePath
F.takeBaseName
withException ::
Either (ParseErrorBundle Text Void) Template ->
IO Template
withException :: Either (ParseErrorBundle Text Void) Template -> IO Template
withException = (ParseErrorBundle Text Void -> IO Template)
-> (Template -> IO Template)
-> Either (ParseErrorBundle Text Void) Template
-> IO Template
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either (MustacheException -> IO Template
forall e a. Exception e => e -> IO a
throwIO (MustacheException -> IO Template)
-> (ParseErrorBundle Text Void -> MustacheException)
-> ParseErrorBundle Text Void
-> IO Template
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ParseErrorBundle Text Void -> MustacheException
MustacheParserException) Template -> IO Template
forall (m :: * -> *) a. Monad m => a -> m a
return