@@ -145,25 +145,108 @@ compile $
145 pandocCompiler >>= loadAndApplyTemplate "templates/post.html" postCtx
145 pandocCompiler >>= loadAndApplyTemplate "templates/post.html" postCtx
148+Control flow in templates
149+-------------------------
151+Sometimes string interpolation does not suffice, and you want a little more
152+control over how your templates are layed out. Hakyll provides a few control
153+structures for this. The syntax for these structures was based on the syntax
154+used in pandoc templates, since Hakyll already has tight integration with
159+In `templates/post.html` of the example site we generated using `hakyll-init`,
160+we see an example of a conditional:
171+This example should be pretty straightforward. One important thing to notice is
172+that `$if(foo)$` **does not** check the truth value of `$foo$`: it merely checks
173+if such a key is present.
175+Note that an if-else form is supported as well:
183+ by some unknown author
190+Partials allow you to [DRY] up your templates by putting repetitive actions into
191+separate template files. You can then include them using
192+`$partial("filename.html")$.
194+[DRY]: http://en.wikipedia.org/wiki/Don%27t_repeat_yourself
196+An example can be found in `templates/archive.html`:
199+Here you can find all my previous posts:
200+$partial("templates/post-list.html")$
203+This partial is just another template and uses the same syntax. Note that in
204+order to use something like this, we also need to load the partial template in
208+match "templates/post-list.html" $ compile templateCompiler
211+Fortunately, we usually don't need to add this since we already have:
214+match "templates/*" $ compile templateCompiler
148−## Producing a list of items
217+### Producing a list of items: for
150At this point, everything in the example site we generated should be clear to
219At this point, everything in the example site we generated should be clear to
151you, except for how we produce the list of posts in `archive.html` and
220you, except for how we produce the list of posts in `archive.html` and
152−`index.html`.
221+`index.html`. Let's look at the `templates/post-list.html` template:
227+ <a href="$url$">$title$</a> - $date$
154−However, this really isn't hard and just uses the things we saw before: loading
233+This uses the `$for(foo)$` construct. This construct allows you loop over a
155−other items and applying templates.
234+list, in this case, `$posts$`. Inside the body of this for loop, all fields
235+refer to the current post, e.g.: `$url$`, `$title$` and `$date$`.
157−We can reproduce a list of items in the archive using the following code:
237+Of course, $posts$ does not magically appear. We have to specify this in
238+`site.hs`. Let's look at how `archive.html` is generated:
159```haskell
240```haskell
161− posts <- recentFirst =<< loadAll "posts/*"
241+posts <- recentFirst =<< loadAll "posts/*"
162− itemTpl <- loadBody "templates/post-item.html"
242+let archiveCtx =
163− list <- applyTemplateList itemTpl postCtx posts
243+ listField "posts" postCtx (return posts) `mappend`
164− makeItem list
244+ constField "title" "Archives" `mappend`
248+We discussed `loadAll` earlier in this tutorial.
167`recentFirst` sorts items by date. This relies on the convention that posts are
250`recentFirst` sorts items by date. This relies on the convention that posts are
168always named `YYYY-MM-DD-title.extension` in Hakyll -- or that the date must be
251always named `YYYY-MM-DD-title.extension` in Hakyll -- or that the date must be
169present in the metadata.
252present in the metadata.
@@ -172,7 +255,24 @@ present in the metadata.
172recentFirst :: [Item a] -> Compiler [Item a]
255recentFirst :: [Item a] -> Compiler [Item a]
175−After loading and sorting the items, we load a template for the posts.
258+After loading and sorting the items, we use `listField` to create the `$posts$`
176−`applyTemplateList` applies this template to every post and concatenates the
259+key.
177−result, which is a simple `String`. After that, we need `makeItem` to wrap the
260+
178−returned `String` to `Item String`.
261+```haskell
262+listField :: String -> Context a -> Compiler [Item a] -> Context b
265+The first parameter is simply the name of the key (`"posts"`). Secondly we have
266+a `Context` with which all items should be rendered -- for our example site, we
267+already wrote such a `Context` for posts: `postCtx`. Lastly, we have a
268+`Compiler` which loads the items. We already loaded the items so we can just use
271+The following snippet would produce the same result:
275+ listField "posts" postCtx (recentFirst =<< loadAll "posts/*") `mappend`
276+ constField "title" "Archives" `mappend`