ruricolist/spinneret

Spinneret escapes pre-formatted tags (in particular, <style>)

Closed this issue · 5 comments

Problem

When running this piece of code:

(spinneret:with-html
  (:style "a > p{
    color: white;
}"))

I get

<style>a &gt; p{
    color: white;
}</style>

Which breaks browser's stylesheet processing and breaks this exact CSS rule because &gt; is not ever parsed as >. It should not be serialized this way, especially in preformatted tags.

Guess

As far as I can tell, it happens because of *pre* special variable not being honored when escaping the body of the tag. But Spinneret has so many layers of printing that I'm unable to narrow it down more than:

(spinneret::with-tag (:style)
  "a > p{
    color: white;
}")

still producing the escaped output.

What I've tried:

  • *print-pretty* as NIL.
  • spinneret:*html-style* as :tree.
  • Using <pre> to learn if it's <style>-specific. It's not, all pre-formated tags are broken the same.

None un-escaped the contents of <style> or any other pre-formatted tag.

@ruricolist, any idea why that happens?

preformatted just means that formatting is preserve, not that it's not escaped. To turn off escaping, use :raw:

(with-html
  (:style
    (:raw
     "a > p{
    color: white;
}")))

Ahhhh, right! Thanks for that!

But then, should it be unescaped for <style>, <script> etc. by default? It would be extremely convenient...

My position is that experience over the decades with templating libraries has shown that implicitly leaving anything unescaped inevitably results in script injection.

That said, this behavior should be better documented. I will add examples of style and script tags in the readme.

Fair! Feel free to close this issue afterwards :)

Thanks a lot!