packages feed

pencil-1.0.1: examples/Docs/site/guides/templates.markdown

# Templates

Pencil comes with a simple templating engine. Templates allow us to build web pages dynamically using Haskell code. Every blog post, for example, can share a common HTML template.

Pencil templates are regular HTML and Markdown (and other formats that Pencil supports) files that contain a **preamble** or **directives**.

## Preamble

Preambles are environment variable declarations inside your source files. A file may only have one preamble, and they must be declared at the top of the file. A preamble is YAML wrapped in an HTML comment. An example Markdown file with a preamble:

```
<!--PREAMBLE
postTitle: "Why I Love Python"
date: 2010-01-30
tags:
  - python
-->

I learned Java first. So when I found out about Python,
it was *love at first sight*.
```

In the above example, Pencil will intelligently parse the `date` value as a [`VDateTime`](https://hackage.haskell.org/package/pencil/docs/Pencil-Internal-Env.html#v:VDateTime). See [`toDateTime`](https://hackage.haskell.org/package/pencil/docs/Pencil-Internal-Env.html#v:toDateTime), which describes the date formats that Pencil will try to coerce into a `VDateTime`.

## Directives

Directives allow you to render variables. They are surrounded by `$${...}`.

### Variables

The simplest directive is the variable directive.

```
Hello $${name}!
```

The above template will render the value of the variable `name`, which is expected to be in the environment at `render`. If the variable is not found, the final render will literally include `${name}`.

### If block

The `if` directive allows us to render content based off the existence of a variable in the current environment.

```
$${if(name)}
  Hello $${name}!
$${end}
```

In this case, we now make sure that `name` is available before rendering.

### For loop

The `for` directive allows for looping over arrays. This is useful for things like rendering a list of blog post titles, linking each line to the actual blog post.

```
<ul>
$${for(posts)}
  <li><a href="$${this.url}">$${postTitle}</a> - $${date}</li>
$${end}
</ul>
```

`posts` must either be a collection node in the Structure, or a [`VEnvList`](https://hackage.haskell.org/package/pencil/docs/Pencil-Internal-Env.html#v:VEnvList) variable. The example will render each post's title, publish date, and will link it to `this.url`. Note that inside the `for` block, the scope changes to each post's environment. So `${postTitle}` will render each post's title.

`this.url` is a special variable that is automatically inserted for you inside a loaded `Page`. It points to the page's destination file path.

### Partials

The `partial` directive injects another template file into the current file. The directives inside the partial are rendered in the same environmental context as the `partial` directive.

Think of partials as just copy-and-pasting snippet from one file to another. Unlike Structures, partials cannot define environment variables.

In the example below, the first `partial` is rendered with the current
environment. The `partial` inside the `for` loop receives the same
environment as any other snippet inside the loop, and thus has access to the environment inside each post.

```
${partial("partials/nav-bar.html")}

${for(posts)}
  ${partial("partials/post-item.html")}
${end}
```

### Escaping

If you want a literal “$${name}” to be rendered, you need to *escape* the dollar sign by doubling it. So in the example below, Pencil will not parse it as a directive, but will render “$${name}” instead:

```
$$${name}
```

[This very source file](https://github.com/elben/pencil/blob/master/examples/Docs/site/guides/templates.markdown) uses escapes.