Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I use snippets in enlive?

I'm a Rails dev getting my feet wet in Clojure. I'm trying to do something which was very simple with ERB but I can't for the life of me figure it out in enlive.

Say I have a simple layout file for a website in layout.html:

<!DOCTYPE html>
<html>
<head>
</head>
<body>
</body>
</html>

And I have these snippets, for instance, header.html and footer.html and this simple route.

(deftemplate layout "layout.html" [])

(defroutes home-routes
  (GET "/" [] layout))

How can I make it so whenever a request goes to "/" it transforms the layout and inserts the header and footer snippets into it?

like image 496
Chris Bui Avatar asked Jan 21 '13 01:01

Chris Bui


1 Answers

defsnippet only matches a specific part of your html (which is why it takes a selector as an argument), and transforms it. deftemplate takes the entire html, and transforms it. Also, defsnippet returns a Clojure data structure while deftemplates returns a vector of strings, so a defsnippet is usually used within a deftemplate.

To give you an idea of what the data returned by a snippet (or selector) look like:

(enlive/html-snippet "<div id='foo'><p>Hello there</p></div>")
;=({:tag :div, :attrs {:id "foo"}, :content ({:tag :p, :attrs nil, :content ("Hello there")})})

In your case you want something like:

header.html:

<div id="my-header-root">
...
</div>

Clojure code:

(enlive/defsnippet header "path/to/header.html" [:#my-header-root] []
identity)

(enlive/defsnippet footer "path/to/footer.html" [enlive/root] []
identity)

(enlive/deftemplate layout "layout.html" [header footer]
[:head] (enlive/content header)
[:body] (enlive/append footer))

(defroutes home-routes
  (GET "/" [] (layout (header) (footer))

The identity function used in the snippets returns it's argument, which in this case is the data structure selected by the :#my-header-root selector (we don't do any transformation). If you want to include everything in i.e head.html you can use the root selector-step that comes with enlive.

You can view the html generated from a defsnippet using something like this:

(print (apply str (enlive/emit* (my-snippet))))

I also recommend the tutorial: https://github.com/swannodette/enlive-tutorial/ and the one by Brian Marick for some more details of how the defsnippet and deftemplate macros work.

Last tip, you can experiment with selectors and transformations using the sniptest macro that comes with enlive:

(enlive/sniptest "<p>Replace me</p>"
[:p] (enlive/content "Hello world!"))
;= "<p>Hello world!</p>"
like image 127
ebaxt Avatar answered Oct 22 '22 16:10

ebaxt