hakyllbars: advanced templates for hakyll

Why another templating language?

hakyll’s own templating language is very simple. It doesn’t permit functions or provide a means to extend its syntax. Simple templates are easy to define and include, but I want something more expressive.

I created my own template language that allows me to specify complex includes, layouts, and define functions. The syntax is inspired by HandlebarsJS, so I call it hakyllbars!

See hakyll’s own template docs here.

What are hakyllbars?

Hakyllbars are double curly-braces {{ and }} which can be used to interpolate expressions into templates.

Special forms of curly braces are capable of different things.

There are a set of default variables and helper functions available for use with bare {{ and }}.

Layouts are applied by using {{@ and }}, which captures all content following the closing }} and passes it as a syntax block to the function between the hakyllbars:

{{@applyLayout "blog-post.html"}}
This will get the blog post treatment.

Control flow is applied by using {{# and }}, which captures all content up to a following {{#end}} and passes it as a syntax block to the function between the opening hakyllbars.

{{#if published}}
  This article was published on {{published}} by {{author}}.
{{#end}}

{{#for posts}}
  {{title}} - {{url}}
{{#else}}
  No posts found.
{{#end}}

Getting started

Here’s some basic boilerplate to leverage Hakyllbars in your site:

import Hakyllbars as HB
import Data.Time

main = do
  -- Sets up configuration for the date fields
  time <- utcToZonedTime <$> getCurrentTimeZone <*> getCurrentTime
  let dateConfig = HB.defaultDateConfigWith defaultTimeLocale time

  match "*.md" do
    route $ setExtension "html"
    -- This is where Hakyllbars is applied
    compile do
      getResourceBody >>= HB.applyTemplates do
        -- Sets the root context used in the templates
        HB.applyContext context
        -- Applies the item content as a template
        HB.applyContent

  where
    context dateConfig =
      -- Sets up the git fields
      HB.gitFields providerDirectory gitWebUrl
        -- Sets up the date fields
        <> HB.dateFields dateConfig
        -- Using the default fields is very recommended
        <> HB.defaultFields host siteRoot

    providerDirectory = "site" -- where your Hakyll files live
    gitWebUrl = "https://github.com/keywordsalad/hakyllbars/tree"
    host = "https://keywordsalad.github.io"
    siteRoot = "/hakyllbars"