{-# LANGUAGE OverloadedStrings #-}
module Snap.Extras.SpliceUtils.Compiled
( utilSplices
, refererCSplice
, paramSplice
, scriptsSplice
, fancyLoopSplice
) where
import Blaze.ByteString.Builder.ByteString
import Control.Monad
import Control.Monad.Trans
import qualified Data.Map.Syntax as MS
import Data.Monoid
import qualified Data.Text as T
import qualified Data.Text.Encoding as T
import Heist
import Heist.Compiled
import Heist.Compiled.LowLevel
import Snap.Core
import qualified Snap.Extras.SpliceUtils.Interpreted as I
import Text.XmlHtml
import Text.XmlHtml.Cursor
utilSplices :: MonadSnap m => Splices (Splice m)
utilSplices = do
"rqparam" MS.## paramSplice
"refererLink" MS.## refererCSplice
refererCSplice :: MonadSnap m => Splice m
refererCSplice = return $ yieldRuntimeText $ return .
maybe "/" T.decodeUtf8 =<< lift (getsRequest (getHeader "Referer"))
paramSplice :: MonadSnap m => Splice m
paramSplice = do
node <- getParamNode
let mat = getAttribute "name" node
case mat of
Nothing -> error $ (T.unpack $ elementTag node) ++
" must have a 'name' attribute"
Just at -> return $ yieldRuntime $ do
val <- lift $ getParam $ T.encodeUtf8 at
return $ maybe mempty fromByteString val
scriptsSplice :: MonadIO m
=> FilePath
-> String
-> Splice m
scriptsSplice d prefix = runNodeList =<< I.scriptsSplice d prefix
fancyLoopSplice :: Monad n
=> Splices (RuntimeSplice n a -> Splice n)
-> RuntimeSplice n [a]
-> Splice n
fancyLoopSplice splices action = do
n <- getParamNode
p <- newEmptyPromise
let splices' = do
MS.mapV ($ getPromise p) splices
"prelude" MS.## return mempty
"interlude" MS.## return mempty
"postlude" MS.## return mempty
preChunks <- findNamedChild n "prelude"
interChunks <- findNamedChild n "interlude"
postChunks <- findNamedChild n "postlude"
itemChunks <- withLocalSplices splices' mempty runChildren
return $ yieldRuntime $ do
items <- action
case items of
[] -> return mempty
(i:is) -> do
pre <- codeGen preChunks
post <- codeGen postChunks
front <- putPromise p i >> codeGen itemChunks
body <- forM is $ \item -> do
putPromise p item
inter <- codeGen interChunks
res <- codeGen itemChunks
return $ inter <> res
return $ pre <> front <> mconcat body <> post
findNamedChild :: Monad n => Node -> T.Text -> Splice n
findNamedChild node name =
maybe (return mempty) (runNodeList . childNodes . current) $
findChild (\c -> tagName (current c) == Just name) $ fromNode node