Using ELisp as an HTML templating engine

HTML templating engines like Jinja or handlebars are commonly used in web development for weaving data into HTML.

For last couple of days, I've been porting my Hakyll based static-site generator to Emacs Lisp, for a more fluent thought-publishing workflow. I found myself in need of an HTML templating engine so I could convert data about my blog posts and notes to HTML.

I found that we actually don't need an HTML templating engine to convert ELisp to HTML. Emacs has built-in capability to work with HTML, we can piggy back on that to get a templating engine without adding any new code.

We can represent DOM, which is a tree data-structure, as a lisp form

Consider following HTML element

<div class="container">
  <a href="https://google.com">Google</a>
</div>

We can write it as a lisp form like this:

'(div ((class . "container"))
      (a ((href . "https://google.com"))
         "Google"))

Note that this is a quoted lisp form. Which means this code isn't actually executed, div or a aren't lisp functions. We can just put in any symbol there, and it is treated as a DOM node.

shr-dom-to-xml converts this lisp form to an HTML string:

(let ((my-url "https://google.com"))
  (shr-dom-to-xml
   `(div ((class . "container"))
         (a ((href . ,my-url))
            "Google"))))

In this example we changed the quote used to showcase how we can run arbitrary lisp forms in our DOM to weave data into it.

You can check my wip ELisp blogging setup for more complex examples, and some glue code I've written to make using ELisp as HTML templating engine easier.