2title: More on compilers: load, and templates
3author: Jasper Van der Jeugt
9The compiler Monad is a complex beast, but this is nicely hidden for the user of
12Suppose that you're generating `index.html` which shows your latest brilliant
13blogpost. This requires `posts/foo.markdown` to be generated *before*
14`index.html` (so we don't have to generate it twice). But you don't have to care
15about any of that: Hakyll will sort this out for you automatically!
17Let's see some quick examples. We can load a specific item:
20load "posts/foo.markdown" :: Compiler (Item String)
23Or a whole bunch of them:
26loadAll "posts/*" :: Compiler [Item String]
29Sometimes you just want the *contents* and not the `Item`:
32loadBody "posts/foo.markdown" :: Compiler String
35This is all useful if we want to use Hakyll's templating system.
42Let's have a look at a simple template:
46<div class="info">Posted on $date$</div>
50As you can probably guess, template files just contain text and only the `$`
51character has special meaning: text between dollar signs ("fields") is replaced
52when the template is applied. If you want an actual dollar sign in the output,
55You usually compile the templates from disk using the aptly named
59match "templates/*" $ compile templateCompiler
62Notice the lack of `route` here: this is because we don't need to write the
63templates to your `_site` folder, we just want to use them elsewhere.
67We can easily guess the meaning of `$title$`, `$date$`, and `$body$`, but these
68are not hard-coded fields: they belong to a certain [Context]. A `Context`
69determines how the fields are interpreted. It's a [Monoid] and therefore very
72[Context]: /reference/Hakyll-Web-Template-Context.html
73[Monoid]: http://learnyouahaskell.com/functors-applicative-functors-and-monoids
75`field` allows us to create a `Context` for a single field:
78field :: String -> (Item a -> Compiler String) -> Context a
81Let's try this out. Note that this is for illustration purposes only: you
82shouldn't have to write complicated fields often. We can implement the `$body$`
86field "body" $ \item -> return (itemBody item) :: Context String
89And `$title$` like this:
92titleContext :: Context a
93titleContext = field "title" $ \item -> do
94 metadata <- getMetadata (itemIdentifier item)
95 return $ fromMaybe "No title" $ M.lookup "title" metadata
98And compose them using the `Monoid` instance:
101context :: Context String
104 , field "body" $ return . itemBody
108Obviously, it would be tedious to implement things like `titleContext` over and
109over again for different websites and different fields. This is why hakyll
110provides `defaultContext`. `defaultContext` is a composed `Context` and allows
113- `$body$` for the body of the page;
114- `$url$` for the destination URL of the page;
115- `$path$` for the original filepath of the page;
116- `$foo$` where foo is specified in the metadata.
118`$date$` is not provided by default, you can see how we add it in the definition
119of `postCtx` in `site.hs`:
122postCtx :: Context String
124 dateField "date" "%B %e, %Y" `mappend`
128### Loading and applying templates
130Now we know about templates, context and how to load arbitrary items. This gives
131us enough background information in order to understand you can apply a
136 tpl <- loadBody "templates/post.html"
137 pandocCompiler >>= applyTemplate tpl postCtx
140Loading and then immediately applying a template is so common there's a
145 pandocCompiler >>= loadAndApplyTemplate "templates/post.html" postCtx
148## Producing a list of items
150At 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
154However, this really isn't hard and just uses the things we saw before: loading
155other items and applying templates.
157We can reproduce a list of items in the archive using the following code:
161 posts <- recentFirst =<< loadAll "posts/*"
162 itemTpl <- loadBody "templates/post-item.html"
163 list <- applyTemplateList itemTpl postCtx posts
167`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
169present in the metadata.
172recentFirst :: [Item a] -> Compiler [Item a]
175After loading and sorting the items, we load a template for the posts.
176`applyTemplateList` applies this template to every post and concatenates the
177result, which is a simple `String`. After that, we need `makeItem` to wrap the
178returned `String` to `Item String`.
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list