GithubHelp home page GithubHelp logo

cgrand / enlive Goto Github PK

View Code? Open in Web Editor NEW
1.6K 50.0 152.0 361 KB

a selector-based (à la CSS) templating and transformation system for Clojure

Home Page: http://wiki.github.com/cgrand/enlive

Clojure 73.22% HTML 26.78%

enlive's Introduction

Enlive Build Status

Enlive is a selector-based (à la CSS) templating library for Clojure.

David Nolen wrote a nice tutorial.

Another tutorial is by Brian Marick.

There's a quickstart section in Clojure Cookbook.

Where do I get support?

On the Enlive Google Group

Artifact

All artifacts are published to clojars. Latest version is 1.1.6:

[enlive "1.1.6"]

What's new in Enlive?

(most recent first)

1.1.6:

  • ADD: exception message when html-resource not found.
  • FIX: auto-reload on windows (also works with chestnut).

Auto-reloading (1.1.2)

(net.cgrand.reload/auto-reload *ns*)

Each time a resource or file used by a template/snippet is updated the namespace is reloaded (as per (require ... :reload)).

Misc

  • Perf improvements
  • Fixes to ${vars} substitutions

Pluggable parsers! (1.1.1)

The *parser* dynamic var controls the parser to be used by html-resource at runtime. (or you can pass {:parser XXX} as an additional arg).

For templates and snippets whose sources are not read dynamically, you can opt for another parser either locally:

(deftemplate ugh {:parser xml-parser}
  (java.io.StringReader. "<a><div>hello</div></a>")
  [])

or globally for the declaring ns:

(set-ns-parser! xml-parser)

A parser is a function from InputStream to nodes. xml-parser, net.cgrand.tagsoup/parser and net.cgrand.jsoup/parser are the three builtin ones.

${vars} substitutions (1.1.1)

The following selector + function is going to replace any ${var} in text and attributes by the value found in the map (or any function).

