/vendor/heist-0.7.0.1/src/Text/Templating/Heist.hs

https://github.com/roman/noomii-crawler · Haskell · 190 lines · 74 code · 20 blank · 96 comment · 0 complexity · 691b7965d1deaea6d493ff86e4d41c4c MD5 · raw file

  1. {-# LANGUAGE GeneralizedNewtypeDeriving #-}
  2. {-|
  3. This module contains the core definitions for the Heist template system.
  4. The Heist template system is based on HTML and XML. It allows you to build
  5. custom HTML and XML based markup languages. With Heist you can define your
  6. own domain-specific HTML and XML tags implemented with Haskell and use them
  7. in your templates.
  8. The most important concept in Heist is the 'Splice'. Splices can be thought
  9. of as functions that transform a node into a list of nodes. Heist then
  10. substitutes the resulting list of nodes into your template in place of the
  11. input node. 'Splice' is implemented as a type synonym @type Splice m =
  12. HeistT m [Node]@, and 'HeistT' has a function 'getParamNode'
  13. that lets you get the input node.
  14. Suppose you have a place on your page where you want to display a link with
  15. the text \"Logout username\" if the user is currently logged in or a link to
  16. the login page if no user is logged in. Assume you have a function
  17. @getUser :: MyAppMonad (Maybe Text)@ that gets the current user.
  18. You can implement this functionality with a 'Splice' as follows:
  19. > import Blaze.ByteString.Builder
  20. > import Data.ByteString.Char8 (ByteString)
  21. > import qualified Data.ByteString.Char8 as B
  22. > import Data.Text (Text)
  23. > import qualified Data.Text as T
  24. > import qualified Text.XmlHtml as X
  25. >
  26. > import Text.Templating.Heist
  27. >
  28. > link :: Text -> Text -> X.Node
  29. > link target text = X.Element "a" [("href", target)] [X.TextNode text]
  30. >
  31. > loginLink :: X.Node
  32. > loginLink = link "/login" "Login"
  33. >
  34. > logoutLink :: Text -> X.Node
  35. > logoutLink user = link "/logout" (T.append "Logout " user)
  36. >
  37. > loginLogoutSplice :: Splice MyAppMonad
  38. > loginLogoutSplice = do
  39. > user <- lift getUser
  40. > return [maybe loginLink logoutLink user]
  41. >
  42. Next, you need to bind that splice to a tag. Heist stores information
  43. about splices and templates in the 'HeistState' data structure. The
  44. following code demonstrates how this splice would be used.
  45. > mySplices = [ ("loginLogout", loginLogoutSplice) ]
  46. >
  47. > main = do
  48. > ets <- loadTemplates "templates" $
  49. > bindSplices mySplices emptyHeistState
  50. > let ts = either error id ets
  51. > t <- runMyAppMonad $ renderTemplate ts "index"
  52. > print $ maybe "Page not found" (toByteString . fst) t
  53. Here we build up our 'HeistState' by starting with emptyHeistState and
  54. applying bindSplice for all the splices we want to add. Then we pass this
  55. to loadTemplates our final 'HeistState' wrapped in an Either to handle
  56. errors. Then we use this 'HeistState' to render our templates.
  57. -}
  58. module Text.Templating.Heist
  59. (
  60. -- * Types
  61. Template
  62. , MIMEType
  63. , Splice
  64. , TemplateMonad
  65. , HeistT
  66. , HeistState
  67. , TemplateState
  68. , templateNames
  69. , spliceNames
  70. -- * Functions and declarations on HeistState values
  71. , addTemplate
  72. , addXMLTemplate
  73. , emptyTemplateState
  74. , defaultHeistState
  75. , bindSplice
  76. , bindSplices
  77. , lookupSplice
  78. , setTemplates
  79. , loadTemplates
  80. , hasTemplate
  81. , addTemplatePathPrefix
  82. -- * Hook functions
  83. -- $hookDoc
  84. , addOnLoadHook
  85. , addPreRunHook
  86. , addPostRunHook
  87. -- * HeistT functions
  88. , stopRecursion
  89. , getParamNode
  90. , runNodeList
  91. , getContext
  92. , getTemplateFilePath
  93. , localParamNode
  94. , getsTS
  95. , getTS
  96. , putTS
  97. , modifyTS
  98. , restoreTS
  99. , localTS
  100. -- * Functions for running splices and templates
  101. , evalTemplate
  102. , callTemplate
  103. , callTemplateWithText
  104. , renderTemplate
  105. , renderWithArgs
  106. , bindStrings
  107. , bindString
  108. -- * Functions for creating splices
  109. , textSplice
  110. , runChildren
  111. , runChildrenWith
  112. , runChildrenWithTrans
  113. , runChildrenWithTemplates
  114. , runChildrenWithText
  115. , mapSplices
  116. -- * Misc functions
  117. , getDoc
  118. , getXMLDoc
  119. , mkCacheTag
  120. -- * Temporary functions
  121. , useOldAttributeSyntax
  122. ) where
  123. import Control.Monad.Trans
  124. import qualified Data.Map as Map
  125. import Text.Templating.Heist.Internal
  126. import Text.Templating.Heist.Splices
  127. import Text.Templating.Heist.Types
  128. ------------------------------------------------------------------------------
  129. -- | The default set of built-in splices.
  130. defaultSpliceMap :: MonadIO m => SpliceMap m
  131. defaultSpliceMap = Map.fromList
  132. [(applyTag, applyImpl)
  133. ,(bindTag, bindImpl)
  134. ,(ignoreTag, ignoreImpl)
  135. ,(markdownTag, markdownSplice)
  136. ]
  137. ------------------------------------------------------------------------------
  138. -- | An empty heist state, with Heist's default splices (@\<apply\>@,
  139. -- @\<bind\>@, @\<ignore\>@, and @\<markdown\>@) mapped. The cache tag is
  140. -- not mapped here because it must be mapped manually in your application.
  141. defaultHeistState :: MonadIO m => HeistState m
  142. defaultHeistState =
  143. HeistState (defaultSpliceMap) Map.empty True [] 0
  144. return return return [] Nothing False
  145. {-# DEPRECATED emptyTemplateState "NOTICE: The name TemplateState is changing to HeistState. Use defaultHeistState instead of emptyTemplateState." #-}
  146. ------------------------------------------------------------------------------
  147. -- | An empty template state, with Heist's default splices (@\<apply\>@,
  148. -- @\<bind\>@, @\<ignore\>@, and @\<markdown\>@) mapped. The static tag is
  149. -- not mapped here because it must be mapped manually in your application.
  150. emptyTemplateState :: MonadIO m => HeistState m
  151. emptyTemplateState = defaultHeistState
  152. -- $hookDoc
  153. -- Heist hooks allow you to modify templates when they are loaded and before
  154. -- and after they are run. Every time you call one of the addAbcHook
  155. -- functions the hook is added to onto the processing pipeline. The hooks
  156. -- processes the template in the order that they were added to the
  157. -- HeistState.
  158. --
  159. -- The pre-run and post-run hooks are run before and after every template is
  160. -- run/rendered. You should be careful what code you put in these hooks
  161. -- because it can significantly affect the performance of your site.