After I updated HAML from 4.0.7 to 5.0.1 I encountered an issue with rendering a partial in an HTML attribute. I'm using Rails 5.
I have a view with this code:
.pop{ content: render('test') }
Some view text
and a partial _test.html.haml
:
.some-class
partial content
The result HTML from this is:
<div class='pop' content='<div class='some-class'>
partial content
</div>
'>
Some view text
</div>
As you see the '
-s in the content
attribute are not escaped and so the HTML is messed up.
With HAML 4.0.7 the result HTML with the same code is:
<div class='pop' content="<div class='some-class'>
 partial content
</div>">
Some view text
</div>
The outer quotations for the content
attribute are "
-s and the inner '
If I interpolate the result from rendering the partial like this:
.pop{ content: "#{render('test')}" }
Some view text
The result HTML is OK and looks like:
<div class='pop' content='<div class='some-class'>
partial content
</div>
'>
Some view text
</div>
Is this a bug with HAML 5 or have I been using an "undocumented feature" in HAML 4? Please tell me if you need more information.
Changing quotes automatically is dropped in Haml 5. This behavior itself is intentional. What's wrong here is that you pass html_safe (SafeBuffer) object (any return value from render method will become so) as attribute value (that should be escaped). Suppose the case it has both types of quotes. It'll be broken in Haml 4 too. As you did, you should remove html_safe state.
One extra choice may be changing Haml to always escape it even if it's html_safe. But currently it's not implemented.
Hello. Is it correct that the same code returns different result for rails and pure haml call?
rails 5.1.0
index.html.haml
- attr_html = capture_haml do
%span.capture_haml test
%div.test_attr{ data: { content: attr_html } }
returns unescaped html
<div class='test_attr' data-content='<span class='capture_haml'>test</span>
--
聽 | '></div>
haml
haml index.html.haml
returns correct string
<div class='test_attr' data-content='<span class='capture_haml'>test</span>
'></div>
Probably intentional https://github.com/haml/haml/blob/1d446b33207ae148f203ca1e5b68dd2428750962/lib/haml/helpers/xss_mods.rb#L62, but I don't know whether it's the case with Haml 4.0 or not.
For SafeBuffer outputs, results can differ between Rails and non-Rails. capture_haml
results are likely to be HTML, so if you render like = attr_html
, it shouldn't be HTML-escaped, right?
And for attributes, unlike Hamlit, Haml doesn't force to HTML-escape attributes if it's HTML-safe. That's basically for backward compatibility, and all of above things are intentional for now.
Haha, for some parts, I doubly commented the same thing.
@k0kubun, so the solution is to always use string interpolation when rendering partial as attribute value, right?
.pop{ content: "#{render('test')}" }
Some view text
Or use .pop{ content: render('test').to_str }
. As it's not straight-forward, it might be better to force to escape it after Haml 6...
Most helpful comment
Or use
.pop{ content: render('test').to_str }
. As it's not straight-forward, it might be better to force to escape it after Haml 6...