     "meta" "param" "source" "track" "wbr"})
 
 
-(defn container-tag? [tag content]
-  (or content
-      (not (contains? void-tags tag))))
-
-
 (def attr-mapping
-  {:class-name "class"
-   :className  "class"
-   :html-for   "for"
-   :htmlFor    "for"})
-
-
-(defn react-attr->html ^String [attr]
-  (let [^String attr-str (or (attr-mapping attr)
-                             (str/lower-case (to-str attr)))]
-    (if (or (.startsWith attr-str "data-")
-            (.startsWith attr-str "aria-")
-            (.startsWith attr-str "-"))
-      attr-str
-      (str/replace attr-str "-" ""))))
+  { :class-name "class"
+    :className  "class"
+    :html-for   "for"
+    :htmlFor    "for" })
+
+
+(defn normalize-attr-key ^String [key]
+  (let [^String str (or (attr-mapping key)
+                        (str/lower-case (to-str key)))]
+    (if (or (.startsWith str "data-")
+            (.startsWith str "aria-")
+            (.startsWith str "-"))
+      str
+      (str/replace str "-" ""))))
 
 
 (defn escape-html [^String s]

    (number? value)
      (str value (when (not= 0 value) "px"))
    (and (string? value)
         (re-matches #"\s*\d+\s*" value))
      (recur key (-> value str/trim Long/parseLong))
    :else
      (escape-html (to-str value))))

    "Turn a Clojure data type into a string of HTML with react ids."))


(defn render-inner-html! [attrs children sb]
  (when-let [inner-html (:dangerouslySetInnerHTML attrs)]
    (when-not (empty? children)
      (throw (Exception. "Invariant Violation: Can only set one of `children` or `props.dangerouslySetInnerHTML`.")))
    (when-not (:__html inner-html)
      (throw (Exception. "Invariant Violation: `props.dangerouslySetInnerHTML` must be in the form `{__html: ...}`. Please visit https://fb.me/react-invariant-dangerously-set-inner-html for more information.")))
    (append! sb (:__html inner-html))
    true))

  
(defn render-content! [tag attrs children *key sb]
  (if (and (nil? children)
           (contains? void-tags tag))
    (append! sb "/>")
    (do
      (append! sb ">")
      (or (render-inner-html! attrs children sb)
          (doseq [element children]
            (-render-html element children *key sb)))
      (append! sb "</" tag ">"))))


(defn render-element!
  "Render an element vector as a HTML element."
  [element *key sb]
  (let [[tag id classes attrs children] (normalize-element element)]

    (append! sb "<" tag)
    
    (when id
      (append! sb " id=\"" id "\""))
    
    (render-attrs! attrs sb)
    
    (render-classes! classes sb)
    
    (when (== @*key 1)
      (append! sb " data-reactroot=\"\""))
    
    (append! sb " data-reactid=\"" @*key "\"")
    (vswap! *key inc)
    
    (render-content! tag attrs children *key sb)))


(extend-protocol HtmlRenderer
  IPersistentVector
  (-render-html [this parent *key sb]
    (render-element! this *key sb))

  ISeq
  (-render-html [this parent *key sb]
    (doseq [element this]
      (-render-html element parent *key sb)))

  Named
  (-render-html [this parent *key sb]
