trailblazer / cells

View components for Ruby and Rails.
https://trailblazer.to/2.1/docs/cells.html
3.07k stars 236 forks source link

Quotes are not escaped in JSON strings in Slim view #315

Closed ethanyoung closed 9 years ago

ethanyoung commented 9 years ago

Assuming I have a cell view like this:

.row data-viewmodel=@feature.view_model.to_json

where the value of [data-viewmodel] is like "{\"model\":\"notice\",\"can_update\":true}"

In previous version cells this the view is rendered correctly. The output of the cell is like

"<div class=\"row\" data-viewmodel=\"{&quote;model&quote;:&quote;notice&quote;,&quote;can_update&quote;:true}\">

However, now the output is like:

"<div class=\"row\" data-viewmodel=\"{\"model\":\"notice\",\"can_update\":true}\">

which will break the HTML when display on the browser.

I have tried to use

include Escaped

but did not help...

What was missing here...?

Thank you in advance.

apotonick commented 9 years ago

We had the same problem here. Please try using #tag_options which should escape the options.

I'd suggest you change your view.

.row data-viewmodel=data_attr

Then, define the #data_attr method on your cell.

class SongCell < Cell::ViewModel
  # ..

  def data_attr
    html_escape @feature.view_model.to_json
  end

This also makes your view logic-less. :smile:

ethanyoung commented 9 years ago

#tag_options does not help. The related code is already included in cell-slim gem anyway...

However, this fixed my issue:

CGI::escapeHTML @feature.view_model.to_json
apotonick commented 9 years ago

Ah, ok, cool. Doesn't #html_escape do just that? And: did you move that code to an instance method of your cell? If not, please do it. :beers:

ethanyoung commented 9 years ago

::ERB::Util.html_escape can also do it.

Yeah, I have moved the code to an instance method. Thank you for the advice. :smiley:

apotonick commented 9 years ago

So, is the #html_escape method available on the cell or not? Because we can add it, as it is extremely handy?

ethanyoung commented 9 years ago

I have to add the line to my cell:

include ::ERB::Util

in order to use #html_escape.

I do not use #html_escape very often. This is my first time using #html_escape to manually escape the JSON string. Previously it was just escaped automatically...

By the way, do you know the reason why #tag_options does not work here? My code was like this:

class FeatureCell < Cell::ViewModel
  #...

  def tag_options(options, escape = true)
    super(options, true)
  end

  def data_feature
    # If not using ::ERB::Util.html_escape then JSON string is not escaped.
    @feature.view_model.to_json
  end
end
apotonick commented 9 years ago

Because #tag_options is not used in your code! :grimacing: