{-# LANGUAGE CPP               #-}

module Heist.Splices
  ( ifISplice
  , ifCSplice
  , ifElseISplice
  , ifElseCSplice
  , module Heist.Splices.Apply
  , module Heist.Splices.Bind
  , module Heist.Splices.Cache
  , module Heist.Splices.Html
  , module Heist.Splices.Ignore
  , module Heist.Splices.Markdown
  ) where

#if !MIN_VERSION_base(4,8,0)
import           Data.Monoid (Monoid(..))
#endif

import qualified Heist.Compiled as C
import qualified Heist.Interpreted as I
import           Heist.Splices.Apply
import           Heist.Splices.Bind
import           Heist.Splices.Cache
import           Heist.Splices.Html
import           Heist.Splices.Ignore
import           Heist.Splices.Markdown
import           Heist.Internal.Types.HeistState
import qualified Text.XmlHtml as X

------------------------------------------------------------------------------
-- | Run the splice contents if given condition is True, make splice disappear
-- if not.
ifISplice :: Monad m => Bool -> I.Splice m
ifISplice :: Bool -> Splice m
ifISplice Bool
cond =
    case Bool
cond of
      Bool
False -> [Node] -> Splice m
forall (m :: * -> *) a. Monad m => a -> m a
return []
      Bool
True -> Splice m
forall (n :: * -> *). Monad n => Splice n
I.runChildren


------------------------------------------------------------------------------
-- | Function for constructing if splices that use a runtime predicate
-- function to determine whether the node's children should be rendered.
ifCSplice :: Monad m
          => (t -> Bool)
          -> RuntimeSplice m t
          -> C.Splice m
ifCSplice :: (t -> Bool) -> RuntimeSplice m t -> Splice m
ifCSplice t -> Bool
predicate RuntimeSplice m t
runtime = do
    DList (Chunk m)
chunks <- Splice m
forall (n :: * -> *). Monad n => Splice n
C.runChildren
    DList (Chunk m) -> Splice m
forall (m :: * -> *) a. Monad m => a -> m a
return (DList (Chunk m) -> Splice m) -> DList (Chunk m) -> Splice m
forall a b. (a -> b) -> a -> b
$ RuntimeSplice m Builder -> DList (Chunk m)
forall (n :: * -> *). RuntimeSplice n Builder -> DList (Chunk n)
C.yieldRuntime (RuntimeSplice m Builder -> DList (Chunk m))
-> RuntimeSplice m Builder -> DList (Chunk m)
forall a b. (a -> b) -> a -> b
$ do
        t
a <- RuntimeSplice m t
runtime
        if t -> Bool
predicate t
a
          then
            DList (Chunk m) -> RuntimeSplice m Builder
forall (n :: * -> *).
Monad n =>
DList (Chunk n) -> RuntimeSplice n Builder
C.codeGen DList (Chunk m)
chunks
          else
            Builder -> RuntimeSplice m Builder
forall (m :: * -> *) a. Monad m => a -> m a
return Builder
forall a. Monoid a => a
mempty


------------------------------------------------------------------------------
-- | Implements an if\/then\/else conditional splice.  It splits its children
-- around the \<else\/\> element to get the markup to be used for the two cases.
ifElseISplice :: Monad m => Bool -> I.Splice m
ifElseISplice :: Bool -> Splice m
ifElseISplice Bool
cond = HeistT m m Node
forall (m :: * -> *) (n :: * -> *). Monad m => HeistT n m Node
getParamNode HeistT m m Node -> (Node -> Splice m) -> Splice m
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= ([Node] -> Splice m
forall (n :: * -> *). Monad n => [Node] -> Splice n
rewrite ([Node] -> Splice m) -> (Node -> [Node]) -> Node -> Splice m
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Node -> [Node]
X.childNodes)
  where
    rewrite :: [Node] -> Splice n
rewrite [Node]
nodes = 
      let ([Node]
ns, [Node]
ns') = (Node -> Bool) -> [Node] -> ([Node], [Node])
forall a. (a -> Bool) -> [a] -> ([a], [a])
break (\Node
n -> Node -> Maybe Text
X.tagName Node
nMaybe Text -> Maybe Text -> Bool
forall a. Eq a => a -> a -> Bool
==Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"else") [Node]
nodes
      in [Node] -> Splice n
forall (n :: * -> *). Monad n => [Node] -> Splice n
I.runNodeList ([Node] -> Splice n) -> [Node] -> Splice n
forall a b. (a -> b) -> a -> b
$ if Bool
cond then [Node]
ns else (Int -> [Node] -> [Node]
forall a. Int -> [a] -> [a]
drop Int
1 [Node]
ns') 


------------------------------------------------------------------------------
-- | Implements an if\/then\/else conditional splice.  It splits its children
-- around the \<else\/\> element to get the markup to be used for the two cases.
ifElseCSplice :: Monad m => Bool -> C.Splice m
ifElseCSplice :: Bool -> Splice m
ifElseCSplice Bool
cond = HeistT m IO Node
forall (m :: * -> *) (n :: * -> *). Monad m => HeistT n m Node
getParamNode HeistT m IO Node -> (Node -> Splice m) -> Splice m
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= ([Node] -> Splice m
forall (n :: * -> *). Monad n => [Node] -> Splice n
rewrite ([Node] -> Splice m) -> (Node -> [Node]) -> Node -> Splice m
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Node -> [Node]
X.childNodes)
  where rewrite :: [Node] -> Splice n
rewrite [Node]
nodes = 
          let ([Node]
ns, [Node]
ns') = (Node -> Bool) -> [Node] -> ([Node], [Node])
forall a. (a -> Bool) -> [a] -> ([a], [a])
break (\Node
n -> Node -> Maybe Text
X.tagName Node
nMaybe Text -> Maybe Text -> Bool
forall a. Eq a => a -> a -> Bool
==Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"else") [Node]
nodes
          in [Node] -> Splice n
forall (n :: * -> *). Monad n => [Node] -> Splice n
C.runNodeList ([Node] -> Splice n) -> [Node] -> Splice n
forall a b. (a -> b) -> a -> b
$ if Bool
cond then [Node]
ns else (Int -> [Node] -> [Node]
forall a. Int -> [a] -> [a]
drop Int
1 [Node]
ns')