| |||||||||||||||||||||||||||||
| |||||||||||||||||||||||||||||
| |||||||||||||||||||||||||||||
Description | |||||||||||||||||||||||||||||
This module contains the core definitions for the Heist template system. The Heist template system is based on XML/xhtml. It allows you to build custom XML-based markup languages. With Heist you can define your own domain-specific XML tags implemented with Haskell and use them in your templates. The most important concept in Heist is the Splice. Splices can be thought of as functions that transform a node into a list of nodes. Heist then substitutes the resulting list of nodes into your template in place of the input node. Splice is implemented as a type synonym type Splice m = TemplateMonad m [Node], and TemplateMonad has a function getParamNode that lets you get the input node. Suppose you have a place on your page where you want to display a link with the text "Logout username" if the user is currently logged in or a link to the login page if no user is logged in. Assume you have a function getUser :: MyAppMonad (Maybe ByteString) that gets the current user. You can implement this functionality with a Splice as follows: import Data.ByteString.Char8 (ByteString) import qualified Data.ByteString.Char8 as B import qualified Text.XML.Expat.Tree as X import Text.Templating.Heist link :: ByteString -> ByteString -> Node link target text = X.Element "a" [("href", target)] [X.Text text] loginLink :: Node loginLink = link "/login" "Login" logoutLink :: ByteString -> Node logoutLink user = link "/logout" (B.append "Logout " user) loginLogoutSplice :: Splice MyAppMonad loginLogoutSplice = do user <- lift getUser return $ [maybe loginLink logoutLink user] Next, you need to bind that splice to an XML tag. Heist stores information about splices and templates in the TemplateState data structure. The following code demonstrates how this splice would be used. mySplices = [ ("loginLogout", loginLogoutSplice) ] main = do ets <- loadTemplates "templates" $ foldr (uncurry bindSplice) emptyTemplateState mySplices let ts = either error id ets t <- runMyAppMonad $ renderTemplate ts "index" print $ maybe "Page not found" id t Here we build up our TemplateState by starting with emptyTemplateState and applying bindSplice for all the splices we want to add. Then we pass this to loadTemplates our final TemplateState wrapped in an Either to handle errors. Then we use this TemplateState to render our templates. | |||||||||||||||||||||||||||||
Synopsis | |||||||||||||||||||||||||||||
Types | |||||||||||||||||||||||||||||
type Node = Node ByteString ByteString | |||||||||||||||||||||||||||||
Heist templates are XML documents. The hexpat library is polymorphic over the type of strings, so here we define a Node alias to fix the string types of the tag names and tag bodies to ByteString. | |||||||||||||||||||||||||||||
type Template = [Node] | |||||||||||||||||||||||||||||
A Template is a forest of XML nodes. Here we deviate from the single root node constraint of well-formed XML because we want to allow templates to contain fragments of a document that may not have a single root. | |||||||||||||||||||||||||||||
type Splice m = TemplateMonad m Template | |||||||||||||||||||||||||||||
A Splice is a TemplateMonad computation that returns a Template. | |||||||||||||||||||||||||||||
data TemplateMonad m a | |||||||||||||||||||||||||||||
| |||||||||||||||||||||||||||||
data TemplateState m | |||||||||||||||||||||||||||||
| |||||||||||||||||||||||||||||
Functions and declarations on TemplateState values | |||||||||||||||||||||||||||||
addTemplate :: Monad m => ByteString -> Template -> TemplateState m -> TemplateState m | |||||||||||||||||||||||||||||
Adds a template to the template state. | |||||||||||||||||||||||||||||
emptyTemplateState :: MonadIO m => TemplateState m | |||||||||||||||||||||||||||||
An empty template state, with Heist's default splices (<apply>, <bind>, <ignore>, and <markdown>) mapped. The static tag is not mapped here because it must be mapped manually in your application. | |||||||||||||||||||||||||||||
bindSplice | |||||||||||||||||||||||||||||
| |||||||||||||||||||||||||||||
bindSplices | |||||||||||||||||||||||||||||
| |||||||||||||||||||||||||||||
lookupSplice :: Monad m => ByteString -> TemplateState m -> Maybe (Splice m) | |||||||||||||||||||||||||||||
Convenience function for looking up a splice. | |||||||||||||||||||||||||||||
setTemplates :: Monad m => TemplateMap -> TemplateState m -> TemplateState m | |||||||||||||||||||||||||||||
Sets the templateMap in a TemplateState. | |||||||||||||||||||||||||||||
loadTemplates :: Monad m => FilePath -> TemplateState m -> IO (Either String (TemplateState m)) | |||||||||||||||||||||||||||||
Traverses the specified directory structure and builds a TemplateState by loading all the files with a .tpl extension. | |||||||||||||||||||||||||||||
hasTemplate :: Monad m => ByteString -> TemplateState m -> Bool | |||||||||||||||||||||||||||||
Returns True if the given template can be found in the template state. | |||||||||||||||||||||||||||||
Hook functions | |||||||||||||||||||||||||||||
Heist hooks allow you to modify templates when they are loaded and before and after they are run. Every time you call one of the addAbcHook functions the hook is added to onto the processing pipeline. The hooks processes the template in the order that they were added to the TemplateState. The pre-run and post-run hooks are run before and after every template is run/rendered. You should be careful what code you put in these hooks because it can significantly affect the performance of your site. | |||||||||||||||||||||||||||||
addOnLoadHook :: Monad m => (Template -> IO Template) -> TemplateState m -> TemplateState m | |||||||||||||||||||||||||||||
Adds an on-load hook to a TemplateState. | |||||||||||||||||||||||||||||
addPreRunHook :: Monad m => (Template -> m Template) -> TemplateState m -> TemplateState m | |||||||||||||||||||||||||||||
Adds a pre-run hook to a TemplateState. | |||||||||||||||||||||||||||||
addPostRunHook :: Monad m => (Template -> m Template) -> TemplateState m -> TemplateState m | |||||||||||||||||||||||||||||
Adds a post-run hook to a TemplateState. | |||||||||||||||||||||||||||||
TemplateMonad functions | |||||||||||||||||||||||||||||
stopRecursion :: Monad m => TemplateMonad m () | |||||||||||||||||||||||||||||
Stops the recursive processing of splices. Consider the following example: <foo> <bar> ... </bar> </foo> Assume that "foo" is bound to a splice procedure. Running the foo splice will result in a list of nodes L. Normally foo will recursively scan L for splices and run them. If foo calls stopRecursion, L will be included in the output verbatim without running any splices. | |||||||||||||||||||||||||||||
getParamNode :: Monad m => TemplateMonad m Node | |||||||||||||||||||||||||||||
Gets the node currently being processed. <speech author="Shakespeare"> To sleep, perchance to dream. </speech> When you call getParamNode inside the code for the speech splice, it returns the Node for the speech tag and its children. getParamNode >>= getChildren returns a list containing one Text node containing part of Hamlet's speech. getParamNode >>= getAttribute "author" would return Just Shakespeare. | |||||||||||||||||||||||||||||
runNodeList :: Monad m => [Node] -> Splice m | |||||||||||||||||||||||||||||
Performs splice processing on a list of nodes. | |||||||||||||||||||||||||||||
getContext :: Monad m => TemplateMonad m TPath | |||||||||||||||||||||||||||||
Gets the current context | |||||||||||||||||||||||||||||
localParamNode :: Monad m => (Node -> Node) -> TemplateMonad m a -> TemplateMonad m a | |||||||||||||||||||||||||||||
TemplateMonad's local. | |||||||||||||||||||||||||||||
getsTS :: Monad m => (TemplateState m -> r) -> TemplateMonad m r | |||||||||||||||||||||||||||||
TemplateMonad's gets. | |||||||||||||||||||||||||||||
getTS :: Monad m => TemplateMonad m (TemplateState m) | |||||||||||||||||||||||||||||
TemplateMonad's get. | |||||||||||||||||||||||||||||
putTS :: Monad m => TemplateState m -> TemplateMonad m () | |||||||||||||||||||||||||||||
TemplateMonad's put. | |||||||||||||||||||||||||||||
modifyTS :: Monad m => (TemplateState m -> TemplateState m) -> TemplateMonad m () | |||||||||||||||||||||||||||||
TemplateMonad's modify. | |||||||||||||||||||||||||||||
restoreTS :: Monad m => TemplateState m -> TemplateMonad m () | |||||||||||||||||||||||||||||
Restores the components of TemplateState that can get modified in template calls. You should use this function instead of putTS to restore an old state. Thas was needed because doctypes needs to be in a global scope as opposed to the template call local scope of state items such as recursionDepth, curContext, and spliceMap. | |||||||||||||||||||||||||||||
Functions for running splices and templates | |||||||||||||||||||||||||||||
evalTemplate :: Monad m => ByteString -> TemplateMonad m (Maybe Template) | |||||||||||||||||||||||||||||
Looks up a template name evaluates it by calling runNodeList. | |||||||||||||||||||||||||||||
callTemplate | |||||||||||||||||||||||||||||
| |||||||||||||||||||||||||||||
renderTemplate :: Monad m => TemplateState m -> ByteString -> m (Maybe ByteString) | |||||||||||||||||||||||||||||
Renders a template from the specified TemplateState. | |||||||||||||||||||||||||||||
bindStrings :: Monad m => [(ByteString, ByteString)] -> TemplateState m -> TemplateState m | |||||||||||||||||||||||||||||
Binds a list of constant string splices. | |||||||||||||||||||||||||||||
bindString :: Monad m => ByteString -> ByteString -> TemplateState m -> TemplateState m | |||||||||||||||||||||||||||||
Binds a single constant string splice. | |||||||||||||||||||||||||||||
Misc functions | |||||||||||||||||||||||||||||
getDoc :: String -> IO (Either String InternalTemplate) | |||||||||||||||||||||||||||||
Reads an XML document from disk. | |||||||||||||||||||||||||||||
parseDoc :: ByteString -> IO (Either String (Maybe ByteString, [Node])) | |||||||||||||||||||||||||||||
Turns an in-memory XML/XHTML bytestring into a (doctype,'[Node]') pair. | |||||||||||||||||||||||||||||
bindStaticTag :: MonadIO m => TemplateState m -> IO (TemplateState m, StaticTagState) | |||||||||||||||||||||||||||||
Modifies a TemplateState to include a "static" tag. The static tag is not bound automatically with the other default Heist tags. This is because this function also returns StaticTagState, so the user will be able to clear it with the clearStaticTagCache function. | |||||||||||||||||||||||||||||
Produced by Haddock version 2.7.2 |