weavejester / hiccup

Fast library for rendering HTML in Clojure
http://weavejester.github.io/hiccup
Eclipse Public License 1.0
2.68k stars 174 forks source link

hiccup/html behaves differently with literal or let-bound value #158

Open nha opened 5 years ago

nha commented 5 years ago

Please consider the following snippet:

(let [c {}]
  (str (hiccup/html c))) ;; "{}"
(str (hiccup/html {})) ;; ""

I am not sure what should be the output here (possibly "", since {} doesn't look like valid html to me), but I would expect both snippets to render the same output.

Adding an explicit {} first parameter makes them render both "{}"

(let [c {}]
  (str (hiccup/html {} c))) ;; "{}"

(str (hiccup/html {} {})) ;; "{}"
weavejester commented 5 years ago

It should probably either output "{}" or throw an error in both cases. Hiccup uses precompilation steps, and it looks like this is producing some strange output when it's fed invalid input.

VictorVSa commented 1 year ago

I think I'm having the same issue while trying to add a class to the html tag:

(defn page [opts & content]
  (-> (p/html5 opts content)
      http-response/ok
      (http-response/content-type "text/html")))

(page {:class "test"} [:div]) ;; ... <html>{ :class "test" } ...

But now if I ignore opts and use the literal inside the p/html5 call, it works correctly

(defn page [opts & content]
  (-> (p/html5 {:class "test"} content)
      http-response/ok
      (http-response/content-type "text/html")))

(page {:class "test"} [:div]) ;; ... <html class="test"> ...

What could be the issue?

weavejester commented 1 year ago

html5 is a macro, and some of the options it takes are necessary to be known at compile-time. In this case, I'd suggest not using the macro, and instead write:


(html {:mode :html} (p/doctype :html5) [:html opts content])