The hastache package

[Tags: bsd3, library, program]

Haskell implementation of Mustache templates (http://mustache.github.com/).

See homepage for examples of usage: http://github.com/lymar/hastache


[Skip to ReadMe]

Properties

Versions0.1.1, 0.1.2, 0.1.3, 0.1.4, 0.1.5, 0.1.6, 0.2.0, 0.2.1, 0.2.2, 0.2.4, 0.3.2, 0.3.3, 0.4.1, 0.4.2, 0.5.0, 0.5.1, 0.6.0, 0.6.1
Change logNone available
Dependenciesbase (==4.*), blaze-builder, bytestring, containers, directory, filepath, ieee754, mtl, syb, text, transformers, utf8-string [details]
LicenseBSD3
CopyrightSergey S Lymar (c) 2011-2013
AuthorSergey S Lymar <sergey.lymar@gmail.com>
MaintainerSergey S Lymar <sergey.lymar@gmail.com>
Stabilityexperimental
CategoryText
Home pagehttp://github.com/lymar/hastache
Bug trackerhttp://github.com/lymar/hastache/issues
Source repositoryhead: git clone http://github.com/lymar/hastache
UploadedSun Aug 11 10:05:11 UTC 2013 by SergeyLymar
DistributionsDebian:0.6.1, FreeBSD:0.6.0, LTSHaskell:0.6.1, NixOS:0.6.1, Stackage:0.6.1
Downloads18051 total (626 in last 30 days)
Votes
0 []
StatusDocs uploaded by user
Build status unknown [no reports yet]

Modules

[Index]

Downloads

Maintainers' corner

For package maintainers and hackage trustees

Readme for hastache-0.5.1

Hastache

Haskell implementation of Mustache templates

Installation

cabal update
cabal install hastache

Usage

Read Mustache documentation for template syntax.

See Hastache hackage page.

Examples

Variables

import Text.Hastache 
import Text.Hastache.Context 
import qualified Data.ByteString.Lazy.Char8 as LZ 

main = hastacheStr defaultConfig (encodeStr template) (mkStrContext context)
    >>= LZ.putStrLn

template = "Hello, {{name}}!\n\nYou have {{unread}} unread messages." 

context "name" = MuVariable "Haskell"
context "unread" = MuVariable (100 :: Int)
Hello, Haskell!

You have 100 unread messages.

With Generics

{-# LANGUAGE DeriveDataTypeable #-}
import Text.Hastache 
import Text.Hastache.Context 
import qualified Data.ByteString.Lazy as LZ 
import Data.Data 
import Data.Generics 

main = hastacheStr defaultConfig (encodeStr template) context
    >>= LZ.putStrLn

data Info = Info { 
    name    :: String, 
    unread  :: Int 
    } deriving (Data, Typeable)

template = "Hello, {{name}}!\n\nYou have {{unread}} unread messages."
context = mkGenericContext $ Info "Haskell" 100

Lists

template = concat [ 
    "{{#heroes}}\n", 
    "* {{name}} \n", 
    "{{/heroes}}\n"] 

context "heroes" = MuList $ map (mkStrContext . mkListContext) 
    ["Nameless","Long Sky","Flying Snow","Broken Sword","Qin Shi Huang"]
    where
    mkListContext name = \"name" -> MuVariable name
* Nameless 
* Long Sky 
* Flying Snow 
* Broken Sword 
* Qin Shi Huang

With Generics

data Hero = Hero { name :: String } deriving (Data, Typeable)
data Heroes = Heroes { heroes :: [Hero] } deriving (Data, Typeable)

template = concat [ 
    "{{#heroes}}\n", 
    "* {{name}} \n", 
    "{{/heroes}}\n"] 

context = mkGenericContext $ Heroes $ map Hero ["Nameless","Long Sky",
    "Flying Snow","Broken Sword","Qin Shi Huang"]

Another Generics version

data Heroes = Heroes { heroes :: [String] } deriving (Data, Typeable)

template = concat [ 
    "{{#heroes}}\n", 
    "* {{.}} \n", 
    "{{/heroes}}\n"] 

context = mkGenericContext $ Heroes ["Nameless","Long Sky","Flying Snow", 
    "Broken Sword","Qin Shi Huang"]

List item by index

main = mapM_ (\(template,context) ->
    hastacheStr defaultConfig (encodeStr template) context >>= LZ.putStrLn) 
        [(template1, mkStrContext context1),
         (template1, context2),
         (template3, context3)]

names = ["Nameless","Long Sky","Flying Snow","Broken Sword","Qin Shi Huang"]

template1 = concat [
    "{{heroes.1.name}}\n",
    "{{heroes.0.name}}\n"]

-- Context as function
context1 "heroes" = MuList $ map (mkStrContext . mkListContext) names
    where
    mkListContext name = \"name" -> MuVariable name
context1 _ = MuNothing

-- With Generics
data Hero = Hero { name :: String } deriving (Data, Typeable)
data Heroes = Heroes { heroes :: [Hero] } deriving (Data, Typeable)

context2 = mkGenericContext $ Heroes $ map Hero names

-- With Generics (another way)
template3 = concat [
    "{{heroName.3}}\n",
    "{{heroName.2}}\n"]

data HeroesStr = HeroesStr { heroName :: [String] } deriving (Data, Typeable)

context3 = mkGenericContext $ HeroesStr names
Long Sky
Nameless

Long Sky
Nameless

Broken Sword
Flying Snow

Conditional evaluation

Boolean

template = "{{#boolean}}true{{/boolean}}{{^boolean}}false{{/boolean}}"
context "boolean" = MuBool False
false

List

template = "{{^messages}}No new messages{{/messages}}"
context "messages" = MuList []
No new messages

Number

main = mapM_ (\ctx ->
    hastacheStr defaultConfig (encodeStr template) (mkStrContext ctx)
    >>= LZ.putStrLn) [context1,context2]

template = "{{#msg}}{{msg}}{{/msg}}{{^msg}}No{{/msg}} new messages."

context1 "msg" = MuVariable (100 :: Int)
context2 "msg" = MuVariable (0 :: Int)
100 new messages.
No new messages.

Functions

template = "Hello, {{#reverse}}world{{/reverse}}!" 

context "reverse" = MuLambda (reverse . decodeStr)
Hello, dlrow!

Monadic functions

{-# LANGUAGE FlexibleContexts #-}
import Text.Hastache 
import Text.Hastache.Context 
import qualified Data.ByteString.Lazy.Char8 as LZ 
import Control.Monad.State 

main = run >>= LZ.putStrLn

run = evalStateT stateFunc ""

stateFunc :: StateT String IO LZ.ByteString
stateFunc = 
    hastacheStr defaultConfig (encodeStr template) (mkStrContext context) 

template = "{{#arg}}aaa{{/arg}} {{#arg}}bbb{{/arg}} {{#arg}}ccc{{/arg}}"

context "arg" = MuLambdaM $ arg . decodeStr

arg :: MonadState String m => String -> m String
arg a = do    
    v <- get
    let nv = v ++ a
    put nv
    return nv
aaa aaabbb aaabbbccc

Generics big example

data Book = Book { 
    title           :: String, 
    publicationYear :: Integer 
    } deriving (Data, Typeable) 
 
data Life = Life { 
    born            :: Integer, 
    died            :: Integer 
    } deriving (Data, Typeable) 
     
data Writer = Writer { 
    name            :: String, 
    life            :: Life, 
    books           :: [Book]
    } deriving (Data, Typeable) 
     
template = concat [ 
    "Name: {{name}} ({{life.born}} - {{life.died}})\n", 
    "{{#life}}\n", 
        "Born: {{born}}\n", 
        "Died: {{died}}\n", 
    "{{/life}}\n", 
    "Bibliography:\n", 
    "{{#books}}\n", 
    "    {{title}} ({{publicationYear}})\n", 
    "{{/books}}\n"
    ]

context = mkGenericContext Writer { 
    name = "Mikhail Bulgakov", 
    life = Life 1891 1940, 
    books = [ 
        Book "Heart of a Dog" 1987, 
        Book "Notes of a country doctor" 1926, 
        Book "The Master and Margarita" 1967]
    }
Name: Mikhail Bulgakov (1891 - 1940)
Born: 1891
Died: 1940
Bibliography:
    Heart of a Dog (1987)
    Notes of a country doctor (1926)
    The Master and Margarita (1967)

More examples