Skip to content

Instantly share code, notes, and snippets.

@attentive
Last active August 29, 2015 14:03
Show Gist options
  • Save attentive/154e78378f341c37c272 to your computer and use it in GitHub Desktop.
Save attentive/154e78378f341c37c272 to your computer and use it in GitHub Desktop.
Shows one way to create a "dynamic deftemplate" for Enlive
(ns gist.conduit
(:use [net.cgrand enlive-html tagsoup]))
; The implementations of conduit and defconduit are modified versions of
; the macros template and deftemplate from the guts of Enlive.
; They're named 'conduit' because the selectors and transformations serve as a
; channel between the scaffold of HTML and some data provided as an argument.
; Tagsoup is used to parse a list of HTML nodes from a specified input file at runtime.
(defmacro conduit
[args & forms]
(let [[& body] (list* args forms)]
`(fn [source# ~@args]
(let [nodes# (parser (clojure.java.io/reader source#))]
(emit* ((snippet* nodes# ~@body) ~@args))))))
(defmacro defconduit
"Defines a group of selectors and transformations to be applied to
a nominated HTML template and arguments."
[name args & forms]
`(def ~name (conduit ~args ~@forms)))
; An example …
(defconduit page
[page-data]
[:head :title] (content (:title page-data))
[:body :div#main] (content (:body page-data)))
; And this is how you use it …
#_(apply str
(page "/path/to/some/file.html"
{:title "This title will be inserted"
:body "As will this body content, if there's a div in the input with id 'main'."}))
@Bost
Copy link

Bost commented Apr 29, 2015

Works fine for me! Thanx. BTW consider using :require instead of :use. See https://gist.github.com/Bost/0f3e66e5138b2e3a45aa

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment