on master help sign in
All ready for the 4.3 release!
commita591b1622fe9608bc1dc485b74a54730c958bf4d authorJasper Van der Jeugt <m@jaspervdj.be> dateWed 12 Jun 2013, 12:15 (13 years ago) parent2c2b9b2
5 files changed+147−15
data/example/posts/2012-10-07-rosa-rosa-rosam.markdown+1 data/example/posts/2012-12-07-tu-quoque.markdown+1 data/example/templates/post.html+6−1 web/releases.markdown+25 web/tutorials/04-compilers.markdown+114−14
data/example/posts/2012-10-07-rosa-rosa-rosam.markdown+1
@@ -1,5 +1,6 @@
11---
22title: Rosa Rosa Rosam
3+author: Ovidius
34---
45
56Suspendisse pharetra ullamcorper sem et auctor. Suspendisse vitae tellus eu
data/example/posts/2012-12-07-tu-quoque.markdown+1
@@ -1,5 +1,6 @@
11---
22title: Tu Quoque
3+author: Julius
34---
45
56Vestibulum leo turpis, dignissim quis ultrices sit amet, iaculis ac ligula.
data/example/templates/post.html+6−1
@@ -1,3 +1,8 @@
1−<div class="info">Posted on $date$</div>
1+<div class="info">
2+ Posted on $date$
3+ $if(author)$
4+ by $author$
5+ $endif$
6+</div>
27
38$body$
web/releases.markdown+25
@@ -4,6 +4,31 @@ title: Releases
44
55# Releases
66
7+## Hakyll 4.3.0.0
8+
9+- Add conditionals, partials and for loops to the template system (includes a
10+ contribution by Ivan N. Veselov)
11+
12+- Improvements to the preview functionality on windows (contribution by Jorge
13+ Israel Peña)
14+
15+- Add pagination support (contribution by Anton Dubovik)
16+
17+- Slight speedup for the Hakyll cache (contribution by justnoxx)
18+
19+- Add teaser functionality (contribution by Ivan N. Veselov)
20+
21+- Make `./site check` work with scheme-relative URLs (contribution by Simonas
22+ Kazlauskas)
23+
24+- The `./site deploy` command can now be customized with Haskell code
25+ (contribution by Samuel Tardieu)
26+
27+- Use `hsnotify` for proper polling instead of sleep loop on all platforms
28+ (contribution by Simonas Kazlauskas)
29+
30+- More useful debug info available
31+
732## Hakyll 4.2.2.0
833
934- Fix issue with `Alternative` instance of `Compiler`
web/tutorials/04-compilers.markdown+114−14
@@ -145,25 +145,108 @@ compile $
145145 pandocCompiler >>= loadAndApplyTemplate "templates/post.html" postCtx
146146```
147147
148−## Producing a list of items
148+Control flow in templates
149+-------------------------
150+
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
155+pandoc.
156+
157+### Conditionals
158+
159+In `templates/post.html` of the example site we generated using `hakyll-init`,
160+we see an example of a conditional:
161+
162+```html
163+<div class="info">
164+ Posted on $date$
165+ $if(author)$
166+ by $author$
167+ $endif$
168+</div>
169+```
170+
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.
174+
175+Note that an if-else form is supported as well:
176+
177+```html
178+<div class="info">
179+ Posted on $date$
180+ $if(author)$
181+ by $author$
182+ $else$
183+ by some unknown author
184+ $endif$
185+</div>
186+```
187+
188+### Partials
189+
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")$.
193+
194+[DRY]: http://en.wikipedia.org/wiki/Don%27t_repeat_yourself
195+
196+An example can be found in `templates/archive.html`:
197+
198+```html
199+Here you can find all my previous posts:
200+$partial("templates/post-list.html")$
201+```
202+
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
205+our `site.hs`:
206+
207+```haskell
208+match "templates/post-list.html" $ compile templateCompiler
209+```
210+
211+Fortunately, we usually don't need to add this since we already have:
212+
213+```haskell
214+match "templates/*" $ compile templateCompiler
215+```
216+
217+### Producing a list of items: for
149218
150219At this point, everything in the example site we generated should be clear to
151220you, 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:
222+
223+```html
224+<ul>
225+ $for(posts)$
226+ <li>
227+ <a href="$url$">$title$</a> - $date$
228+ </li>
229+ $endfor$
230+</ul>
231+```
153232
154−However, this really isn't hard and just uses the things we saw before: loading
155−other items and applying templates.
233+This uses the `$for(foo)$` construct. This construct allows you loop over a
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$`.
156236
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:
158239
159240```haskell
160−compile $ do
161− posts <- recentFirst =<< loadAll "posts/*"
162− itemTpl <- loadBody "templates/post-item.html"
163− list <- applyTemplateList itemTpl postCtx posts
164− makeItem list
241+posts <- recentFirst =<< loadAll "posts/*"
242+let archiveCtx =
243+ listField "posts" postCtx (return posts) `mappend`
244+ constField "title" "Archives" `mappend`
245+ defaultContext
165246```
166247
248+We discussed `loadAll` earlier in this tutorial.
249+
167250`recentFirst` sorts items by date. This relies on the convention that posts are
168251always named `YYYY-MM-DD-title.extension` in Hakyll -- or that the date must be
169252present in the metadata.
@@ -172,7 +255,24 @@ present in the metadata.
172255recentFirst :: [Item a] -> Compiler [Item a]
173256```
174257
175−After loading and sorting the items, we load a template for the posts.
176−`applyTemplateList` applies this template to every post and concatenates the
177−result, which is a simple `String`. After that, we need `makeItem` to wrap the
178−returned `String` to `Item String`.
258+After loading and sorting the items, we use `listField` to create the `$posts$`
259+key.
260+
261+```haskell
262+listField :: String -> Context a -> Compiler [Item a] -> Context b
263+```
264+
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
269+`return posts`.
270+
271+The following snippet would produce the same result:
272+
273+```haskell
274+let archiveCtx =
275+ listField "posts" postCtx (recentFirst =<< loadAll "posts/*") `mappend`
276+ constField "title" "Archives" `mappend`
277+ defaultContext
278+```