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

Default to HTML encoded strings. Provide an override function. #66

Closed simon-nicholls closed 11 years ago

simon-nicholls commented 11 years ago

A naive implementation of HTML encoding by default, to get the ball rolling hopefully. Comments?

weavejester commented 11 years ago

HTML encoding won't work with Hiccup 1.0 because the output of the html macro is a string, therefore there's no way to distinguish nested HTML from a string that needs to be HTML encoded.

However, because there's a lot of interest in this, I'm going to start development on 2.0 in the next few days. I already have a lot of the work complete in separate branches.

simon-nicholls commented 11 years ago

2.0 development would be great. Thanks for taking the issue seriously.

Regarding the code I've included here, it's not dealing with many use cases - just plain pre-compilable strings for simplicity. However, the approach I'm trying to demonstrate, for debate, is that strings are either HTML safe or they are not, and a set can be used to identify those that are.

It's true that the html macro always produces strings, but that's not a problem in this approach. The problem is to have a set in the top level html macro only, that is usable by any (possibly lazily generated) string that will render. Couldn't nested html macros behave appropriately via macrolet / &form or other mechanism?

Of course if nested html macros are tweaked, we could probably use a different type internally anyway, to get metadata back.

Btw, it was great to meet you at the EuroClojure conference. See you at HaskellX if you're going!

weavejester commented 11 years ago

The problem is that this needs to work:

(defn doctype []
  "<!DOCTYPE html>")

(defn foo []
  (html [:p "foo"]))

(defn bar []
  (html (doctype) [:div (foo)]))

As far as I can tell, under the code you've supplied, this wouldn't work unless we wrapped foo and doctype in your html-safe function, but that would break compatibility. Hiccup follows semantic versioning, so any break in compatibility is a major version release.

simon-nicholls commented 11 years ago

I think switching to default HTML safety is a major breaking change, and needs a major version release anyway. When I made the switch with Rails, I greatly underestimated how many strings needed html safety tagging (many helper functions were "tainted"). Though it was a great benefit afterwards.

I can get single escaping and safety marking working for the basic case I tried with (compilable literal strings), but any approach needs to be considered freshly in the context of your 2.0 plans. I look at that foo function and see it equivalent to a "final product" string. Treating it differently "in context" is going to be a hack of some type, it's just that metadata (if it were possible) would be cleaner and has precedent elsewhere.

Anyway, I don't think this issue makes sense outside of 2.0, so I'll close out. Catch you at HaskellX if you go.

weavejester commented 11 years ago

It's actually the first I've heard of HaskellX, but I'll look it up :)