diff --git a/src/hiccup/compiler.clj b/src/hiccup/compiler.clj index 4b57b25..ed49bc7 100644 --- a/src/hiccup/compiler.clj +++ b/src/hiccup/compiler.clj @@ -331,26 +331,34 @@ (compile-element (apply vector tag {} content))) (defmethod compile-element ::literal-tag - [[tag attrs & content]] + [[tag attrs-or-content & content]] (let [[tag tag-attrs _] (normalize-element-form [tag]) - attrs-sym (gensym "attrs")] - `(let [~attrs-sym ~attrs] + attrs-or-content-sym (gensym "attrs_or_content__") + attrs?-sym (gensym "attrs?__") + content?-sym (gensym "content?__")] + `(let [~attrs-or-content-sym ~attrs-or-content + ~attrs?-sym (map? ~attrs-or-content-sym) + ~content?-sym (and (not ~attrs?-sym) + (some? ~attrs-or-content-sym))] (build-string - (if (map? ~attrs-sym) - ~(if (container-tag? tag content) - `(build-string ~(str "<" tag) - (render-attr-map (merge ~tag-attrs ~attrs-sym)) - ">") - `(build-string ~(str "<" tag) - (render-attr-map (merge ~tag-attrs ~attrs-sym)) - ~(end-tag))) - (build-string ~(str "<" tag (render-attr-map tag-attrs) ">") - ~@(compile-seq [attrs-sym]))) + ;; start tag + "<" ~tag + (if ~attrs?-sym + (render-attr-map (merge ~tag-attrs ~attrs-or-content-sym)) + ~(render-attr-map tag-attrs)) + ~(if (container-tag? tag content) + ">" + `(if ~content?-sym ">" ~(end-tag))) + + ;; contents + (when ~content?-sym + (render-html ~attrs-or-content-sym)) ~@(compile-seq content) - ;; ending tag, when the above code did not emit an ending tag + + ;; end tag ~(if (container-tag? tag content) (str "") - `(when-not (map? ~attrs-sym) + `(when ~content?-sym ~(str ""))))))) (defmethod compile-element ::default diff --git a/test/hiccup/compiler_test.clj b/test/hiccup/compiler_test.clj index 552e219..4457519 100644 --- a/test/hiccup/compiler_test.clj +++ b/test/hiccup/compiler_test.clj @@ -44,18 +44,17 @@ (is (= (str (html {:mode :sgml} [:br (identity "x")])) "
x
")))) (testing "runtime nil," + ;; use case: a function which returns a map of attributes or nil (testing "normal tag" (is (= (str (html {:mode :xhtml} [:p (identity nil)])) "

")) (is (= (str (html {:mode :html} [:p (identity nil)])) "

")) - (is (= (str (html {:mode :xml} [:p (identity nil)])) "

")) - (is (= (str (html {:mode :sgml} [:p (identity nil)])) "

"))) + (is (= (str (html {:mode :xml} [:p (identity nil)])) "

")) + (is (= (str (html {:mode :sgml} [:p (identity nil)])) "

"))) (testing "void tag" - ;; TODO: this might not be desired behavior (use case: the user has - ;; a function which returns a map of attributes or nil) - (is (= (str (html {:mode :xhtml} [:br (identity nil)])) "

")) - (is (= (str (html {:mode :html} [:br (identity nil)])) "

")) - (is (= (str (html {:mode :xml} [:br (identity nil)])) "

")) - (is (= (str (html {:mode :sgml} [:br (identity nil)])) "

"))))) + (is (= (str (html {:mode :xhtml} [:br (identity nil)])) "
")) + (is (= (str (html {:mode :html} [:br (identity nil)])) "
")) + (is (= (str (html {:mode :xml} [:br (identity nil)])) "
")) + (is (= (str (html {:mode :sgml} [:br (identity nil)])) "
"))))) (deftest test-compile-element-default (testing "runtime tag" diff --git a/test/hiccup2/optimizations_test.clj b/test/hiccup2/optimizations_test.clj index 44fef99..b55c519 100644 --- a/test/hiccup2/optimizations_test.clj +++ b/test/hiccup2/optimizations_test.clj @@ -75,4 +75,4 @@ (partition 2 1) (map (fn [[a b]] (- b a))))] (is (< (apply max diffs) - (* 1.1 (apply min diffs))))))) + (* 1.2 (apply min diffs)))))))