This post is part of a small series of posts on enlive. See Exploring Enlive for the background.

In Search of Lost Joy

Out of the box, enlive supports only HTML documents as the source for templates. When we started using enlive, one thing we quickly re-discovered was how incredibly dull and cumbersome it is to actually work with HTML.

One popular templating language that aims to remedy this is haml, marketed as a “Beautiful, DRY, well-indented, clear markup” for creating HTML-like documents. A quick taste for the uninitiated:

  %h1 Warning!
  %p.wat Invalid use of robot
<div id="message">
  <p class="wat">Invalid use of robot</p>

However, in all its beauty, haml has slightly a less exciting model for actually generating dynamic content. Like many other templating solutions, it allows you to embed and execute arbitrary code in your template.

Nothing particularly wrong with that, but it would be interesting to see if one could leverage the terse way of describing a HTML-like document provided by haml with the enlive model for transformation and composition.

A Seed is Planted

Unsurprisingly, we were not the first ones to experience the pain of HTML when using enlive, and other people have explored ways of marrying it with haml.

Two noteworthy approaches:

I think both approaches are interesting and have their strengths and weaknesses, but my main concern with both of them was the added ceremony and slightly awkward integration.

My starting point when exploring this idea further was this: Given an enlive template definition, such as:

(deftemplate tps-report "tps-report.html"

Would it be possibly to somehow just specify a haml document as source instead, and have it all work out nicely:

(deftemplate tps-report "tps-report.haml" ;; <- OMG, different extension!

After a quick look in the enlive source the idea seemed quite possible. All that was needed was, given a source, provide enlive with some enlive data, and leave it to do its magic.

Also, since the goal is to use enlive for the transformation and composition, we don’t care about the parts of haml that concern embedded code.

Given this limitation, how hard can it be to write something that reads a haml document, skips any code related content, and translates it into enlive data?

Enter hamelito

Not entirely trivial, it turned out, but quite fun and a good hacking project for my daily commute:

hamelito is a clojure library that allows you to use a subset of haml as the source for enlive templates

For the parsing, I use excellent parser combinator library kern by Armando Blancas. A pleasure to learn and very well documented.

With exceptionally good timing to my little effort, Christophe also added support for pluggable parsers to enlive, defining an interface for libraries like hamelito.

The result:

(ns blahonga
  (require [net.cgrand.enlive-html             :as enlive]
           [com.github.ragnard.hamelito.enlive :as haml]))

;; To use haml for all templates in the current namespace:
(enlive/set-ns-parser! haml/parser)

(deftemplate tps-report "tps-report.haml" ;; <- mission accomplished!

;; To use haml for a specific template/snippet:
(enlive/deftemplate haml-template {:parser haml/parser} "template.haml"

Exit HTML?

Once hamelito was capable enough, we converted our application to use hamelito and haml templates. The actual conversion took exactly four key-strokes and a mouse-click per template1, thanks to

hamelito is still young and I’m sure that throwing more haml documents at it will expose bugs. If you’re curious, please go ahead and try it, I’d be happy for any comments or bug reports.

but was good when experimenting.

  1. copy, paste, click convert, copy, paste