module Wobsurv.Util.Mustache.Renderer where import BasePrelude import Control.Monad.Trans.Class import Control.Monad.Trans.Reader import Control.Monad.Trans.Except import Control.Monad.Trans.State import qualified Data.ByteString import qualified Data.HashMap.Strict as HashMap import qualified Data.Text import qualified Data.Text.Lazy import qualified Filesystem import qualified Filesystem.Path.CurrentOS as Path import qualified Text.Hastache import qualified Text.Hastache.Context type BS = Data.ByteString.ByteString type Text = Data.Text.Text type LazyText = Data.Text.Lazy.Text type Path = Path.FilePath -- | -- A fast Hastache renderer, -- which preloads all templates instead of reading them during each rendering. type Renderer = TemplatesCache -- | -- Mappings from template names to their contents -- stored in RAM for faster processing. -- -- Supposed to be loaded once during the initialization of the app. type TemplatesCache = HashMap.HashMap TemplateName Text type TemplateName = Text type Context = HashMap.HashMap Text Value data Value where Variable :: Text.Hastache.MuVar a => a -> Value Contexts :: [Context] -> Value -- | -- Initialize a renderer by loading all templates from the specified folder. new :: Path -> IO Renderer new path = initTemplatesCache where initTemplatesCache = flip execStateT mempty $ do subpaths <- lift $ Filesystem.listDirectory path forM_ subpaths $ \subpath -> do contents <- lift $ Filesystem.readTextFile subpath modify $ HashMap.insert (fromString $ Path.encodeString $ Path.basename subpath) contents -- | -- Workarounds over Hastache API to enable it with caching. render :: (Data model) => model -> TemplateName -> Renderer -> Maybe LazyText render model name cache = do template <- HashMap.lookup name cache return $ unsafePerformIO $ Text.Hastache.hastacheStr config template context where config = Text.Hastache.MuConfig Text.Hastache.htmlEscape Nothing Nothing getTemplate where getTemplate s = return $ HashMap.lookup (fromString s) cache context = Text.Hastache.Context.mkGenericContext model