{-# LANGUAGE BangPatterns #-} {-# LANGUAGE CPP #-} {-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE UndecidableInstances #-} {-| Internal types and accessors. There are no guarantees that heist will preserve backwards compatibility for symbols in this module. If you use them, no complaining when your code breaks. -} module Heist.Internal.Types ( module Heist.Internal.Types.HeistState , module Heist.Internal.Types ) where ------------------------------------------------------------------------------ import Data.HashMap.Strict (HashMap) import Data.Text (Text) #if !MIN_VERSION_base(4,8,0) import Control.Applicative #endif #if !MIN_VERSION_base(4,11,0) import Data.Semigroup #endif ------------------------------------------------------------------------------ import qualified Heist.Compiled.Internal as C import qualified Heist.Interpreted.Internal as I import Heist.Internal.Types.HeistState ------------------------------------------------------------------------------ ------------------------------------------------------------------------------ type TemplateRepo = HashMap TPath DocumentFile ------------------------------------------------------------------------------ -- | An IO action for getting a template repo from this location. By not just -- using a directory path here, we support templates loaded from a database, -- retrieved from the network, or anything else you can think of. type TemplateLocation = IO (Either [String] TemplateRepo) ------------------------------------------------------------------------------ -- | My lens creation function to avoid a dependency on lens. lens :: Functor f => (t1 -> t) -> (t1 -> a -> b) -> (t -> f a) -> t1 -> f b lens sa sbt afb s = sbt s <$> afb (sa s) ------------------------------------------------------------------------------ -- | The splices and templates Heist will use. To bind a splice simply -- include it in the appropriate place here. data SpliceConfig m = SpliceConfig { _scInterpretedSplices :: Splices (I.Splice m) -- ^ Interpreted splices are the splices that Heist has always had. -- They return a list of nodes and are processed at runtime. , _scLoadTimeSplices :: Splices (I.Splice IO) -- ^ Load time splices are like interpreted splices because they -- return a list of nodes. But they are like compiled splices because -- they are processed once at load time. All of Heist's built-in -- splices should be used as load time splices. , _scCompiledSplices :: Splices (C.Splice m) -- ^ Compiled splices return a DList of Chunks and are processed at -- load time to generate a runtime monad action that will be used to -- render the template. , _scAttributeSplices :: Splices (AttrSplice m) -- ^ Attribute splices are bound to attribute names and return a list -- of attributes. , _scTemplateLocations :: [TemplateLocation] -- ^ A list of all the locations that Heist should get its templates -- from. , _scCompiledTemplateFilter :: TPath -> Bool -- ^ Predicate function to control which templates to compile. Using -- templates filtered out with this is still possible via -- callTemplate. } ------------------------------------------------------------------------------ -- | Lens for interpreted splices -- :: Simple Lens (SpliceConfig m) (Splices (I.Splice m)) scInterpretedSplices :: Functor f => (Splices (I.Splice m) -> f (Splices (I.Splice m))) -> SpliceConfig m -> f (SpliceConfig m) scInterpretedSplices = lens _scInterpretedSplices setter where setter sc v = sc { _scInterpretedSplices = v } ------------------------------------------------------------------------------ -- | Lens for load time splices -- :: Simple Lens (SpliceConfig m) (Splices (I.Splice IO)) scLoadTimeSplices :: Functor f => (Splices (I.Splice IO) -> f (Splices (I.Splice IO))) -> SpliceConfig m -> f (SpliceConfig m) scLoadTimeSplices = lens _scLoadTimeSplices setter where setter sc v = sc { _scLoadTimeSplices = v } ------------------------------------------------------------------------------ -- | Lens for complied splices -- :: Simple Lens (SpliceConfig m) (Splices (C.Splice m)) scCompiledSplices :: Functor f => (Splices (C.Splice m) -> f (Splices (C.Splice m))) -> SpliceConfig m -> f (SpliceConfig m) scCompiledSplices = lens _scCompiledSplices setter where setter sc v = sc { _scCompiledSplices = v } ------------------------------------------------------------------------------ -- | Lens for attribute splices -- :: Simple Lens (SpliceConfig m) (Splices (AttrSplice m)) scAttributeSplices :: Functor f => (Splices (AttrSplice m) -> f (Splices (AttrSplice m))) -> SpliceConfig m -> f (SpliceConfig m) scAttributeSplices = lens _scAttributeSplices setter where setter sc v = sc { _scAttributeSplices = v } ------------------------------------------------------------------------------ -- | Lens for template locations -- :: Simple Lens (SpliceConfig m) [TemplateLocation] scTemplateLocations :: Functor f => ([TemplateLocation] -> f [TemplateLocation]) -> SpliceConfig m -> f (SpliceConfig m) scTemplateLocations = lens _scTemplateLocations setter where setter sc v = sc { _scTemplateLocations = v } ------------------------------------------------------------------------------ -- | Lens for compiled template filter -- :: Simple Lens (SpliceConfig m) (TBool -> Bool) scCompiledTemplateFilter :: Functor f => ((TPath -> Bool) -> f (TPath -> Bool)) -> SpliceConfig m -> f (SpliceConfig m) scCompiledTemplateFilter = lens _scCompiledTemplateFilter setter where setter sc v = sc { _scCompiledTemplateFilter = v } instance Semigroup (SpliceConfig m) where SpliceConfig a1 b1 c1 d1 e1 f1 <> SpliceConfig a2 b2 c2 d2 e2 f2 = SpliceConfig (a1 <> a2) (b1 <> b2) (c1 <> c2) (d1 <> d2) (e1 <> e2) (\x -> f1 x && f2 x) instance Monoid (SpliceConfig m) where mempty = SpliceConfig mempty mempty mempty mempty mempty (const True) #if !MIN_VERSION_base(4,11,0) mappend = (<>) #endif data HeistConfig m = HeistConfig { _hcSpliceConfig :: SpliceConfig m -- ^ Splices and templates , _hcNamespace :: Text -- ^ A namespace to use for all tags that are bound to splices. Use -- empty string for no namespace. , _hcErrorNotBound :: Bool -- ^ Whether to throw an error when a tag wih the heist namespace does -- not correspond to a bound splice. When not using a namespace, this -- flag is ignored. } ------------------------------------------------------------------------------ -- | Lens for the SpliceConfig -- :: Simple Lens (HeistConfig m) (SpliceConfig m) hcSpliceConfig :: Functor f => ((SpliceConfig m) -> f (SpliceConfig m)) -> HeistConfig m -> f (HeistConfig m) hcSpliceConfig = lens _hcSpliceConfig setter where setter hc v = hc { _hcSpliceConfig = v } ------------------------------------------------------------------------------ -- | Lens for the namespace -- :: Simple Lens (HeistConfig m) Text hcNamespace :: Functor f => (Text -> f Text) -> HeistConfig m -> f (HeistConfig m) hcNamespace = lens _hcNamespace setter where setter hc v = hc { _hcNamespace = v } ------------------------------------------------------------------------------ -- | Lens for the namespace error flag -- :: Simple Lens (HeistConfig m) Bool hcErrorNotBound :: Functor f => (Bool -> f Bool) -> HeistConfig m -> f (HeistConfig m) hcErrorNotBound = lens _hcErrorNotBound setter where setter hc v = hc { _hcErrorNotBound = v } ------------------------------------------------------------------------------ -- | Lens for interpreted splices -- :: Simple Lens (HeistConfig m) (Splices (I.Splice m)) hcInterpretedSplices :: Functor f => (Splices (I.Splice m) -> f (Splices (I.Splice m))) -> HeistConfig m -> f (HeistConfig m) hcInterpretedSplices = hcSpliceConfig . scInterpretedSplices ------------------------------------------------------------------------------ -- | Lens for load time splices -- :: Simple Lens (HeistConfig m) (Splices (I.Splice IO)) hcLoadTimeSplices :: Functor f => (Splices (I.Splice IO) -> f (Splices (I.Splice IO))) -> HeistConfig m -> f (HeistConfig m) hcLoadTimeSplices = hcSpliceConfig . scLoadTimeSplices ------------------------------------------------------------------------------ -- | Lens for compiled splices -- :: Simple Lens (HeistConfig m) (Splices (C.Splice m)) hcCompiledSplices :: Functor f => (Splices (C.Splice m) -> f (Splices (C.Splice m))) -> HeistConfig m -> f (HeistConfig m) hcCompiledSplices = hcSpliceConfig . scCompiledSplices ------------------------------------------------------------------------------ -- | Lens for attribute splices -- :: Simple Lens (HeistConfig m) (Splices (AttrSplice m)) hcAttributeSplices :: Functor f => (Splices (AttrSplice m) -> f (Splices (AttrSplice m))) -> HeistConfig m -> f (HeistConfig m) hcAttributeSplices = hcSpliceConfig . scAttributeSplices ------------------------------------------------------------------------------ -- | Lens for template locations -- :: Simple Lens (HeistConfig m) [TemplateLocation] hcTemplateLocations :: Functor f => ([TemplateLocation] -> f [TemplateLocation]) -> HeistConfig m -> f (HeistConfig m) hcTemplateLocations = hcSpliceConfig . scTemplateLocations ------------------------------------------------------------------------------ -- | Lens for compiled template filter -- :: Simple Lens (SpliceConfig m) (TBool -> Bool) hcCompiledTemplateFilter :: Functor f => ((TPath -> Bool) -> f (TPath -> Bool)) -> HeistConfig m -> f (HeistConfig m) hcCompiledTemplateFilter = hcSpliceConfig . scCompiledTemplateFilter