hastache-0.6.1: Haskell implementation of Mustache templates

Safe HaskellNone
LanguageHaskell98

Text.Hastache.Context

Description

Hastache context helpers

Synopsis

Documentation

mkStrContext :: Monad m => (String -> MuType m) -> MuContext m

Make Hastache context from String -> MuType function

mkStrContextM :: Monad m => (String -> m (MuType m)) -> MuContext m

Make Hastache context from monadic String -> MuType function

mkGenericContext :: (Monad m, Data a, Typeable m) => a -> MuContext m

Make Hastache context from Data.Data deriving type

Supported field types:

  • ()
  • String
  • Char
  • Double
  • Float
  • Int
  • Int8
  • Int16
  • Int32
  • Int64
  • Integer
  • Word
  • Word8
  • Word16
  • Word32
  • Word64
  • Data.ByteString.ByteString
  • Data.ByteString.Lazy.ByteString
  • Data.Text.Text
  • Data.Text.Lazy.Text
  • Bool
  • Version
  • Maybe a (where a is a supported datatype)
  • Either a b (where a and b are supported datatypes)
  • Data.Text.Text -> Data.Text.Text
  • Data.Text.Text -> Data.Text.Lazy.Text
  • Data.Text.Lazy.Text -> Data.Text.Lazy.Text
  • Data.ByteString.ByteString -> Data.ByteString.ByteString
  • String -> String
  • Data.ByteString.ByteString -> Data.ByteString.Lazy.ByteString
  • MonadIO m => Data.Text.Text -> m Data.Text.Text
  • MonadIO m => Data.Text.Text -> m Data.Text.Lazy.Text
  • MonadIO m => Data.Text.Lazy.Text -> m Data.Text.Lazy.Text
  • MonadIO m => Data.ByteString.ByteString -> m Data.ByteString.ByteString
  • MonadIO m => String -> m String
  • MonadIO m => Data.ByteString.ByteString -> m Data.ByteString.Lazy.ByteString

Example:

import Text.Hastache 
import Text.Hastache.Context
import qualified Data.Text as T
import qualified Data.Text.Lazy as TL
import qualified Data.Text.Lazy.IO as TL
import Data.Data 
import Data.Generics 
import Data.Char

data InternalData = InternalData {
    someField       :: String,
    anotherField    :: Int
    } deriving (Data, Typeable, Show)

data Example = Example {
    stringField             :: String,
    intField                :: Int,
    dataField               :: InternalData,
    simpleListField         :: [String],
    dataListField           :: [InternalData],
    stringFunc              :: String -> String,
    textFunc                :: T.Text -> T.Text,
    monadicStringFunc       :: String -> IO String,
    monadicTextFunc         :: T.Text -> IO T.Text
    } deriving (Data, Typeable)

example = hastacheStr defaultConfig (encodeStr template) 
    (mkGenericContext context)
    where
    template = unlines [
        "string: {{stringField}}",
        "int: {{intField}}",
        "data: {{dataField.someField}}, {{dataField.anotherField}}",
        "data: {{#dataField}}{{someField}}, {{anotherField}}{{/dataField}}",
        "simple list: {{#simpleListField}}{{.}} {{/simpleListField}}",
        "data list:",
        "{{#dataListField}}",
        " * {{someField}}, {{anotherField}}. top level var: {{intField}}",
        "{{/dataListField}}",
        "{{#stringFunc}}upper{{/stringFunc}}",
        "{{#textFunc}}reverse{{/textFunc}}",
        "{{#monadicStringFunc}}upper (monadic){{/monadicStringFunc}}",
        "{{#monadicTextFunc}}reverse (monadic){{/monadicTextFunc}}"]
    context = Example { stringField = "string value", intField = 1, 
        dataField = InternalData "val" 123, simpleListField = ["a","b","c"],
        dataListField = [InternalData "aaa" 1, InternalData "bbb" 2],
        stringFunc = map toUpper,
        textFunc = T.reverse,
        monadicStringFunc = return . map toUpper,
        monadicTextFunc = return . T.reverse }

main = example >>= TL.putStrLn

Result:

string: string value 
int: 1 
data: val, 123 
data: val, 123 
simple list: a b c  
data list: 
 * aaa, 1. top level var: 1 
 * bbb, 2. top level var: 1 
UPPER 
esrever 
UPPER (MONADIC)
)cidanom( esrever

Hastache also supports datatypes with multiple constructors:

data A = A { str :: String }
       | B { num :: Int }

{{#A}}
A : {{str}}
{{/A}}
{{#B}}
B : {{num}}
{{/B}}

mkGenericContext' :: (Monad m, Data a, Typeable m) => (String -> String) -> Ext -> a -> MuContext m

Like mkGenericContext, but apply the first function to record field names when constructing the context. The second function is used to constructing values for context from datatypes that are nor supported as primitives in the library. The resulting value can be accessed using the .DatatypeName field:

{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE TypeSynonymInstances #-}
import Text.Hastache 
import Text.Hastache.Context 

import qualified Data.Text.Lazy as TL 
import qualified Data.Text.Lazy.IO as TL 

import Data.Data (Data, Typeable)
import Data.Decimal
import Data.Generics.Aliases (extQ)

data Test = Test {n::Int, m::Decimal} deriving (Data, Typeable)
deriving instance Data Decimal

val :: Test
val = Test 1 (Decimal 3 1500)

q :: Ext
q = defaultExt `extQ` ((i::Decimal) -> "A decimal: " ++ show i)

r "m" = "moo"
r x   = x

example :: IO TL.Text
example = hastacheStr defaultConfig
                      (encodeStr template)
                      (mkGenericContext' r q val)

template = concat [ 
     "{{n}}\n",
     "{{moo.Decimal}}"
     ] 

main = example >>= TL.putStrLn

Result:

1
A decimal: 1.500

type Ext = forall b. (Data b, Typeable b) => b -> String

defaultExt :: Ext

defaultExt == gshow