module Text.Yate.Engine ( renderTemplate ) where import Control.Monad import Control.Applicative import Data.Monoid import qualified Data.HashMap.Strict as M import qualified Data.Text.Lazy as TL import qualified Data.Vector as V import Text.Yate.Engine.Internal import Text.Yate.Types renderTemplate :: ToYate a => Template a -> a -> Either String TL.Text renderTemplate template dat = let val = toYate dat in go template val val where go :: Template a -> YateValue -> YateValue -> Either String TL.Text go tpl main current = case tpl of Content txt -> return txt Variable path -> showValue <$> resolvePath path main current If path yes no -> case valueToBoolean <$> resolvePath path main current of Left _ -> go no main current Right b -> go (if b then yes else no) main current For name path tpl' -> do list <- resolvePath path main current case list of List values -> do let step acc value = do main' <- case main of Object m -> return $ Object $ M.insert name value m _ -> Left "main value is not an object" (acc <>) <$> go tpl' main' current V.foldM step "" values _ -> Left $ "encountered non-list value on a for statement: " ++ show path In path tpl' -> do current' <- resolvePath path main current go tpl' main current' Parts tpls -> foldM (\acc tpl' -> (acc <>) <$> go tpl' main current) "" tpls