 
 ;; Core types
 
-(defn- str-attrs [attrs]
-	(str-join (map (fn [[k v]] [" " k "=\"" (html-escape v) "\""]) attrs)))
+(defrecord Attrs []
+	java.lang.Object
+	(toString [this]
+		(str-join (map (fn [[k v]] [" " k "=\"" (html-escape v) "\""]) this)))
+	clojure.lang.IFn
+	(invoke [this] this)
+	(invoke [this x] (.applyTo this (list x)))
+	(applyTo [this args] (let [t (first args)] (t this))))
 
 (defrecord Css []
 	java.lang.Object

	clojure.lang.IFn
	(invoke [this] this)
	(invoke [this x] (.applyTo this (list x)))
	(applyTo [this args] (let [tag (first args)] (tag this))))

(defrecord-ifn Tag [tag-name attrs css items]
	java.lang.Object
	(toString [_]
		(let [attrs-with-css (if (empty? css) attrs (assoc attrs :style (str css)))]
			(str-join
				"<" tag-name (str-attrs attrs-with-css)
				(if (empty? items)
					" />"
					[">" (map html-escape items) "</" tag-name ">"]))))

(defn extend-tag [t & stuff]
	(if (empty? stuff)
		t
		(let [attrs (apply merge (:attrs t) (filter attrs-or-map? stuff))
		      css (apply merge (:css t) (filter css? stuff))
		      items (concat (:items t) (flatten (filter child-item? stuff)))]
			(Tag. (:tag-name t) attrs css items))))