[:#container any-node] (replace-vars {:name "world" :class "hello"})

hiccup-style helper (1.1.0)

(content (html [:h3#hello "Hello worls"]))

older stuff

By default selector-transformation pairs are run sequentially. When you know that several transformations are independent, you can now specify (as an optimization) to process them in lockstep. Note that this doesn't work with fragments selectors.

Example:

  [:a :selector] a-transformation
  [:another :selector] another-transformation
  [:a :dependent :selector] yet-another-transformation

If the first two transformations are independent you can rewrite this code as:

  :lockstep
  {[:a :selector] a-transformation
   [:another :selector] another-transformation}
  [:a :dependent :selector] yet-another-transformation

Transformations are now slightly restricted in their return values: a node or a collection of nodes (instead of freely nested collections of nodes).

Dynamic selectors: selectors aren't compiled anymore. It means that you don't need to wrap them in (selector ...) forms anymore nor to eval them in the most dynamic cases.

Fragment selectors allow to select adjacent nodes. They are denoted by a map of two node selectors (eg {[:h1] [:p]}), bounds are inclusive and they select the smallest matching fragments.

Transformations (the right-hand parts of rules) are now plain old closures. These functions take one arg (the selected node) and return nil, another node or a collection of nodes.

Rules are applied top-down: the first rule transforms the whole tree and the resulting tree is passed to the next rules.

Nodes are transformed deep-first, that is: if a selector selects several nodes, descendants are transformed first. Hence, when the transformation is applied to an ancestor, you can "see" the transformed descendants (but you can not see your transformed siblings).

   /B                                                                             /(T B)
  A    if A and B are selected and transformed by T the the resulting tree is (T A      )
   \C                                                                             \C

Concepts

snippet is a unit of your page. It may be logical or visual entry, such as header, footer, page element. Snippet is usually a part of a template, and may serve as a container for other snippets. For example, for navigation on the web page. For that, let’s first define an html template for the navigation. Snippets are created by using net.cgrand.enlive-html/defsnippet function and, same as templates, they require a corresponding HTML template file to be availble in a classpath.

So, snippet function returns a seq of nodes, it can be used as a building block for more complex templates.

templates combine snippets together, they serve like a basement for the snippets. In order to create a template, you can use net.cgrand.enlive-html/deftemplate function. deftemplate is used as something what you would call layout in some other templating systems. In essence, it’s either a self-contained page (rarely true in bigger applications), or a container for snippets.

That said, a template is a returns a seq of string -- basically it's a snippet whose output is serialized. Templates return a seq of strings to avoid building the whole string.

Templates and snippets transform a source (specified as a path (to access resources on the classpath), a File, a Reader, an InputStream, a URI, a URL, an element or a seq of nodes).

Next concept is selectors, which are used within snippets and templates to identify the block of HTML code the transformation would be applied to. They’re very similar to CSS selectors, but also allow more sophisticated, predicate-based selections, for example, you can select a tag based on some part of content, or an attribute. Transformations are functions that triggered on the elements found by selectors. They receive content obtained selector, and modify it in some way.

Quickstart tutorial

Template

If you want to go see the compiled version of the following steps all in one place, you can check out an example Ring application.

First thing you need to start, is to define your first template:

(require '[net.cgrand.enlive-html :as html])

(html/deftemplate main-template "templates/application.html"
  [])

Now, you can start writing selectors and transformations for the given selectors. Let's add a title to the template. Given that your template already has <head> and <title> tags, let's insert a title.

Content of templates/application.html:

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>This is a title placeholder</title>
  </head>
  <body>
  </body>
</html>
(html/deftemplate main-template "templates/application.html"
  []
  [:head :title] (html/content "Enlive starter kit"))

Here, [:head :title] is a selector, pretty much like a css selector. If you're coming from jQuery, you can write same selector as $("head title"). html/content is a transformation. It puts the given content into the element specified by your selector.

Snippet

Let's add several snippets. For example, navigation and some content. For that, let's first define a template for the navigation. Content of templates/header.html

<!DOCTYPE html>
<html lang="en">
  <body>
    <header>
      <h1>Header placeholder</h1>
      <ul id="navigation">
        <li><a href="#">Placeholder for navigation</a></li>
      </ul>
    </header>
  </body>
</html>
(html/defsnippet main-template "templates/header.html"
  [:header]
  [heading navigation-elements]
  [:h1] (html/content heading)
  [:ul [:li html/first-of-type]] (html/clone-for [[caption url] navigation-elements]
                                                 [:li :a] (html/content caption)
                                                 [:li :a] (html/set-attr :href url)))

Selectors

Enlive selectors can match either nodes or fragments (several adjacent nodes).

At the core, every selector is a vector. The items of this vector are called steps.

A step is a predicate, for example :h1, :p.some-class or even (attr? :lang).

To select elements which match several predicates, you need to group predicates into a vector: inside steps, vectors mean "and". This may seem confusing but the rule is simple: the outer-most vector hierarchically chains steps, all other vectors denote intersection (and) between steps.

So [:p (attr? :lang)] is going to match any elements with a lang attribute inside a :p element. On the other hand, [[:p (attr? :lang)]] is going to match any p with a lang attribute.

Similarly, sets group predicates in an union. Hence inside steps, sets mean "or". So [#{:div.class1 :div.class2}] match every div which has either class1 or class2. This can alternatively be written as [[:div #{:.class1 .class2}]]. Indeed you can have nested "ors" and "ands" which means nested sets and vectors.

At the top level you can have a big "or" between selectors by wrapping several selectors in a set. #{[:td :em] [:th :em]} is going to match any em insides either a th or a td. This is equivalent to [#{:td :th} :em].

Selector Syntax

See syntax.html

Some examples:

Enlive                                       CSS
=======================================================
[:div]                                       div
[:body :script]                              body script
#{[:ul.outline :> :li] [:ol.outline :> li]}  ul.outline > li, ol.outline > li
[#{:ul.outline :ol.outline} :> :li]          ul.outline > li, ol.outline > li
[[#{:ul :ol} :.outline] :> :li]              ul.outline > li, ol.outline > li
[:div :> :*]                                 div > *
[:div :> text-node]                          (text children of a div)
[:div :> any-node]                           (all children (including text nodes and comments) of a div)
{[:dt] [:dl]}                                (fragments starting by DT and ending at the *next* DD)

The at form

The at form is the most important form in Enlive. There are implicit at forms in snippet and template.

(at a-node
  [:a :selector] a-transformation
  [:another :selector] another-transformation
  ;; ...
  )

The right-hand value of a rule can be nil. It's the idiomatic way to remove an element.

Transformations are closures which take one arg (the selected node) and return nil, another node or an arbitrarily nested collection of nodes.

Rules are applied top-down: the first rule transforms the whole tree and the resulting tree is passed to the next rules.

Transformations

A transformation is a function that returns either a node or collection of node.

Enlive defines several helper functions:

;; Replaces the content of the element. Values can be nodes or collection of nodes.
(content "xyz" a-node "abc")

;; Replaces the content of the element. Values are strings containing html code.
(html-content "<blink>please no</blink>")

;; Wraps selected node into the given tag
(wrap :div)
;; or
(wrap :div {:class "foo"})

;; Opposite to wrap, returns the content of the selected node
unwrap

;; Sets given key value pairs as attributes for selected node
(set-attr :attr1 "val1" :attr2 "val2")

;; Removes attribute(s) from selected node
(remove-attr :attr1 :attr2)

;; Adds class(es) to the selected node
(add-class "foo" "bar")

;; Removes class(es) from the selected node
(remove-class "foo" "bar")

;; Chains (composes) several transformations. Applies functions from left to right.
(do-> transformation1 transformation2)

;; Clones the selected node, applying transformations to it.
(clone-for [item items] transformation)
;; or
(clone-for [item items]
  selector1 transformation1
  selector2 transformation2)

;; Appends the values to the content of the selected element.
(append "xyz" a-node "abc")

;; Prepends the values to the content of the selected element.
(prepend "xyz" a-node "abc")

;; Inserts the values after the current selection (node or fragment).
(after "xyz" a-node "abc")

;; Inserts the values before the current selection (node or fragment).
(before "xyz" a-node "abc")

;; Replaces the current selection (node or fragment).
(substitute "xyz" a-node "abc")

;; Takes all nodes (under the current element) matched by src-selector, removes
;; them and combines them with the elements matched by dest-selector.
(move [:.footnote] [:#footnotes] content)

Known limitations/problems

  • No namespaces support (hence unsuitable for most XML)

enlive's People

Contributors

bronsa avatar cemerick avatar cgrand avatar claj avatar dthume avatar ghoseb avatar hugoduncan avatar ifesdjeen avatar jafingerhut avatar justiniac avatar marick avatar mcramm avatar neatonk avatar oskarth avatar peeja avatar sander avatar sattvik avatar sergeydidenko avatar swannodette avatar wolfes avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

enlive's Issues

Enlive (or one of its dependencies) breaks the HTML5 boilerplate

Given the following HTML template (trimmed down from https://raw.github.com/h5bp/html5-boilerplate/master/index.html ):

<!DOCTYPE html>
<!--[if lt IE 7]>      <html class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]-->
<!--[if IE 7]>         <html class="no-js lt-ie9 lt-ie8"> <![endif]-->
<!--[if IE 8]>         <html class="no-js lt-ie9"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js"> <!--<![endif]-->
    <head>
        <title>Hi</title>
    </head>
    <body>
       Hi.
    </body>
</html>

If I run such a file through net.cgrand.enlive-html/deftemplate (even without any modifications), the following HTML ends up making it to the browser:

<!DOCTYPE html>
<!--[if lt IE 7]>      <html class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]--><!DOCTYPE html>
<!--[if IE 7]>         <html class="no-js lt-ie9 lt-ie8"> <![endif]--><!DOCTYPE html>
<!--[if IE 8]>         <html class="no-js lt-ie9"> <![endif]--><!DOCTYPE html>
<!--[if gt IE 8]><!--><!DOCTYPE html>
<html class="no-js"> <!--<![endif]-->
    <head>
        <title>Hi</title>
    </head>
    <body>
       Hi.
    </body>
</html>

Note the repeated DOCTYPE statements. I don't have access to any IE browsers to fully assess the outcome of this, but I'd wager that it wouldn't take it well (since for some versions of IE, the DOCTYPE statement will come after the <html> tag).

Clone For produces randomly failing markup

I'm running something like (enlive/clone-for [script-src ["/js/mylib.js" "js/my2ndlib.js"] (enlive/set-attr :src script-src)). The resulting HTML is usually as expected, but upon refresh of the page the server regenerates it and often leaves off a character or two from the tags, leaving me with broken scripts, e.g. <script src="..."></script>script></script<script. I've tried both the xml-resource and the standard deftemplate form to no avail.

at macro not working as expected

Hi, seems that at macro is not working as it should when is used with one rule. Here is a test:

(import 'java.io.StringReader)

;; node don't need to be nested in a vector
(defmacro at-2 [node & rules]
  `(at* ~node ~@(map #(%1 %2) (cycle [#(list `selector %) identity]) rules)))

(def html (html-resource (StringReader. "<div> <h1> Hello </h1> world </div>")))
(def x (at html [:div] (append "!!!"), [:h1] (content "Hi")))
(def y (at-2 html (selector [:div]) (append "!!!"), (selector [:h1]) (content "Hi")))
(def c (at* html (selector [:div]) (append "!!!"), (selector [:h1]) (content "Hi")))
;; (= x c)
;; (= y c)

spelling mistake in readme

Is there a missing colon here?

This can alternatively be written as [[:div #{:.class1 .class2}]].

==>

This can alternatively be written as [[:div #{:.class1 :.class2}]].

Templates inherit thread bindings when created

I ran into a bug today where templates created with deftemplate seem to behave as if created with bound-fn.

Take this example:

(def ^{:dynamic true} *foo*) 
(defn x [] (prn *foo*)) 
(binding [*foo* "foo"] (x))

This has the effect of printing "foo" because when x is called, the binding sets the value of *foo*. If you replace x with a deftemplate, *foo* is unbound and doesn't get the bindings.

I'm actually pretty shocked that I'm the only one who has noticed this after all this time. This makes Enlive pretty hard to use with Noir and Sandbar because their stateful sessions use bindings to reflect the current session. I'm stuck on moving RefHeap to Enlive because I don't want to delve into the major hax that'd be involved in working around this.

Also, is this project going to be actively maintained in the future? I see there are some pull requests and issues that have been festering for a year or longer. They don't really inspire confidence. :p

empty & complement

Is it a good idea to rename these since they belong to core? Good names are hard to come by in Clojure ;)

Lazy-seq in mapknit kills performance

Hi,

Currently mapknit uses lazy-seq:

(defn- mapknit
 ([f coll]
   (mapknit f coll nil))
 ([f coll etc]
    (lazy-seq
     (if (seq coll)
       (f (first coll) (mapknit f (rest coll) etc))
       etc))))

If you remove (lazy-seq), which doesn't seem 100% mandatory here (disputable), you get a major (~8x) performance increase when rendering large pages.

Right now, rendering takes around 250-300 milliseconds for large page. With that change it's possible to get time down to 40ms.

Do you have any ideas what may be causing it and wether it's safe to get rid of it?

Support for or?

I'm actually using Enlive to grab data from Amazon Web Services. One thing that would be nice would be something like the or operator.

[[:some :selector] :or [:another :selector]]

if the first selector returns nodes, that is the result. Otherwise move on to the following selector. This would be useful when some selector for some reason doesn't match and you want to fall back on another selector. This is very useful if you are explicitly using the select macro to pull in portions of an xml document.

Character encoding

Hi,
The character encoding of an HTML read using (enlive-html/html-resource (java.net.URL. url)) is not recognized automatically. This is because enlive assumes UTF-8 encoding, instead of extracting it from the HTML file. Please solve this problem.
In the meantime I'm using this patch to workaround it: http://groups.google.com/group/enlive-clj/msg/8026b46279ac0152?pli=1

Thank you very much for your time.
Keep up the good work =)
Cheers

Make the HTML-parser exchangable

The parser that is currently used, TagSoup, cleans up the document very aggressively. It removes some markup that is valid HTML5. I already got enlive to work with NekoHTML, but in order to future-proof the library, the user should be enabled to specify the parser himself. I have the following API ideas for this:

(html-resource "http://github.com" :parser com.example/mozilla-html5parser)

or alternatively

 (binding [*enlive-parser* com.example/neko-html-parser]
   (html-resource "http://github.com"))

Unicode appears to be getting stripped/corrupted

Here is the simplest test case I could come up with:

user=> (use 'net.cgrand.enlive-html)       
nil
user=> (System/getProperty "file.encoding")
"UTF8"
user=> (defsnippet test-tpl (java.io.StringReader. "<p></p>") [:p] [text] [:p] (content text))
#'user/test-tpl
user=> (test-tpl "hello")
({:tag :p, :attrs nil, :content ("hello")})
user=> (test-tpl "…they’re not")
({:tag :p, :attrs nil, :content ("&theyre not")})
user=> 
user=> (test-tpl "あなた→")
({:tag :p, :attrs nil, :content ("Bj_�")})

As you can see (hopefully you can see?) strings are getting messed up by transformations. I've tried with other transforms – html-content, html-snippet and substitute, and always hit the same problem.

at* uses transform incorrectly

transform takes three arguments, which makes it unsuitable for reduce

A quick fix:

(defn at* [nodes & rules](reduce #%28apply transform %1 %2%29 nodes %28partition 2 rules%29))

Support multi-arity templates

It'd be very nice if templates' arities could be overloaded, following Clojure's syntax. Example:

(enlive/template "index.html"
                 ([id]
                    [:#some_selector]
                      (content "blah" id))
                 ([id products]
                    [:#blah]
                      (content (interpose id products))))

What do you think?

Victor

Runtime resourse resolving

The following template definition:

(deftemplate front-page (file "pages/main.html")
  [...]
  ...)

does not work when "pages/main.html" does not refer to vaid file during compile time. It fails with FileNotFoundException.

My project's resources (that is, html page templates) are not present in the resources directory since I want an ability to edit HTML templates without recompiling the whole jar (I just do not understand why all the tutorials and other sources all over the internet are written is such way that the templates are supposed to be present inside jar file - you have to rebuild whole uberjar when you change single tag in one of the templates!). Complete application is assembled using ant script, and it is supposed that all files will be in correct place once the program is run.

But I cannot use any enlive forms which work with external files, since files are resolved at compile time. I don't this this is right behavior.

ranges + defsnippet bug?

When I try the following:

(def *section-sel* {[:h2] [:ul]})
 
(defsnippet section-model "tutorial/template2.html" *section-sel*
  [{:keys [title links]}]
  [:h2] (content title)
  [:ul] (content (map link-model links)))

I get the following exception:

nth not supported on this type: PersistentArrayMap
  [Thrown class java.lang.UnsupportedOperationException]

flatten-nodes-coll (and thus clone-for) cannot accept integers

using numbers as arguments for clone-for fail with exception:

user=> ((html/clone-for [item [2 3 4]] (fn [x] item)) :test-node)
(user=> java.lang.IllegalArgumentException: Don't know how to create ISeq from: java.lang.Integer

while using string are ok:

user=> ((html/clone-for [item ["2" "3" "4"]] (fn [x] item)) :test-node)
("2" "3" "4")

Quick troubleshooting shown, that this is flatten-nodes-coll is failing:

user=> (html/flatten-nodes-coll [1 2 3])
(user=> java.lang.IllegalArgumentException: Don't know how to create ISeq from: java.lang.Integer

:content should be a vector rather than a list

If I try to use Enlive to scrape a page:

(def wiki-page
  (html/html-resource (java.net.URL. "http://en.wikipedia.org/wiki/List_of_mathematical_symbols")))

(first
 (html/select wiki-page [:table.wikitable :td :a]))
;; => {:tag :a, :attrs {:title "Equals sign", :href "/wiki/Equals_sign"}, :content ("=")}

... the Clojure reader cannot turn this into a proper data structure because the :content node, being a list rather than a vector, attempts to call the first element as a function, resulting in an exception:

java.lang.String cannot be cast to clojure.lang.IFn

(Unrelated: joyeux noël, M. Grand.)

Opening < of html elements is randomly stripped

The opening < of html elements is randomly stripped from template output.

layout.clj

(ns quality.views.layout
  (:require [net.cgrand.enlive-html :as html]))

(html/deftemplate layout-html
  "quality/views/layout.html"
  [title body]

  [:title]
  (html/content (str title " - Quality"))

  [:div#universe]
  (html/content body))

layout.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title>Quality</title>
</head>
<body>
<div id="universe"></div>
</body>
</html>

One request, for instance, just output this:

<!DOCTYPE html>
html lang="en">
<head>
    meta charset="utf-8" />
    <title>Page title - Quality</title>
head>
<body>
<div id="universe">Hello</div>
</body>
</html>

I'm using enlive 1.1.4.

null pointer exception

(require '[net.cgrand.enlive-html :as html])

(html/deftemplate main-template "cal-template.html" [])
CompilerException java.lang.NullPointerException, compiling:(form-init4068037723
946272080.clj:1:1)

I actually can only get sniptest to work. I thought this may be because I am supplying the html directly in that function:

(html/sniptest (slurp "cal-template.html"))
"<div style=\"padding:5px;\" class=\"container mine wauto theme-home\" id=\"cal-
template\">\n\t<p>\n\t\t<b>Event</b>: <span id=\"summary\"></span><br />\n\t\t<b
>When</b>: <span id=\"when\"></span><br />\n\t\t<b>Where</b>: <span id=\"where\"
></span><br />\n\t\t<b>Description</b>: <span id=\"what\"></span>\n\t</p>\n</div
>"

What am I missing here?

replace-vars {:id 1} failed

I had

<td>${id}</td>

in html, when I do

replace-vars {:id 1}

it failed with

java.lang.ClassCastException: java.lang.Long cannot be cast to java.lang.String

Unobtrusive auto-selectors

You can use snippet markers within your HTML template code in order to generate *-prefixed selectors that you can later use within Enlive template.

For example, if you say:

<div snippet="content-main"></div>

You can later reference it with *content-main selector, which will be automatically generated for you.

One of the hidden benefist is that if your application code relies on some element in HTML, here it will be validated, and if there's anything referenced that's not present in HTML, you'll get an exception during compilation, which is good, I think.

For example, having an html template such as:

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>App Layout</title>
  </head>
  <body>
    <div snippet="content-main">
      <ul snippet="simple-list">
        <li snippet="simple-list-item">${value}</li>
      </ul>
    </div>
  </body>
</html>

You can do:

(ns clojurewerkz.gizmo.enlive-test
  (:require [net.cgrand.enlive-html :as html])
  (:use clojure.test
        clojurewerkz.gizmo.widget
        clojurewerkz.gizmo.enlive))

(deftest defsnippet-test
  (defsnippet defsnippet-test-snippet-1 "templates/snippets/sniptest.html"
    [*content-main]
    [values]
    [*simple-list [*simple-list-item]] (html/clone-for [value values]
                                                       [html/any-node] (html/replace-vars {:value value})))

  (is (= (render* (defsnippet-test-snippet-1 ["a" "b" "c"]))
         "<div snippet=\"content-main\">
      <ul snippet=\"simple-list\">
        <li snippet=\"simple-list-item\">a</li><li snippet=\"simple-list-item\">b</li><li snippet=\"simple-list-item\">c</li>
      </ul>
    </div>")))

Where *content-main, *simple-list, *simple-list-item are symbols generated from HTML markup.

These symbols will throw an exception during compile time if they're gone from HTML markup.
They're unobtrusive (you can use different HTML ids and all other attributes without breaking application code).
You don't have to write complex (potentially nested) CSS selectors

Enlive and AngularJS Issues

Here's how you normally start an AngularJS (http://angularjs.org/) document:

<!doctype html>
<html ng-app>

However, TagSoup only recognizes uppercase DOCTYPE so if you enter it as lowercase, Enlive won't include the doctype in the generated document.

TagSoup also rewrites the above HTML tag as...

<html ng-app="ng-app">  

...but this causes JavaScript errors...

Uncaught Error: No module: ng-app                 angular-1.0.1.min.js:17

You can get around this by setting ng-app to an empty string:

<!DOCTYPE html> 
<html ng-app=""> 

See https://groups.google.com/d/msg/angular/wgWVZzrD-yQ/k3bAmYuaqkwJ

Problem with destructing

Following snippet returns passed map as a content of #name element:

(defsnippet details (path "details.html") [:div#details]
  [{:keys [name desc price capacity order-url photos-urls]}]
  [:#name] (content name)
  [:#desc] (content desc)
  [:#price] (append price)
  [:#capacity] (append capacity)
  [:a#order] (set-attr :href order-url)
  [:#photos :img] (clone-for [u photos-urls]
                    (set-attr :src u)))

But this snippet works well:

(defsnippet details (path "details.html") [:div#details]
  [x]
  [:#name] (content (:name x))
  [:#desc] (content (:desc x))
  [:#price] (append (:price x))
  [:#capacity] (append (:capacity x))
  [:a#order] (set-attr :href (:order-url x))
  [:#photos :img] (clone-for [u (:photos-urls x)]
                    (set-attr :src u)))

Enllive 1.0.0 and Clojure 1.2.1

Testing Related Issues Needed

Christophe,

I just finished up training with the Clojure Core guys in Durham and now have a decent foundation. Will you please guide me on what the testing needs you have for Enlive via issues, so I can make a positive contribution to your projects while my understanding grows. Testing is about the only area I feel comfortable saying I can help out at this point and I want to be a part of Enlive.

PHB

Please stop using version ranges

Using [1.2.0,) is a bad idea and causes all sorts of problems for downstream users. Phil Hagelberg recommends not using version ranges. Nelson Morris just wrote a blog post picking on your regex library explaining why version ranges are a bad idea.

Configurable time-out for network / IO operations in get-resource

In order to create robust code it would be great to have a configurable timeout for network operations (and possibly also other IO operations that might hit a network barrier or be unavailable), ie. in the get-resource multi-method, especially when hitting a URL or URI.

It also (indirectly) applies to html-resource and xml-resource.

first-of-type (and actually nth-of-type) is not taking a complete predicate into consideration

Here's a failing test that verifies it:

(deftest first-of-type-test
  (is (=
       "<div class=\"first-level\"><div class=\"foo second-level-first\">a</div><div class=\"second-level-second\">b</div></div>"
       (sniptest "<div class='first-level'><div class='second-level-first'>a</div><div class='second-level-second'>b</div></div>"
                 [:div.first-level [:div.second-level-first first-of-type]] (add-class "foo"))))

  (is (=
       "<div class=\"first-level\"><div class=\"second-level-first\">a</div><div class=\"foo second-level-second\">b</div></div>"
       (sniptest "<div class='first-level'><div class='second-level-first'>a</div><div class='second-level-second'>b</div></div>"
                 [:div.first-level [:div.second-level-second first-of-type]] (add-class "foo")))))

This test fails, because class "foo" is not being added to div.second-level-second node.

If you change selector to

[:div.first-level [:div.second-level-second (nth-of-type 2)]]

Which kind of undermines meaning of nth-of type combined with any different selector, it will correctly add class "foo" to the required node.

UPDATE:
I will provide a pull request that fixes the issue later today or during the week. Just putting it here not to forget.

StringReader and special characters

When I process some HTMl with html-snippet, it appears StringReader produces byte output for characters like "& t r a d e;". Note below the trademark symbol at the end of the output:

({:tag :html, :attrs nil, :content ({:tag :head, :attrs nil, :content nil} {:tag :body, :attrs nil, :content ("Hello World!™")})})

Is there anyway to avoid that? I'm manipulating templates and passing them to a PDF processor, and it's garbling up the characters. Ideas?

<?xml ... ?> being stripped from XML output

Enlive version [enlive "1.1.4"] strips out the <?xml ... ?> declaration from the output (which it probably shouldn't).

  • test.rss
<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0"></rss>
  • test.clj
(defn render [nodes]
  (apply str nodes))

(deftemplate test (xml-resource "test.rss") [])

(defroutes routes
  (GET "/test" [] (render (test))))
  • output (GET /test)
<rss version="2.0"></rss>

IOException Pushback buffer overflow java.io.PushbackReader.unread (:-1)

When I run this code:

(html/select (html/html-resource (java.net.URL. "http://en.wiktionary.org/wiki/Index:English/m1")) [:ol :li :a])

I get this exception:

java.io.IOException: Pushback buffer overflow
at java.io.PushbackReader.unread(Unknown Source)
at org.ccil.cowan.tagsoup.HTMLScanner.unread(HTMLScanner.java:274)
at org.ccil.cowan.tagsoup.HTMLScanner.scan(HTMLScanner.java:487)
at org.ccil.cowan.tagsoup.Parser.parse(Parser.java:449)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at clojure.lang.Reflector.invokeMatchingMethod(Reflector.java:93)
at clojure.lang.Reflector.invokeInstanceMethod(Reflector.java:28)
at net.cgrand.enlive_html$startparse_tagsoup.invoke(enlive_html.clj:37)
at net.cgrand.xml$parse.invoke(xml.clj:94)
at net.cgrand.enlive_html$load_html_resource$fn__1089.invoke(enlive_html.clj:54)
at net.cgrand.enlive_html$load_html_resource.invoke(enlive_html.clj:53)
at net.cgrand.enlive_html$fn__1113.invoke(enlive_html.clj:102)
at clojure.lang.MultiFn.invoke(MultiFn.java:167)
at net.cgrand.enlive_html$html_resource.invoke(enlive_html.clj:69)
at wikitionary_fetch.core$fetch_url.invoke(core.clj:7)
at wikitionary_fetch.core$get_index_page.invoke(core.clj:25)
at wikitionary_fetch.core$get_all_words$fn__3073.invoke(core.clj:30)
at clojure.core$map$fn__4087.invoke(core.clj:2434)
at clojure.lang.LazySeq.sval(LazySeq.java:42)
at clojure.lang.LazySeq.seq(LazySeq.java:60)

This code works perfectly:

(html/select (html/html-resource (java.net.URL. "http://en.wiktionary.org/wiki/Index:English")) [:center :p :a])

Java: Java(TM) SE Runtime Environment (build 1.7.0_04-b20) 32-bit
Clojure: 1.4.0
Enlive: 1.0.1

Exception in thread "main" java.lang.StackOverflowError

Using Clojure 1.4 and Enlive 1.0.0.

Exception in thread "main" java.lang.StackOverflowError
    at clojure.lang.RT.seq(RT.java:475)
    at clojure.lang.RT.vals(RT.java:507)
    at clojure.core$vals.invoke(core.clj:1459)
    at net.cgrand.enlive_html$make_state$fn__1415.invoke(enlive_html.clj:367)
    at clojure.lang.AFn.applyToHelper(AFn.java:161)
    at clojure.lang.AFn.applyTo(AFn.java:151)
    at clojure.core$apply.invoke(core.clj:601)
    at clojure.core$memoize$fn__4921.doInvoke(core.clj:5620)
    at clojure.lang.RestFn.invoke(RestFn.java:408)
    at clojure.core$comp$fn__4034.invoke(core.clj:2279)
    at net.cgrand.enlive_html$step.invoke(enlive_html.clj:390)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538.invoke(enlive_html.clj:497)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538$fn__1539.invoke(enlive_html.clj:498)
    at clojure.core$map$fn__4087.invoke(core.clj:2434)
    at clojure.lang.LazySeq.sval(LazySeq.java:42)
    at clojure.lang.LazySeq.seq(LazySeq.java:60)
    at clojure.lang.RT.seq(RT.java:473)
    at clojure.core$seq.invoke(core.clj:133)
    at clojure.core$apply.invoke(core.clj:601)
    at clojure.core$mapcat.doInvoke(core.clj:2461)
    at clojure.lang.RestFn.invoke(RestFn.java:423)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538.invoke(enlive_html.clj:498)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538$fn__1539.invoke(enlive_html.clj:498)
    at clojure.core$map$fn__4087.invoke(core.clj:2434)
    at clojure.lang.LazySeq.sval(LazySeq.java:42)
    at clojure.lang.LazySeq.seq(LazySeq.java:60)
    at clojure.lang.Cons.next(Cons.java:39)
    at clojure.lang.RT.boundedLength(RT.java:1633)
    at clojure.lang.RestFn.applyTo(RestFn.java:130)
    at clojure.core$apply.invoke(core.clj:601)
    at clojure.core$mapcat.doInvoke(core.clj:2461)
    at clojure.lang.RestFn.invoke(RestFn.java:423)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538.invoke(enlive_html.clj:498)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538$fn__1539.invoke(enlive_html.clj:498)
    at clojure.core$map$fn__4087.invoke(core.clj:2434)
    at clojure.lang.LazySeq.sval(LazySeq.java:42)
    at clojure.lang.LazySeq.seq(LazySeq.java:60)
    at clojure.lang.Cons.next(Cons.java:39)
    at clojure.lang.RT.boundedLength(RT.java:1633)
    at clojure.lang.RestFn.applyTo(RestFn.java:130)
    at clojure.core$apply.invoke(core.clj:601)
    at clojure.core$mapcat.doInvoke(core.clj:2461)
    at clojure.lang.RestFn.invoke(RestFn.java:423)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538.invoke(enlive_html.clj:498)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538$fn__1539.invoke(enlive_html.clj:498)
    at clojure.core$map$fn__4087.invoke(core.clj:2434)
    at clojure.lang.LazySeq.sval(LazySeq.java:42)
    at clojure.lang.LazySeq.seq(LazySeq.java:60)
    at clojure.lang.Cons.next(Cons.java:39)
    at clojure.lang.RT.boundedLength(RT.java:1633)
    at clojure.lang.RestFn.applyTo(RestFn.java:130)
    at clojure.core$apply.invoke(core.clj:601)
    at clojure.core$mapcat.doInvoke(core.clj:2461)
    at clojure.lang.RestFn.invoke(RestFn.java:423)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538.invoke(enlive_html.clj:498)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538$fn__1539.invoke(enlive_html.clj:498)
    at clojure.core$map$fn__4087.invoke(core.clj:2434)
    at clojure.lang.LazySeq.sval(LazySeq.java:42)
    at clojure.lang.LazySeq.seq(LazySeq.java:60)
    at clojure.lang.Cons.next(Cons.java:39)
    at clojure.lang.RT.boundedLength(RT.java:1633)
    at clojure.lang.RestFn.applyTo(RestFn.java:130)
    at clojure.core$apply.invoke(core.clj:601)
    at clojure.core$mapcat.doInvoke(core.clj:2461)
    at clojure.lang.RestFn.invoke(RestFn.java:423)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538.invoke(enlive_html.clj:498)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538$fn__1539.invoke(enlive_html.clj:498)
    at clojure.core$map$fn__4087.invoke(core.clj:2434)
    at clojure.lang.LazySeq.sval(LazySeq.java:42)
    at clojure.lang.LazySeq.seq(LazySeq.java:60)
    at clojure.lang.Cons.next(Cons.java:39)
    at clojure.lang.RT.boundedLength(RT.java:1633)
    at clojure.lang.RestFn.applyTo(RestFn.java:130)
    at clojure.core$apply.invoke(core.clj:601)
    at clojure.core$mapcat.doInvoke(core.clj:2461)
    at clojure.lang.RestFn.invoke(RestFn.java:423)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538.invoke(enlive_html.clj:498)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538$fn__1539.invoke(enlive_html.clj:498)
    at clojure.core$map$fn__4087.invoke(core.clj:2434)
    at clojure.lang.LazySeq.sval(LazySeq.java:42)
    at clojure.lang.LazySeq.seq(LazySeq.java:60)
    at clojure.lang.Cons.next(Cons.java:39)
    at clojure.lang.RT.boundedLength(RT.java:1633)
    at clojure.lang.RestFn.applyTo(RestFn.java:130)
    at clojure.core$apply.invoke(core.clj:601)
    at clojure.core$mapcat.doInvoke(core.clj:2461)
    at clojure.lang.RestFn.invoke(RestFn.java:423)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538.invoke(enlive_html.clj:498)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538$fn__1539.invoke(enlive_html.clj:498)
    at clojure.core$map$fn__4087.invoke(core.clj:2434)
    at clojure.lang.LazySeq.sval(LazySeq.java:42)
    at clojure.lang.LazySeq.seq(LazySeq.java:60)
    at clojure.lang.Cons.next(Cons.java:39)
    at clojure.lang.RT.boundedLength(RT.java:1633)
    at clojure.lang.RestFn.applyTo(RestFn.java:130)
    at clojure.core$apply.invoke(core.clj:601)
    at clojure.core$mapcat.doInvoke(core.clj:2461)
    at clojure.lang.RestFn.invoke(RestFn.java:423)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538.invoke(enlive_html.clj:498)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538$fn__1539.invoke(enlive_html.clj:498)
    at clojure.core$map$fn__4087.invoke(core.clj:2434)
    at clojure.lang.LazySeq.sval(LazySeq.java:42)
    at clojure.lang.LazySeq.seq(LazySeq.java:60)
    at clojure.lang.Cons.next(Cons.java:39)
    at clojure.lang.RT.boundedLength(RT.java:1633)
    at clojure.lang.RestFn.applyTo(RestFn.java:130)
    at clojure.core$apply.invoke(core.clj:601)
    at clojure.core$mapcat.doInvoke(core.clj:2461)
    at clojure.lang.RestFn.invoke(RestFn.java:423)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538.invoke(enlive_html.clj:498)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538$fn__1539.invoke(enlive_html.clj:498)
    at clojure.core$map$fn__4087.invoke(core.clj:2434)
    at clojure.lang.LazySeq.sval(LazySeq.java:42)
    at clojure.lang.LazySeq.seq(LazySeq.java:60)
    at clojure.lang.Cons.next(Cons.java:39)
    at clojure.lang.RT.boundedLength(RT.java:1633)
    at clojure.lang.RestFn.applyTo(RestFn.java:130)
    at clojure.core$apply.invoke(core.clj:601)
    at clojure.core$mapcat.doInvoke(core.clj:2461)
    at clojure.lang.RestFn.invoke(RestFn.java:423)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538.invoke(enlive_html.clj:498)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538$fn__1539.invoke(enlive_html.clj:498)
    at clojure.core$map$fn__4087.invoke(core.clj:2434)
    at clojure.lang.LazySeq.sval(LazySeq.java:42)
    at clojure.lang.LazySeq.seq(LazySeq.java:60)
    at clojure.lang.Cons.next(Cons.java:39)
    at clojure.lang.RT.boundedLength(RT.java:1633)
    at clojure.lang.RestFn.applyTo(RestFn.java:130)
    at clojure.core$apply.invoke(core.clj:601)
    at clojure.core$mapcat.doInvoke(core.clj:2461)
    at clojure.lang.RestFn.invoke(RestFn.java:423)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538.invoke(enlive_html.clj:498)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538$fn__1539.invoke(enlive_html.clj:498)
    at clojure.core$map$fn__4087.invoke(core.clj:2434)
    at clojure.lang.LazySeq.sval(LazySeq.java:42)
    at clojure.lang.LazySeq.seq(LazySeq.java:60)
    at clojure.lang.Cons.next(Cons.java:39)
    at clojure.lang.RT.boundedLength(RT.java:1633)
    at clojure.lang.RestFn.applyTo(RestFn.java:130)
    at clojure.core$apply.invoke(core.clj:601)
    at clojure.core$mapcat.doInvoke(core.clj:2461)
    at clojure.lang.RestFn.invoke(RestFn.java:423)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538.invoke(enlive_html.clj:498)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538$fn__1539.invoke(enlive_html.clj:498)
    at clojure.core$map$fn__4087.invoke(core.clj:2434)
    at clojure.lang.LazySeq.sval(LazySeq.java:42)
    at clojure.lang.LazySeq.seq(LazySeq.java:60)
    at clojure.lang.Cons.next(Cons.java:39)
    at clojure.lang.RT.boundedLength(RT.java:1633)
    at clojure.lang.RestFn.applyTo(RestFn.java:130)
    at clojure.core$apply.invoke(core.clj:601)
    at clojure.core$mapcat.doInvoke(core.clj:2461)
    at clojure.lang.RestFn.invoke(RestFn.java:423)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538.invoke(enlive_html.clj:498)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538$fn__1539.invoke(enlive_html.clj:498)
    at clojure.core$map$fn__4087.invoke(core.clj:2434)
    at clojure.lang.LazySeq.sval(LazySeq.java:42)
    at clojure.lang.LazySeq.seq(LazySeq.java:60)
    at clojure.lang.Cons.next(Cons.java:39)
    at clojure.lang.RT.boundedLength(RT.java:1633)
    at clojure.lang.RestFn.applyTo(RestFn.java:130)
    at clojure.core$apply.invoke(core.clj:601)
    at clojure.core$mapcat.doInvoke(core.clj:2461)
    at clojure.lang.RestFn.invoke(RestFn.java:423)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538.invoke(enlive_html.clj:498)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538$fn__1539.invoke(enlive_html.clj:498)
    at clojure.core$map$fn__4087.invoke(core.clj:2434)
    at clojure.lang.LazySeq.sval(LazySeq.java:42)
    at clojure.lang.LazySeq.seq(LazySeq.java:60)
    at clojure.lang.Cons.next(Cons.java:39)
    at clojure.lang.RT.boundedLength(RT.java:1633)
    at clojure.lang.RestFn.applyTo(RestFn.java:130)
    at clojure.core$apply.invoke(core.clj:601)
    at clojure.core$mapcat.doInvoke(core.clj:2461)
    at clojure.lang.RestFn.invoke(RestFn.java:423)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538.invoke(enlive_html.clj:498)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538$fn__1539.invoke(enlive_html.clj:498)
    at clojure.core$map$fn__4087.invoke(core.clj:2434)
    at clojure.lang.LazySeq.sval(LazySeq.java:42)
    at clojure.lang.LazySeq.seq(LazySeq.java:60)
    at clojure.lang.Cons.next(Cons.java:39)
    at clojure.lang.RT.boundedLength(RT.java:1633)
    at clojure.lang.RestFn.applyTo(RestFn.java:130)
    at clojure.core$apply.invoke(core.clj:601)
    at clojure.core$mapcat.doInvoke(core.clj:2461)
    at clojure.lang.RestFn.invoke(RestFn.java:423)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538.invoke(enlive_html.clj:498)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538$fn__1539.invoke(enlive_html.clj:498)
    at clojure.core$map$fn__4087.invoke(core.clj:2434)
    at clojure.lang.LazySeq.sval(LazySeq.java:42)
    at clojure.lang.LazySeq.seq(LazySeq.java:60)
    at clojure.lang.Cons.next(Cons.java:39)
    at clojure.lang.RT.boundedLength(RT.java:1633)
    at clojure.lang.RestFn.applyTo(RestFn.java:130)
    at clojure.core$apply.invoke(core.clj:601)
    at clojure.core$mapcat.doInvoke(core.clj:2461)
    at clojure.lang.RestFn.invoke(RestFn.java:423)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538.invoke(enlive_html.clj:498)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538$fn__1539.invoke(enlive_html.clj:498)
    at clojure.core$map$fn__4087.invoke(core.clj:2434)
    at clojure.lang.LazySeq.sval(LazySeq.java:42)
    at clojure.lang.LazySeq.seq(LazySeq.java:60)
    at clojure.lang.Cons.next(Cons.java:39)
    at clojure.lang.RT.boundedLength(RT.java:1633)
    at clojure.lang.RestFn.applyTo(RestFn.java:130)
    at clojure.core$apply.invoke(core.clj:601)
    at clojure.core$mapcat.doInvoke(core.clj:2461)
    at clojure.lang.RestFn.invoke(RestFn.java:423)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538.invoke(enlive_html.clj:498)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538$fn__1539.invoke(enlive_html.clj:498)
    at clojure.core$map$fn__4087.invoke(core.clj:2434)
    at clojure.lang.LazySeq.sval(LazySeq.java:42)
    at clojure.lang.LazySeq.seq(LazySeq.java:60)
    at clojure.lang.Cons.next(Cons.java:39)
    at clojure.lang.RT.boundedLength(RT.java:1633)
    at clojure.lang.RestFn.applyTo(RestFn.java:130)
    at clojure.core$apply.invoke(core.clj:601)
    at clojure.core$mapcat.doInvoke(core.clj:2461)
    at clojure.lang.RestFn.invoke(RestFn.java:423)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538.invoke(enlive_html.clj:498)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538$fn__1539.invoke(enlive_html.clj:498)
    at clojure.core$map$fn__4087.invoke(core.clj:2434)
    at clojure.lang.LazySeq.sval(LazySeq.java:42)
    at clojure.lang.LazySeq.seq(LazySeq.java:60)
    at clojure.lang.Cons.next(Cons.java:39)
    at clojure.lang.RT.boundedLength(RT.java:1633)
    at clojure.lang.RestFn.applyTo(RestFn.java:130)
    at clojure.core$apply.invoke(core.clj:601)
    at clojure.core$mapcat.doInvoke(core.clj:2461)
    at clojure.lang.RestFn.invoke(RestFn.java:423)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538.invoke(enlive_html.clj:498)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538$fn__1539.invoke(enlive_html.clj:498)
    at clojure.core$map$fn__4087.invoke(core.clj:2434)
    at clojure.lang.LazySeq.sval(LazySeq.java:42)
    at clojure.lang.LazySeq.seq(LazySeq.java:60)
    at clojure.lang.Cons.next(Cons.java:39)
    at clojure.lang.RT.boundedLength(RT.java:1633)
    at clojure.lang.RestFn.applyTo(RestFn.java:130)
    at clojure.core$apply.invoke(core.clj:601)
    at clojure.core$mapcat.doInvoke(core.clj:2461)
    at clojure.lang.RestFn.invoke(RestFn.java:423)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538.invoke(enlive_html.clj:498)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538$fn__1539.invoke(enlive_html.clj:498)
    at clojure.core$map$fn__4087.invoke(core.clj:2434)
    at clojure.lang.LazySeq.sval(LazySeq.java:42)
    at clojure.lang.LazySeq.seq(LazySeq.java:60)
    at clojure.lang.Cons.next(Cons.java:39)
    at clojure.lang.RT.boundedLength(RT.java:1633)
    at clojure.lang.RestFn.applyTo(RestFn.java:130)
    at clojure.core$apply.invoke(core.clj:601)
    at clojure.core$mapcat.doInvoke(core.clj:2461)
    at clojure.lang.RestFn.invoke(RestFn.java:423)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538.invoke(enlive_html.clj:498)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538$fn__1539.invoke(enlive_html.clj:498)
    at clojure.core$map$fn__4087.invoke(core.clj:2434)
    at clojure.lang.LazySeq.sval(LazySeq.java:42)
    at clojure.lang.LazySeq.seq(LazySeq.java:60)
    at clojure.lang.Cons.next(Cons.java:39)
    at clojure.lang.RT.boundedLength(RT.java:1633)
    at clojure.lang.RestFn.applyTo(RestFn.java:130)
    at clojure.core$apply.invoke(core.clj:601)
    at clojure.core$mapcat.doInvoke(core.clj:2461)
    at clojure.lang.RestFn.invoke(RestFn.java:423)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538.invoke(enlive_html.clj:498)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538$fn__1539.invoke(enlive_html.clj:498)
    at clojure.core$map$fn__4087.invoke(core.clj:2434)
    at clojure.lang.LazySeq.sval(LazySeq.java:42)
    at clojure.lang.LazySeq.seq(LazySeq.java:60)
    at clojure.lang.Cons.next(Cons.java:39)
    at clojure.lang.RT.boundedLength(RT.java:1633)
    at clojure.lang.RestFn.applyTo(RestFn.java:130)
    at clojure.core$apply.invoke(core.clj:601)
    at clojure.core$mapcat.doInvoke(core.clj:2461)
    at clojure.lang.RestFn.invoke(RestFn.java:423)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538.invoke(enlive_html.clj:498)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538$fn__1539.invoke(enlive_html.clj:498)
    at clojure.core$map$fn__4087.invoke(core.clj:2434)
    at clojure.lang.LazySeq.sval(LazySeq.java:42)
    at clojure.lang.LazySeq.seq(LazySeq.java:60)
    at clojure.lang.Cons.next(Cons.java:39)
    at clojure.lang.RT.boundedLength(RT.java:1633)
    at clojure.lang.RestFn.applyTo(RestFn.java:130)
    at clojure.core$apply.invoke(core.clj:601)
    at clojure.core$mapcat.doInvoke(core.clj:2461)
    at clojure.lang.RestFn.invoke(RestFn.java:423)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538.invoke(enlive_html.clj:498)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538$fn__1539.invoke(enlive_html.clj:498)
    at clojure.core$map$fn__4087.invoke(core.clj:2434)
    at clojure.lang.LazySeq.sval(LazySeq.java:42)
    at clojure.lang.LazySeq.seq(LazySeq.java:60)
    at clojure.lang.Cons.next(Cons.java:39)
    at clojure.lang.RT.boundedLength(RT.java:1633)
    at clojure.lang.RestFn.applyTo(RestFn.java:130)
    at clojure.core$apply.invoke(core.clj:601)
    at clojure.core$mapcat.doInvoke(core.clj:2461)
    at clojure.lang.RestFn.invoke(RestFn.java:423)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538.invoke(enlive_html.clj:498)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538$fn__1539.invoke(enlive_html.clj:498)
    at clojure.core$map$fn__4087.invoke(core.clj:2434)
    at clojure.lang.LazySeq.sval(LazySeq.java:42)
    at clojure.lang.LazySeq.seq(LazySeq.java:60)
    at clojure.lang.Cons.next(Cons.java:39)
    at clojure.lang.RT.boundedLength(RT.java:1633)
    at clojure.lang.RestFn.applyTo(RestFn.java:130)
    at clojure.core$apply.invoke(core.clj:601)
    at clojure.core$mapcat.doInvoke(core.clj:2461)
    at clojure.lang.RestFn.invoke(RestFn.java:423)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538.invoke(enlive_html.clj:498)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538$fn__1539.invoke(enlive_html.clj:498)
    at clojure.core$map$fn__4087.invoke(core.clj:2434)
    at clojure.lang.LazySeq.sval(LazySeq.java:42)
    at clojure.lang.LazySeq.seq(LazySeq.java:60)
    at clojure.lang.Cons.next(Cons.java:39)
    at clojure.lang.RT.boundedLength(RT.java:1633)
    at clojure.lang.RestFn.applyTo(RestFn.java:130)
    at clojure.core$apply.invoke(core.clj:601)
    at clojure.core$mapcat.doInvoke(core.clj:2461)
    at clojure.lang.RestFn.invoke(RestFn.java:423)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538.invoke(enlive_html.clj:498)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538$fn__1539.invoke(enlive_html.clj:498)
    at clojure.core$map$fn__4087.invoke(core.clj:2434)
    at clojure.lang.LazySeq.sval(LazySeq.java:42)
    at clojure.lang.LazySeq.seq(LazySeq.java:60)
    at clojure.lang.Cons.next(Cons.java:39)
    at clojure.lang.RT.boundedLength(RT.java:1633)
    at clojure.lang.RestFn.applyTo(RestFn.java:130)
    at clojure.core$apply.invoke(core.clj:601)
    at clojure.core$mapcat.doInvoke(core.clj:2461)
    at clojure.lang.RestFn.invoke(RestFn.java:423)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538.invoke(enlive_html.clj:498)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538$fn__1539.invoke(enlive_html.clj:498)
    at clojure.core$map$fn__4087.invoke(core.clj:2434)
    at clojure.lang.LazySeq.sval(LazySeq.java:42)
    at clojure.lang.LazySeq.seq(LazySeq.java:60)
    at clojure.lang.Cons.next(Cons.java:39)
    at clojure.lang.RT.boundedLength(RT.java:1633)
    at clojure.lang.RestFn.applyTo(RestFn.java:130)
    at clojure.core$apply.invoke(core.clj:601)
    at clojure.core$mapcat.doInvoke(core.clj:2461)
    at clojure.lang.RestFn.invoke(RestFn.java:423)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538.invoke(enlive_html.clj:498)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538$fn__1539.invoke(enlive_html.clj:498)
    at clojure.core$map$fn__4087.invoke(core.clj:2434)
    at clojure.lang.LazySeq.sval(LazySeq.java:42)
    at clojure.lang.LazySeq.seq(LazySeq.java:60)
    at clojure.lang.Cons.next(Cons.java:39)
    at clojure.lang.RT.boundedLength(RT.java:1633)
    at clojure.lang.RestFn.applyTo(RestFn.java:130)
    at clojure.core$apply.invoke(core.clj:601)
    at clojure.core$mapcat.doInvoke(core.clj:2461)
    at clojure.lang.RestFn.invoke(RestFn.java:423)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538.invoke(enlive_html.clj:498)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538$fn__1539.invoke(enlive_html.clj:498)
    at clojure.core$map$fn__4087.invoke(core.clj:2434)
    at clojure.lang.LazySeq.sval(LazySeq.java:42)
    at clojure.lang.LazySeq.seq(LazySeq.java:60)
    at clojure.lang.Cons.next(Cons.java:39)
    at clojure.lang.RT.boundedLength(RT.java:1633)
    at clojure.lang.RestFn.applyTo(RestFn.java:130)
    at clojure.core$apply.invoke(core.clj:601)
    at clojure.core$mapcat.doInvoke(core.clj:2461)
    at clojure.lang.RestFn.invoke(RestFn.java:423)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538.invoke(enlive_html.clj:498)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538$fn__1539.invoke(enlive_html.clj:498)
    at clojure.core$map$fn__4087.invoke(core.clj:2434)
    at clojure.lang.LazySeq.sval(LazySeq.java:42)
    at clojure.lang.LazySeq.seq(LazySeq.java:60)
    at clojure.lang.Cons.next(Cons.java:39)
    at clojure.lang.RT.boundedLength(RT.java:1633)
    at clojure.lang.RestFn.applyTo(RestFn.java:130)
    at clojure.core$apply.invoke(core.clj:601)
    at clojure.core$mapcat.doInvoke(core.clj:2461)
    at clojure.lang.RestFn.invoke(RestFn.java:423)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538.invoke(enlive_html.clj:498)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538$fn__1539.invoke(enlive_html.clj:498)
    at clojure.core$map$fn__4087.invoke(core.clj:2434)
    at clojure.lang.LazySeq.sval(LazySeq.java:42)
    at clojure.lang.LazySeq.seq(LazySeq.java:60)
    at clojure.lang.Cons.next(Cons.java:39)
    at clojure.lang.RT.boundedLength(RT.java:1633)
    at clojure.lang.RestFn.applyTo(RestFn.java:130)
    at clojure.core$apply.invoke(core.clj:601)
    at clojure.core$mapcat.doInvoke(core.clj:2461)
    at clojure.lang.RestFn.invoke(RestFn.java:423)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538.invoke(enlive_html.clj:498)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538$fn__1539.invoke(enlive_html.clj:498)
    at clojure.core$map$fn__4087.invoke(core.clj:2434)
    at clojure.lang.LazySeq.sval(LazySeq.java:42)
    at clojure.lang.LazySeq.seq(LazySeq.java:60)
    at clojure.lang.Cons.next(Cons.java:39)
    at clojure.lang.RT.boundedLength(RT.java:1633)
    at clojure.lang.RestFn.applyTo(RestFn.java:130)
    at clojure.core$apply.invoke(core.clj:601)
    at clojure.core$mapcat.doInvoke(core.clj:2461)
    at clojure.lang.RestFn.invoke(RestFn.java:423)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538.invoke(enlive_html.clj:498)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538$fn__1539.invoke(enlive_html.clj:498)
    at clojure.core$map$fn__4087.invoke(core.clj:2434)
    at clojure.lang.LazySeq.sval(LazySeq.java:42)
    at clojure.lang.LazySeq.seq(LazySeq.java:60)
    at clojure.lang.Cons.next(Cons.java:39)
    at clojure.lang.RT.boundedLength(RT.java:1633)
    at clojure.lang.RestFn.applyTo(RestFn.java:130)
    at clojure.core$apply.invoke(core.clj:601)
    at clojure.core$mapcat.doInvoke(core.clj:2461)
    at clojure.lang.RestFn.invoke(RestFn.java:423)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538.invoke(enlive_html.clj:498)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538$fn__1539.invoke(enlive_html.clj:498)
    at clojure.core$map$fn__4087.invoke(core.clj:2434)
    at clojure.lang.LazySeq.sval(LazySeq.java:42)
    at clojure.lang.LazySeq.seq(LazySeq.java:60)
    at clojure.lang.Cons.next(Cons.java:39)
    at clojure.lang.RT.boundedLength(RT.java:1633)
    at clojure.lang.RestFn.applyTo(RestFn.java:130)
    at clojure.core$apply.invoke(core.clj:601)
    at clojure.core$mapcat.doInvoke(core.clj:2461)
    at clojure.lang.RestFn.invoke(RestFn.java:423)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538.invoke(enlive_html.clj:498)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538$fn__1539.invoke(enlive_html.clj:498)
    at clojure.core$map$fn__4087.invoke(core.clj:2434)
    at clojure.lang.LazySeq.sval(LazySeq.java:42)
    at clojure.lang.LazySeq.seq(LazySeq.java:60)
    at clojure.lang.Cons.next(Cons.java:39)
    at clojure.lang.RT.boundedLength(RT.java:1633)
    at clojure.lang.RestFn.applyTo(RestFn.java:130)
    at clojure.core$apply.invoke(core.clj:601)
    at clojure.core$mapcat.doInvoke(core.clj:2461)
    at clojure.lang.RestFn.invoke(RestFn.java:423)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538.invoke(enlive_html.clj:498)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538$fn__1539.invoke(enlive_html.clj:498)
    at clojure.core$map$fn__4087.invoke(core.clj:2434)
    at clojure.lang.LazySeq.sval(LazySeq.java:42)
    at clojure.lang.LazySeq.seq(LazySeq.java:60)
    at clojure.lang.Cons.next(Cons.java:39)
    at clojure.lang.RT.boundedLength(RT.java:1633)
    at clojure.lang.RestFn.applyTo(RestFn.java:130)
    at clojure.core$apply.invoke(core.clj:601)
    at clojure.core$mapcat.doInvoke(core.clj:2461)
    at clojure.lang.RestFn.invoke(RestFn.java:423)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538.invoke(enlive_html.clj:498)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538$fn__1539.invoke(enlive_html.clj:498)
    at clojure.core$map$fn__4087.invoke(core.clj:2434)
    at clojure.lang.LazySeq.sval(LazySeq.java:42)
    at clojure.lang.LazySeq.seq(LazySeq.java:60)
    at clojure.lang.Cons.next(Cons.java:39)
    at clojure.lang.RT.boundedLength(RT.java:1633)
    at clojure.lang.RestFn.applyTo(RestFn.java:130)
    at clojure.core$apply.invoke(core.clj:601)
    at clojure.core$mapcat.doInvoke(core.clj:2461)
    at clojure.lang.RestFn.invoke(RestFn.java:423)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538.invoke(enlive_html.clj:498)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538$fn__1539.invoke(enlive_html.clj:498)
    at clojure.core$map$fn__4087.invoke(core.clj:2434)
    at clojure.lang.LazySeq.sval(LazySeq.java:42)
    at clojure.lang.LazySeq.seq(LazySeq.java:60)
    at clojure.lang.Cons.next(Cons.java:39)
    at clojure.lang.RT.boundedLength(RT.java:1633)
    at clojure.lang.RestFn.applyTo(RestFn.java:130)
    at clojure.core$apply.invoke(core.clj:601)
    at clojure.core$mapcat.doInvoke(core.clj:2461)
    at clojure.lang.RestFn.invoke(RestFn.java:423)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538.invoke(enlive_html.clj:498)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538$fn__1539.invoke(enlive_html.clj:498)
    at clojure.core$map$fn__4087.invoke(core.clj:2434)
    at clojure.lang.LazySeq.sval(LazySeq.java:42)
    at clojure.lang.LazySeq.seq(LazySeq.java:60)
    at clojure.lang.Cons.next(Cons.java:39)
    at clojure.lang.RT.boundedLength(RT.java:1633)
    at clojure.lang.RestFn.applyTo(RestFn.java:130)
    at clojure.core$apply.invoke(core.clj:601)
    at clojure.core$mapcat.doInvoke(core.clj:2461)
    at clojure.lang.RestFn.invoke(RestFn.java:423)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538.invoke(enlive_html.clj:498)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538$fn__1539.invoke(enlive_html.clj:498)
    at clojure.core$map$fn__4087.invoke(core.clj:2434)
    at clojure.lang.LazySeq.sval(LazySeq.java:42)
    at clojure.lang.LazySeq.seq(LazySeq.java:60)
    at clojure.lang.Cons.next(Cons.java:39)
    at clojure.lang.RT.boundedLength(RT.java:1633)
    at clojure.lang.RestFn.applyTo(RestFn.java:130)
    at clojure.core$apply.invoke(core.clj:601)
    at clojure.core$mapcat.doInvoke(core.clj:2461)
    at clojure.lang.RestFn.invoke(RestFn.java:423)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538.invoke(enlive_html.clj:498)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538$fn__1539.invoke(enlive_html.clj:498)
    at clojure.core$map$fn__4087.invoke(core.clj:2434)
    at clojure.lang.LazySeq.sval(LazySeq.java:42)
    at clojure.lang.LazySeq.seq(LazySeq.java:60)
    at clojure.lang.Cons.next(Cons.java:39)
    at clojure.lang.RT.boundedLength(RT.java:1633)
    at clojure.lang.RestFn.applyTo(RestFn.java:130)
    at clojure.core$apply.invoke(core.clj:601)
    at clojure.core$mapcat.doInvoke(core.clj:2461)
    at clojure.lang.RestFn.invoke(RestFn.java:423)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538.invoke(enlive_html.clj:498)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538$fn__1539.invoke(enlive_html.clj:498)
    at clojure.core$map$fn__4087.invoke(core.clj:2434)
    at clojure.lang.LazySeq.sval(LazySeq.java:42)
    at clojure.lang.LazySeq.seq(LazySeq.java:60)
    at clojure.lang.Cons.next(Cons.java:39)
    at clojure.lang.RT.boundedLength(RT.java:1633)
    at clojure.lang.RestFn.applyTo(RestFn.java:130)
    at clojure.core$apply.invoke(core.clj:601)
    at clojure.core$mapcat.doInvoke(core.clj:2461)
    at clojure.lang.RestFn.invoke(RestFn.java:423)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538.invoke(enlive_html.clj:498)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538$fn__1539.invoke(enlive_html.clj:498)
    at clojure.core$map$fn__4087.invoke(core.clj:2434)
    at clojure.lang.LazySeq.sval(LazySeq.java:42)
    at clojure.lang.LazySeq.seq(LazySeq.java:60)
    at clojure.lang.Cons.next(Cons.java:39)
    at clojure.lang.RT.boundedLength(RT.java:1633)
    at clojure.lang.RestFn.applyTo(RestFn.java:130)
    at clojure.core$apply.invoke(core.clj:601)
    at clojure.core$mapcat.doInvoke(core.clj:2461)
    at clojure.lang.RestFn.invoke(RestFn.java:423)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538.invoke(enlive_html.clj:498)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538$fn__1539.invoke(enlive_html.clj:498)
    at clojure.core$map$fn__4087.invoke(core.clj:2434)
    at clojure.lang.LazySeq.sval(LazySeq.java:42)
    at clojure.lang.LazySeq.seq(LazySeq.java:60)
    at clojure.lang.Cons.next(Cons.java:39)
    at clojure.lang.RT.boundedLength(RT.java:1633)
    at clojure.lang.RestFn.applyTo(RestFn.java:130)
    at clojure.core$apply.invoke(core.clj:601)
    at clojure.core$mapcat.doInvoke(core.clj:2461)
    at clojure.lang.RestFn.invoke(RestFn.java:423)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538.invoke(enlive_html.clj:498)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538$fn__1539.invoke(enlive_html.clj:498)
    at clojure.core$map$fn__4087.invoke(core.clj:2434)
    at clojure.lang.LazySeq.sval(LazySeq.java:42)
    at clojure.lang.LazySeq.seq(LazySeq.java:60)
    at clojure.lang.Cons.next(Cons.java:39)
    at clojure.lang.RT.boundedLength(RT.java:1633)
    at clojure.lang.RestFn.applyTo(RestFn.java:130)
    at clojure.core$apply.invoke(core.clj:601)
    at clojure.core$mapcat.doInvoke(core.clj:2461)
    at clojure.lang.RestFn.invoke(RestFn.java:423)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538.invoke(enlive_html.clj:498)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538$fn__1539.invoke(enlive_html.clj:498)
    at clojure.core$map$fn__4087.invoke(core.clj:2434)
    at clojure.lang.LazySeq.sval(LazySeq.java:42)
    at clojure.lang.LazySeq.seq(LazySeq.java:60)
    at clojure.lang.Cons.next(Cons.java:39)
    at clojure.lang.RT.boundedLength(RT.java:1633)
    at clojure.lang.RestFn.applyTo(RestFn.java:130)
    at clojure.core$apply.invoke(core.clj:601)
    at clojure.core$mapcat.doInvoke(core.clj:2461)
    at clojure.lang.RestFn.invoke(RestFn.java:423)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538.invoke(enlive_html.clj:498)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538$fn__1539.invoke(enlive_html.clj:498)
    at clojure.core$map$fn__4087.invoke(core.clj:2434)
    at clojure.lang.LazySeq.sval(LazySeq.java:42)
    at clojure.lang.LazySeq.seq(LazySeq.java:60)
    at clojure.lang.Cons.next(Cons.java:39)
    at clojure.lang.RT.boundedLength(RT.java:1633)
    at clojure.lang.RestFn.applyTo(RestFn.java:130)
    at clojure.core$apply.invoke(core.clj:601)
    at clojure.core$mapcat.doInvoke(core.clj:2461)
    at clojure.lang.RestFn.invoke(RestFn.java:423)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538.invoke(enlive_html.clj:498)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538$fn__1539.invoke(enlive_html.clj:498)
    at clojure.core$map$fn__4087.invoke(core.clj:2434)
    at clojure.lang.LazySeq.sval(LazySeq.java:42)
    at clojure.lang.LazySeq.seq(LazySeq.java:60)
    at clojure.lang.Cons.next(Cons.java:39)
    at clojure.lang.RT.boundedLength(RT.java:1633)
    at clojure.lang.RestFn.applyTo(RestFn.java:130)
    at clojure.core$apply.invoke(core.clj:601)
    at clojure.core$mapcat.doInvoke(core.clj:2461)
    at clojure.lang.RestFn.invoke(RestFn.java:423)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538.invoke(enlive_html.clj:498)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538$fn__1539.invoke(enlive_html.clj:498)
    at clojure.core$map$fn__4087.invoke(core.clj:2434)
    at clojure.lang.LazySeq.sval(LazySeq.java:42)
    at clojure.lang.LazySeq.seq(LazySeq.java:60)
    at clojure.lang.Cons.next(Cons.java:39)
    at clojure.lang.RT.boundedLength(RT.java:1633)
    at clojure.lang.RestFn.applyTo(RestFn.java:130)
    at clojure.core$apply.invoke(core.clj:601)
    at clojure.core$mapcat.doInvoke(core.clj:2461)
    at clojure.lang.RestFn.invoke(RestFn.java:423)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538.invoke(enlive_html.clj:498)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538$fn__1539.invoke(enlive_html.clj:498)
    at clojure.core$map$fn__4087.invoke(core.clj:2434)
    at clojure.lang.LazySeq.sval(LazySeq.java:42)
    at clojure.lang.LazySeq.seq(LazySeq.java:60)
    at clojure.lang.Cons.next(Cons.java:39)
    at clojure.lang.RT.boundedLength(RT.java:1633)
    at clojure.lang.RestFn.applyTo(RestFn.java:130)
    at clojure.core$apply.invoke(core.clj:601)
    at clojure.core$mapcat.doInvoke(core.clj:2461)
    at clojure.lang.RestFn.invoke(RestFn.java:423)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538.invoke(enlive_html.clj:498)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538$fn__1539.invoke(enlive_html.clj:498)
    at clojure.core$map$fn__4087.invoke(core.clj:2434)
    at clojure.lang.LazySeq.sval(LazySeq.java:42)
    at clojure.lang.LazySeq.seq(LazySeq.java:60)
    at clojure.lang.Cons.next(Cons.java:39)
    at clojure.lang.RT.boundedLength(RT.java:1633)
    at clojure.lang.RestFn.applyTo(RestFn.java:130)
    at clojure.core$apply.invoke(core.clj:601)
    at clojure.core$mapcat.doInvoke(core.clj:2461)
    at clojure.lang.RestFn.invoke(RestFn.java:423)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538.invoke(enlive_html.clj:498)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538$fn__1539.invoke(enlive_html.clj:498)
    at clojure.core$map$fn__4087.invoke(core.clj:2434)
    at clojure.lang.LazySeq.sval(LazySeq.java:42)
    at clojure.lang.LazySeq.seq(LazySeq.java:60)
    at clojure.lang.Cons.next(Cons.java:39)
    at clojure.lang.RT.boundedLength(RT.java:1633)
    at clojure.lang.RestFn.applyTo(RestFn.java:130)
    at clojure.core$apply.invoke(core.clj:601)
    at clojure.core$mapcat.doInvoke(core.clj:2461)
    at clojure.lang.RestFn.invoke(RestFn.java:423)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538.invoke(enlive_html.clj:498)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538$fn__1539.invoke(enlive_html.clj:498)
    at clojure.core$map$fn__4087.invoke(core.clj:2434)
    at clojure.lang.LazySeq.sval(LazySeq.java:42)
    at clojure.lang.LazySeq.seq(LazySeq.java:60)
    at clojure.lang.Cons.next(Cons.java:39)
    at clojure.lang.RT.boundedLength(RT.java:1633)
    at clojure.lang.RestFn.applyTo(RestFn.java:130)
    at clojure.core$apply.invoke(core.clj:601)
    at clojure.core$mapcat.doInvoke(core.clj:2461)
    at clojure.lang.RestFn.invoke(RestFn.java:423)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538.invoke(enlive_html.clj:498)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538$fn__1539.invoke(enlive_html.clj:498)
    at clojure.core$map$fn__4087.invoke(core.clj:2434)
    at clojure.lang.LazySeq.sval(LazySeq.java:42)
    at clojure.lang.LazySeq.seq(LazySeq.java:60)
    at clojure.lang.Cons.next(Cons.java:39)
    at clojure.lang.RT.boundedLength(RT.java:1633)
    at clojure.lang.RestFn.applyTo(RestFn.java:130)
    at clojure.core$apply.invoke(core.clj:601)
    at clojure.core$mapcat.doInvoke(core.clj:2461)
    at clojure.lang.RestFn.invoke(RestFn.java:423)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538.invoke(enlive_html.clj:498)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538$fn__1539.invoke(enlive_html.clj:498)
    at clojure.core$map$fn__4087.invoke(core.clj:2434)
    at clojure.lang.LazySeq.sval(LazySeq.java:42)
    at clojure.lang.LazySeq.seq(LazySeq.java:60)
    at clojure.lang.Cons.next(Cons.java:39)
    at clojure.lang.RT.boundedLength(RT.java:1633)
    at clojure.lang.RestFn.applyTo(RestFn.java:130)
    at clojure.core$apply.invoke(core.clj:601)
    at clojure.core$mapcat.doInvoke(core.clj:2461)
    at clojure.lang.RestFn.invoke(RestFn.java:423)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538.invoke(enlive_html.clj:498)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538$fn__1539.invoke(enlive_html.clj:498)
    at clojure.core$map$fn__4087.invoke(core.clj:2434)
    at clojure.lang.LazySeq.sval(LazySeq.java:42)
    at clojure.lang.LazySeq.seq(LazySeq.java:60)
    at clojure.lang.Cons.next(Cons.java:39)
    at clojure.lang.RT.boundedLength(RT.java:1633)
    at clojure.lang.RestFn.applyTo(RestFn.java:130)
    at clojure.core$apply.invoke(core.clj:601)
    at clojure.core$mapcat.doInvoke(core.clj:2461)
    at clojure.lang.RestFn.invoke(RestFn.java:423)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538.invoke(enlive_html.clj:498)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538$fn__1539.invoke(enlive_html.clj:498)
    at clojure.core$map$fn__4087.invoke(core.clj:2434)
    at clojure.lang.LazySeq.sval(LazySeq.java:42)
    at clojure.lang.LazySeq.seq(LazySeq.java:60)
    at clojure.lang.Cons.next(Cons.java:39)
    at clojure.lang.RT.boundedLength(RT.java:1633)
    at clojure.lang.RestFn.applyTo(RestFn.java:130)
    at clojure.core$apply.invoke(core.clj:601)
    at clojure.core$mapcat.doInvoke(core.clj:2461)
    at clojure.lang.RestFn.invoke(RestFn.java:423)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538.invoke(enlive_html.clj:498)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538$fn__1539.invoke(enlive_html.clj:498)
    at clojure.core$map$fn__4087.invoke(core.clj:2434)
    at clojure.lang.LazySeq.sval(LazySeq.java:42)
    at clojure.lang.LazySeq.seq(LazySeq.java:60)
    at clojure.lang.Cons.next(Cons.java:39)
    at clojure.lang.RT.boundedLength(RT.java:1633)
    at clojure.lang.RestFn.applyTo(RestFn.java:130)
    at clojure.core$apply.invoke(core.clj:601)
    at clojure.core$mapcat.doInvoke(core.clj:2461)
    at clojure.lang.RestFn.invoke(RestFn.java:423)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538.invoke(enlive_html.clj:498)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538$fn__1539.invoke(enlive_html.clj:498)
    at clojure.core$map$fn__4087.invoke(core.clj:2434)
    at clojure.lang.LazySeq.sval(LazySeq.java:42)
    at clojure.lang.LazySeq.seq(LazySeq.java:60)
    at clojure.lang.Cons.next(Cons.java:39)
    at clojure.lang.RT.boundedLength(RT.java:1633)
    at clojure.lang.RestFn.applyTo(RestFn.java:130)
    at clojure.core$apply.invoke(core.clj:601)
    at clojure.core$mapcat.doInvoke(core.clj:2461)
    at clojure.lang.RestFn.invoke(RestFn.java:423)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538.invoke(enlive_html.clj:498)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538$fn__1539.invoke(enlive_html.clj:498)
    at clojure.core$map$fn__4087.invoke(core.clj:2434)
    at clojure.lang.LazySeq.sval(LazySeq.java:42)
    at clojure.lang.LazySeq.seq(LazySeq.java:60)
    at clojure.lang.Cons.next(Cons.java:39)
    at clojure.lang.RT.boundedLength(RT.java:1633)
    at clojure.lang.RestFn.applyTo(RestFn.java:130)
    at clojure.core$apply.invoke(core.clj:601)
    at clojure.core$mapcat.doInvoke(core.clj:2461)
    at clojure.lang.RestFn.invoke(RestFn.java:423)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538.invoke(enlive_html.clj:498)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538$fn__1539.invoke(enlive_html.clj:498)
    at clojure.core$map$fn__4087.invoke(core.clj:2434)
    at clojure.lang.LazySeq.sval(LazySeq.java:42)
    at clojure.lang.LazySeq.seq(LazySeq.java:60)
    at clojure.lang.Cons.next(Cons.java:39)
    at clojure.lang.RT.boundedLength(RT.java:1633)
    at clojure.lang.RestFn.applyTo(RestFn.java:130)
    at clojure.core$apply.invoke(core.clj:601)
    at clojure.core$mapcat.doInvoke(core.clj:2461)
    at clojure.lang.RestFn.invoke(RestFn.java:423)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538.invoke(enlive_html.clj:498)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538$fn__1539.invoke(enlive_html.clj:498)
    at clojure.core$map$fn__4087.invoke(core.clj:2434)
    at clojure.lang.LazySeq.sval(LazySeq.java:42)
    at clojure.lang.LazySeq.seq(LazySeq.java:60)
    at clojure.lang.Cons.next(Cons.java:39)
    at clojure.lang.RT.boundedLength(RT.java:1633)
    at clojure.lang.RestFn.applyTo(RestFn.java:130)
    at clojure.core$apply.invoke(core.clj:601)
    at clojure.core$mapcat.doInvoke(core.clj:2461)
    at clojure.lang.RestFn.invoke(RestFn.java:423)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538.invoke(enlive_html.clj:498)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538$fn__1539.invoke(enlive_html.clj:498)
    at clojure.core$map$fn__4087.invoke(core.clj:2434)
    at clojure.lang.LazySeq.sval(LazySeq.java:42)
    at clojure.lang.LazySeq.seq(LazySeq.java:60)
    at clojure.lang.Cons.next(Cons.java:39)
    at clojure.lang.RT.boundedLength(RT.java:1633)
    at clojure.lang.RestFn.applyTo(RestFn.java:130)
    at clojure.core$apply.invoke(core.clj:601)
    at clojure.core$mapcat.doInvoke(core.clj:2461)
    at clojure.lang.RestFn.invoke(RestFn.java:423)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538.invoke(enlive_html.clj:498)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538$fn__1539.invoke(enlive_html.clj:498)
    at clojure.core$map$fn__4087.invoke(core.clj:2434)
    at clojure.lang.LazySeq.sval(LazySeq.java:42)
    at clojure.lang.LazySeq.seq(LazySeq.java:60)
    at clojure.lang.Cons.next(Cons.java:39)
    at clojure.lang.RT.boundedLength(RT.java:1633)
    at clojure.lang.RestFn.applyTo(RestFn.java:130)
    at clojure.core$apply.invoke(core.clj:601)
    at clojure.core$mapcat.doInvoke(core.clj:2461)
    at clojure.lang.RestFn.invoke(RestFn.java:423)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538.invoke(enlive_html.clj:498)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538$fn__1539.invoke(enlive_html.clj:498)
    at clojure.core$map$fn__4087.invoke(core.clj:2434)
    at clojure.lang.LazySeq.sval(LazySeq.java:42)
    at clojure.lang.LazySeq.seq(LazySeq.java:60)
    at clojure.lang.Cons.next(Cons.java:39)
    at clojure.lang.RT.boundedLength(RT.java:1633)
    at clojure.lang.RestFn.applyTo(RestFn.java:130)
    at clojure.core$apply.invoke(core.clj:601)
    at clojure.core$mapcat.doInvoke(core.clj:2461)
    at clojure.lang.RestFn.invoke(RestFn.java:423)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538.invoke(enlive_html.clj:498)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538$fn__1539.invoke(enlive_html.clj:498)
    at clojure.core$map$fn__4087.invoke(core.clj:2434)
    at clojure.lang.LazySeq.sval(LazySeq.java:42)
    at clojure.lang.LazySeq.seq(LazySeq.java:60)
    at clojure.lang.Cons.next(Cons.java:39)
    at clojure.lang.RT.boundedLength(RT.java:1633)
    at clojure.lang.RestFn.applyTo(RestFn.java:130)
    at clojure.core$apply.invoke(core.clj:601)
    at clojure.core$mapcat.doInvoke(core.clj:2461)
    at clojure.lang.RestFn.invoke(RestFn.java:423)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538.invoke(enlive_html.clj:498)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538$fn__1539.invoke(enlive_html.clj:498)
    at clojure.core$map$fn__4087.invoke(core.clj:2434)
    at clojure.lang.LazySeq.sval(LazySeq.java:42)
    at clojure.lang.LazySeq.seq(LazySeq.java:60)
    at clojure.lang.Cons.next(Cons.java:39)
    at clojure.lang.RT.boundedLength(RT.java:1633)
    at clojure.lang.RestFn.applyTo(RestFn.java:130)
    at clojure.core$apply.invoke(core.clj:601)
    at clojure.core$mapcat.doInvoke(core.clj:2461)
    at clojure.lang.RestFn.invoke(RestFn.java:423)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538.invoke(enlive_html.clj:498)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538$fn__1539.invoke(enlive_html.clj:498)
    at clojure.core$map$fn__4087.invoke(core.clj:2434)
    at clojure.lang.LazySeq.sval(LazySeq.java:42)
    at clojure.lang.LazySeq.seq(LazySeq.java:60)
    at clojure.lang.Cons.next(Cons.java:39)
    at clojure.lang.RT.boundedLength(RT.java:1633)
    at clojure.lang.RestFn.applyTo(RestFn.java:130)
    at clojure.core$apply.invoke(core.clj:601)
    at clojure.core$mapcat.doInvoke(core.clj:2461)
    at clojure.lang.RestFn.invoke(RestFn.java:423)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538.invoke(enlive_html.clj:498)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538$fn__1539.invoke(enlive_html.clj:498)
    at clojure.core$map$fn__4087.invoke(core.clj:2434)
    at clojure.lang.LazySeq.sval(LazySeq.java:42)
    at clojure.lang.LazySeq.seq(LazySeq.java:60)
    at clojure.lang.Cons.next(Cons.java:39)
    at clojure.lang.RT.boundedLength(RT.java:1633)
    at clojure.lang.RestFn.applyTo(RestFn.java:130)
    at clojure.core$apply.invoke(core.clj:601)
    at clojure.core$mapcat.doInvoke(core.clj:2461)
    at clojure.lang.RestFn.invoke(RestFn.java:423)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538.invoke(enlive_html.clj:498)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538$fn__1539.invoke(enlive_html.clj:498)
    at clojure.core$map$fn__4087.invoke(core.clj:2434)
    at clojure.lang.LazySeq.sval(LazySeq.java:42)
    at clojure.lang.LazySeq.seq(LazySeq.java:60)
    at clojure.lang.Cons.next(Cons.java:39)
    at clojure.lang.RT.boundedLength(RT.java:1633)
    at clojure.lang.RestFn.applyTo(RestFn.java:130)
    at clojure.core$apply.invoke(core.clj:601)
    at clojure.core$mapcat.doInvoke(core.clj:2461)
    at clojure.lang.RestFn.invoke(RestFn.java:423)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538.invoke(enlive_html.clj:498)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538$fn__1539.invoke(enlive_html.clj:498)
    at clojure.core$map$fn__4087.invoke(core.clj:2434)
    at clojure.lang.LazySeq.sval(LazySeq.java:42)
    at clojure.lang.LazySeq.seq(LazySeq.java:60)
    at clojure.lang.Cons.next(Cons.java:39)
    at clojure.lang.RT.boundedLength(RT.java:1633)
    at clojure.lang.RestFn.applyTo(RestFn.java:130)
    at clojure.core$apply.invoke(core.clj:601)
    at clojure.core$mapcat.doInvoke(core.clj:2461)
    at clojure.lang.RestFn.invoke(RestFn.java:423)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538.invoke(enlive_html.clj:498)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538$fn__1539.invoke(enlive_html.clj:498)
    at clojure.core$map$fn__4087.invoke(core.clj:2434)
    at clojure.lang.LazySeq.sval(LazySeq.java:42)
    at clojure.lang.LazySeq.seq(LazySeq.java:60)
    at clojure.lang.Cons.next(Cons.java:39)
    at clojure.lang.RT.boundedLength(RT.java:1633)
    at clojure.lang.RestFn.applyTo(RestFn.java:130)
    at clojure.core$apply.invoke(core.clj:601)
    at clojure.core$mapcat.doInvoke(core.clj:2461)
    at clojure.lang.RestFn.invoke(RestFn.java:423)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538.invoke(enlive_html.clj:498)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538$fn__1539.invoke(enlive_html.clj:498)
    at clojure.core$map$fn__4087.invoke(core.clj:2434)
    at clojure.lang.LazySeq.sval(LazySeq.java:42)
    at clojure.lang.LazySeq.seq(LazySeq.java:60)
    at clojure.lang.Cons.next(Cons.java:39)
    at clojure.lang.RT.boundedLength(RT.java:1633)
    at clojure.lang.RestFn.applyTo(RestFn.java:130)
    at clojure.core$apply.invoke(core.clj:601)
    at clojure.core$mapcat.doInvoke(core.clj:2461)
    at clojure.lang.RestFn.invoke(RestFn.java:423)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538.invoke(enlive_html.clj:498)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538$fn__1539.invoke(enlive_html.clj:498)
    at clojure.core$map$fn__4087.invoke(core.clj:2434)
    at clojure.lang.LazySeq.sval(LazySeq.java:42)
    at clojure.lang.LazySeq.seq(LazySeq.java:60)
    at clojure.lang.Cons.next(Cons.java:39)
    at clojure.lang.RT.boundedLength(RT.java:1633)
    at clojure.lang.RestFn.applyTo(RestFn.java:130)
    at clojure.core$apply.invoke(core.clj:601)
    at clojure.core$mapcat.doInvoke(core.clj:2461)
    at clojure.lang.RestFn.invoke(RestFn.java:423)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538.invoke(enlive_html.clj:498)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538$fn__1539.invoke(enlive_html.clj:498)
    at clojure.core$map$fn__4087.invoke(core.clj:2434)
    at clojure.lang.LazySeq.sval(LazySeq.java:42)
    at clojure.lang.LazySeq.seq(LazySeq.java:60)
    at clojure.lang.Cons.next(Cons.java:39)
    at clojure.lang.RT.boundedLength(RT.java:1633)
    at clojure.lang.RestFn.applyTo(RestFn.java:130)
    at clojure.core$apply.invoke(core.clj:601)
    at clojure.core$mapcat.doInvoke(core.clj:2461)
    at clojure.lang.RestFn.invoke(RestFn.java:423)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538.invoke(enlive_html.clj:498)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538$fn__1539.invoke(enlive_html.clj:498)
    at clojure.core$map$fn__4087.invoke(core.clj:2434)
    at clojure.lang.LazySeq.sval(LazySeq.java:42)
    at clojure.lang.LazySeq.seq(LazySeq.java:60)
    at clojure.lang.Cons.next(Cons.java:39)
    at clojure.lang.RT.boundedLength(RT.java:1633)
    at clojure.lang.RestFn.applyTo(RestFn.java:130)
    at clojure.core$apply.invoke(core.clj:601)
    at clojure.core$mapcat.doInvoke(core.clj:2461)
    at clojure.lang.RestFn.invoke(RestFn.java:423)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538.invoke(enlive_html.clj:498)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538$fn__1539.invoke(enlive_html.clj:498)
    at clojure.core$map$fn__4087.invoke(core.clj:2434)
    at clojure.lang.LazySeq.sval(LazySeq.java:42)
    at clojure.lang.LazySeq.seq(LazySeq.java:60)
    at clojure.lang.Cons.next(Cons.java:39)
    at clojure.lang.RT.boundedLength(RT.java:1633)
    at clojure.lang.RestFn.applyTo(RestFn.java:130)
    at clojure.core$apply.invoke(core.clj:601)
    at clojure.core$mapcat.doInvoke(core.clj:2461)
    at clojure.lang.RestFn.invoke(RestFn.java:423)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538.invoke(enlive_html.clj:498)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538$fn__1539.invoke(enlive_html.clj:498)
    at clojure.core$map$fn__4087.invoke(core.clj:2434)
    at clojure.lang.LazySeq.sval(LazySeq.java:42)
    at clojure.lang.LazySeq.seq(LazySeq.java:60)
    at clojure.lang.Cons.next(Cons.java:39)
    at clojure.lang.RT.boundedLength(RT.java:1633)
    at clojure.lang.RestFn.applyTo(RestFn.java:130)
    at clojure.core$apply.invoke(core.clj:601)
    at clojure.core$mapcat.doInvoke(core.clj:2461)
    at clojure.lang.RestFn.invoke(RestFn.java:423)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538.invoke(enlive_html.clj:498)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538$fn__1539.invoke(enlive_html.clj:498)
    at clojure.core$map$fn__4087.invoke(core.clj:2434)
    at clojure.lang.LazySeq.sval(LazySeq.java:42)
    at clojure.lang.LazySeq.seq(LazySeq.java:60)
    at clojure.lang.Cons.next(Cons.java:39)
    at clojure.lang.RT.boundedLength(RT.java:1633)
    at clojure.lang.RestFn.applyTo(RestFn.java:130)
    at clojure.core$apply.invoke(core.clj:601)
    at clojure.core$mapcat.doInvoke(core.clj:2461)
    at clojure.lang.RestFn.invoke(RestFn.java:423)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538.invoke(enlive_html.clj:498)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538$fn__1539.invoke(enlive_html.clj:498)
    at clojure.core$map$fn__4087.invoke(core.clj:2434)
    at clojure.lang.LazySeq.sval(LazySeq.java:42)
    at clojure.lang.LazySeq.seq(LazySeq.java:60)
    at clojure.lang.Cons.next(Cons.java:39)
    at clojure.lang.RT.boundedLength(RT.java:1633)
    at clojure.lang.RestFn.applyTo(RestFn.java:130)
    at clojure.core$apply.invoke(core.clj:601)
    at clojure.core$mapcat.doInvoke(core.clj:2461)
    at clojure.lang.RestFn.invoke(RestFn.java:423)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538.invoke(enlive_html.clj:498)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538$fn__1539.invoke(enlive_html.clj:498)
    at clojure.core$map$fn__4087.invoke(core.clj:2434)
    at clojure.lang.LazySeq.sval(LazySeq.java:42)
    at clojure.lang.LazySeq.seq(LazySeq.java:60)
    at clojure.lang.Cons.next(Cons.java:39)
    at clojure.lang.RT.boundedLength(RT.java:1633)
    at clojure.lang.RestFn.applyTo(RestFn.java:130)
    at clojure.core$apply.invoke(core.clj:601)
    at clojure.core$mapcat.doInvoke(core.clj:2461)
    at clojure.lang.RestFn.invoke(RestFn.java:423)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538.invoke(enlive_html.clj:498)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538$fn__1539.invoke(enlive_html.clj:498)
    at clojure.core$map$fn__4087.invoke(core.clj:2434)
    at clojure.lang.LazySeq.sval(LazySeq.java:42)
    at clojure.lang.LazySeq.seq(LazySeq.java:60)
    at clojure.lang.Cons.next(Cons.java:39)
    at clojure.lang.RT.boundedLength(RT.java:1633)
    at clojure.lang.RestFn.applyTo(RestFn.java:130)
    at clojure.core$apply.invoke(core.clj:601)
    at clojure.core$mapcat.doInvoke(core.clj:2461)
    at clojure.lang.RestFn.invoke(RestFn.java:423)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538.invoke(enlive_html.clj:498)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538$fn__1539.invoke(enlive_html.clj:498)
    at clojure.core$map$fn__4087.invoke(core.clj:2434)
    at clojure.lang.LazySeq.sval(LazySeq.java:42)
    at clojure.lang.LazySeq.seq(LazySeq.java:60)
    at clojure.lang.Cons.next(Cons.java:39)
    at clojure.lang.RT.boundedLength(RT.java:1633)
    at clojure.lang.RestFn.applyTo(RestFn.java:130)
    at clojure.core$apply.invoke(core.clj:601)
    at clojure.core$mapcat.doInvoke(core.clj:2461)
    at clojure.lang.RestFn.invoke(RestFn.java:423)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538.invoke(enlive_html.clj:498)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538$fn__1539.invoke(enlive_html.clj:498)
    at clojure.core$map$fn__4087.invoke(core.clj:2434)
    at clojure.lang.LazySeq.sval(LazySeq.java:42)
    at clojure.lang.LazySeq.seq(LazySeq.java:60)
    at clojure.lang.Cons.next(Cons.java:39)
    at clojure.lang.RT.boundedLength(RT.java:1633)
    at clojure.lang.RestFn.applyTo(RestFn.java:130)
    at clojure.core$apply.invoke(core.clj:601)
    at clojure.core$mapcat.doInvoke(core.clj:2461)
    at clojure.lang.RestFn.invoke(RestFn.java:423)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538.invoke(enlive_html.clj:498)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538$fn__1539.invoke(enlive_html.clj:498)
    at clojure.core$map$fn__4087.invoke(core.clj:2434)
    at clojure.lang.LazySeq.sval(LazySeq.java:42)
    at clojure.lang.LazySeq.seq(LazySeq.java:60)
    at clojure.lang.Cons.next(Cons.java:39)
    at clojure.lang.RT.boundedLength(RT.java:1633)
    at clojure.lang.RestFn.applyTo(RestFn.java:130)
    at clojure.core$apply.invoke(core.clj:601)
    at clojure.core$mapcat.doInvoke(core.clj:2461)
    at clojure.lang.RestFn.invoke(RestFn.java:423)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538.invoke(enlive_html.clj:498)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538$fn__1539.invoke(enlive_html.clj:498)
    at clojure.core$map$fn__4087.invoke(core.clj:2434)
    at clojure.lang.LazySeq.sval(LazySeq.java:42)
    at clojure.lang.LazySeq.seq(LazySeq.java:60)
    at clojure.lang.Cons.next(Cons.java:39)
    at clojure.lang.RT.boundedLength(RT.java:1633)
    at clojure.lang.RestFn.applyTo(RestFn.java:130)
    at clojure.core$apply.invoke(core.clj:601)
    at clojure.core$mapcat.doInvoke(core.clj:2461)
    at clojure.lang.RestFn.invoke(RestFn.java:423)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538.invoke(enlive_html.clj:498)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538$fn__1539.invoke(enlive_html.clj:498)
    at clojure.core$map$fn__4087.invoke(core.clj:2434)
    at clojure.lang.LazySeq.sval(LazySeq.java:42)
    at clojure.lang.LazySeq.seq(LazySeq.java:60)
    at clojure.lang.Cons.next(Cons.java:39)
    at clojure.lang.RT.boundedLength(RT.java:1633)
    at clojure.lang.RestFn.applyTo(RestFn.java:130)
    at clojure.core$apply.invoke(core.clj:601)
    at clojure.core$mapcat.doInvoke(core.clj:2461)
    at clojure.lang.RestFn.invoke(RestFn.java:423)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538.invoke(enlive_html.clj:498)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538$fn__1539.invoke(enlive_html.clj:498)
    at clojure.core$map$fn__4087.invoke(core.clj:2434)
    at clojure.lang.LazySeq.sval(LazySeq.java:42)
    at clojure.lang.LazySeq.seq(LazySeq.java:60)
    at clojure.lang.Cons.next(Cons.java:39)
    at clojure.lang.RT.boundedLength(RT.java:1633)
    at clojure.lang.RestFn.applyTo(RestFn.java:130)
    at clojure.core$apply.invoke(core.clj:601)
    at clojure.core$mapcat.doInvoke(core.clj:2461)
    at clojure.lang.RestFn.invoke(RestFn.java:423)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538.invoke(enlive_html.clj:498)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538$fn__1539.invoke(enlive_html.clj:498)
    at clojure.core$map$fn__4087.invoke(core.clj:2434)
    at clojure.lang.LazySeq.sval(LazySeq.java:42)
    at clojure.lang.LazySeq.seq(LazySeq.java:60)
    at clojure.lang.Cons.next(Cons.java:39)
    at clojure.lang.RT.boundedLength(RT.java:1633)
    at clojure.lang.RestFn.applyTo(RestFn.java:130)
    at clojure.core$apply.invoke(core.clj:601)
    at clojure.core$mapcat.doInvoke(core.clj:2461)
    at clojure.lang.RestFn.invoke(RestFn.java:423)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538.invoke(enlive_html.clj:498)
    at net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__1538$fn__1539.invoke(enlive_html.clj:498)

add necessary project.clj dependency to readme

I think it's helpful to add the current release version dependency information to the readme as is done with other libraries. I often find myself wanting to know what the latest release version number is and getting here only to be met with it's absence in that very long readme.

John

Support for UTF8

It seems it doesn't support UTF 8 encoding. It would be great if it supports.

Lockstep transformation throws ClassCastException

Lockstep transforms trigger exceptions due to faulty usage of transients

user=> (use 'net.cgrand.enlive-html)
user=> (at (html [:html [:a "foo"][:b "bar"]])
         :lockstep {[:a] (content "1") [:b] (content "2")})
java.lang.ClassCastException: clojure.lang.PersistentArrayMap cannot be cast to clojure.lang.ITransientCollection

clone-for does not work well with single letter tag

user> (use 'net.cgrand.enlive-html)
nil
user> (sniptest "<tr><bb><div></div></bb></tr>"
[:tr] (clone-for [option-value-map [1]]
[:div] (content "a")))
"<tr><bb><div>a</div></bb></tr>"
user> (sniptest "<tr><b><div></div></b></tr>"
[:tr] (clone-for [option-value-map [1]]
[:div] (content "a")))
"<tr></tr><b></b><div><b></b></div><b></b>"

https://gist.github.com/4467322

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.