[](https://travis-ci.org/arowM/heterocephalus)
[](https://hackage.haskell.org/package/heterocephalus)
[](http://stackage.org/lts/package/heterocephalus)
[](http://stackage.org/nightly/package/heterocephalus)

# Heterocephalus template engine
A type-safe template engine for working with popular front end development tools.
Any PRs are welcome, even for documentation fixes. (The main author of this library is not an English native.)
* [Who should use this?](#who-should-use-this)
* [Features](#features)
* [Usage](#usage)
* [Checking behaviours in `ghci`](#checking-behaviours-in-ghci)
* [Syntax](#syntax)
* [Why "heterocephalus"?](#why-heterocephalus)
## Who should use this?
If you are planning to use Haskell with recent web front-end tools like gulp,
webpack, npm, etc, then this library can help you!
There are many Haskell template engines today.
[Shakespeare](http://hackage.haskell.org/package/shakespeare) is great because
it checks template variables at compile time. Using Shakespeare, it's not
possible to for the template file to cause a runtime-error.
Shakespeare provides its own original ways of writing HTML
([Hamlet](https://hackage.haskell.org/package/shakespeare/docs/Text-Hamlet.html)),
CSS
([Cassius](https://hackage.haskell.org/package/shakespeare/docs/Text-Cassius.html)
/
[Lucius](https://hackage.haskell.org/package/shakespeare/docs/Text-Lucius.html)),
and JavaScript
([Julius](https://hackage.haskell.org/package/shakespeare-2.0.11.2/docs/Text-Julius.html)).
If you use these original markup languages, it is possible to use control
statements like `forall` (for looping), `if` (for conditionals), and `case`
(for case-splitting).
However, if you're using any other markup language (like
[pug](https://pugjs.org), [slim](http://slim-lang.com/),
[haml](http://haml.info/), normal HTML, normal CSS, etc), Shakespeare only
provides you with the
[Text.Shakespeare.Text](https://hackage.haskell.org/package/shakespeare/docs/Text-Shakespeare-Text.html)
module. This gives you variable interpolation, but no control statements like
`forall`, `if`, or `case`.
[`Haiji`](https://hackage.haskell.org/package/haiji) is another interesting
library. It has all the features we require, but its templates take a very
[long time to compile](https://github.com/blueimpact/kucipong/pull/7) with
GHC >= 7.10.
Hetercephalus fills this missing niche. It gives you variable interpolation
along with control statements that can be used with any markup language. Its
compile times are reasonable.
## Features
Here are the main features of this module.
* __DO__ ensure that all interpolated variables are in scope
* __DO__ ensure that all interpolated variables have proper types for the template
* __DO__ expand the template literal on compile time
* __DO__ provide a way to use `forall`, `if`, and `case` statments in the template
`Text.Shakespeare.Text.text` has a way to do variable interpolation, but no
way to use these types of control statements.
* __DO NOT__ enforce that templates obey a peculiar syntax
Shakespeare templates make you use their original style (Hamlet, Cassius,
Lucius, Julius, etc). The
[`Text.Shakespeare.Text.text`](https://hackage.haskell.org/package/shakespeare/docs/Text-Shakespeare-Text.html#v:text)
function does not require you to use any particular style, but it does not
have control statements like `forall`, `if` and `case`.
This makes it impossible to use Shakespeare with another template engine
such as `pug` in front end side. It is not suitable for recent rich front
end tools.
* __DO NOT__ have a long compile time
`haiji` is another awesome template library. It has many of our required
features, but it takes too long to compile when used with ghc >= 7.10.
* __DO NOT__ provide unneeded control statements
Other template engines like [EDE](https://hackage.haskell.org/package/ede)
provide rich control statements like importing external files.
Heterocephalus does not provide control statements like this because it is
meant to be used with a rich front-end template engine (like pug, slim,
etc).
## Usage
You can compile external template files with the following four functions:
* `compileTextFile`: A basic function that embeds variables without escaping and without default values.
* `compileTextFileWithDefault`: Same as `compileTextFile` but you can set default template values.
* `compileHtmlFile`: Same as `compileTextFile` but all embeded variables are escaped for html.
* `compileHtmlFileWithDefault`: Same as `compileHtmlFile` but you can set default template values.
For more details, see the [latest haddock
document](https://www.stackage.org/haddock/nightly/heterocephalus/Text-Heterocephalus.html).
## Checking behaviours in `ghci`
To check the behaviour, you can test in `ghci` as follows. Note that
`compileText` and `compileHtml` are used for checking syntaxes.
```haskell
$ stack install heterocephalus # Only first time
$ stack repl --no-build --no-load
Prelude> :m Text.Heterocephalus Text.Blaze.Renderer.String
Prelude> :set -XTemplateHaskell -XQuasiQuotes
Prelude> let a = 34; b = "<script>"; in renderMarkup [compileText|foo #{a} #{b}|]
"foo 34 <script>"
Prelude> let a = 34; b = "<script>"; in renderMarkup [compileHtml|foo #{a} #{b}|]
"foo 34 <script>"
```
## Syntax
The
[Text.Heterocephalus](https://www.stackage.org/haddock/nightly/heterocephalus/Text-Heterocephalus.html)
module provides two major features for use in template files: variable interpolation
and control statements.
### Variable interpolation
A Haskell variable can be embedded in the template file with the `#{foo}`
syntax. The value of the variable will be injected in at run time.
#### Basic usage
All of following are correct (this assumes that you have already declared the
`var` variable in your Haskell program and it is in scope):
```text
#{ var }
#{var}
#{ var}
#{var }
#{ var }
```
The variable must be an instance of
[`Text.Blaze.ToMarkup`](https://hackage.haskell.org/package/blaze-markup/docs/Text-Blaze.html#t:ToMarkup).
#### Advanced usage
You can use functions and data constructors as well.
```text
#{ even num }
#{ num + 3 }
#{ take 3 str }
#{ maybe "" id (Just b) }
```
### Control statements
Only two type of control statements are provided.
#### Forall
```
%{ forall x <- xs }
#{x}
%{ endforall }
%{ forall (k,v) <- kvs }
#{k}: #{v}
%{ endforall }
```
#### If
```
%{ if even num }
#{num} is even number.
%{ else }
#{num} is odd number.
%{ endif }
```
```
%{ if (num < 30) }
#{ num } is less than 30.
%{ elseif (num <= 60) }
#{ num } is between 30 and 60.
%{ else }
#{ num } is over 60.
%{ endif }
```
#### Case
```
%{ case maybeNum }
%{ of Just 3 }
num is 3.
%{ of Just num }
num is not 3, but #{num}.
%{ of Nothing }
num is not anything.
%{ endif }
```
```
%{ case nums }
%{ of (:) n _ }
first num is #{n}.
%{ of [] }
no nums.
%{ endif }
```
#### Why we do not provide `maybe` and `with`?
TODO
Discussions about this topic is on [issue #9](https://github.com/arowM/heterocephalus/issues/9).
## Why "heterocephalus"?
"Heterocephalus" is the scientific name of the [naked mole-rat](https://en.wikipedia.org/wiki/Naked_mole-rat).