 Does nothing if the targetted node can't be found. Returns a new
 sequence of dom nodes.
 dom-nodes
-  A seq of nodes representing the document. The first element node is considered the root.
+A seq of nodes representing the document. The first element node is considered the root.
 rules
-  A seq of rules identifying where to place the new nodes. Each rule is a pair of values.
-  The first value is a seq of element types (as keywords) to navigate down. The second
-  value is a position (:before, :after:, :top, or :bottom). The first matching rule
-  is used.
+A seq of rules identifying where to place the new nodes. Each rule is a pair of values.
+The first value is a seq of element types (as keywords) to navigate down. The second
+value is a position (:before, :after:, :top, or :bottom). The first matching rule
+is used.
 new-nodes
-  The new nodes to insert in a position within the document."
+The new nodes to insert in a position within the document."
   [dom-nodes rules new-nodes]
   (loop [result []
          queue dom-nodes]

;;; and limitations under the License.

(ns
  cascade.dom
  "DOM node structure, rendering and manipulation"
  (:import
    (clojure.lang Keyword Sequential))
  (:require
    (clojure [zip :as z] [string :as str]))
  (:use
    (cascade fail utils)))

;;; TODO: For testing purposes (i.e., to get consistent results across JVMs, etc.)
;;; it may be necessary to sort attributes when rendering (but I'd rather not bother

  "Is the object some kind of DOM node?"
  [node]
  (or (element? node)
      (instance? Static node)
      (instance? Comment node)))

(defn dom-zipper
  [root-node]
  (fail-unless (element? root-node) "Root node for dom-zipper must be an element node.")
  (z/zipper
   element? ; can have children
   :content ; children are (already) a seq in the :content key
   (fn [node children] (assoc node :content children))
   root-node))

(defn navigate-dom-path
  "Starting from the root location (from dom-zipper) search for the first element child
