deface icon indicating copy to clipboard operation
deface copied to clipboard

html escaping when using slim + deface (related to #120)

Open DavidBennettPIO opened this issue 11 years ago • 8 comments

When overriding an erb template that has an override with a slim template, the html content from blocks (like form_for) is escaped.

This issue was happening to me a few months ago when I upgraded to Deface 1.0 and is still happening with latest fixes in master.

I have a feeling it's related to the change from code to erb tags as pointed out in #120

When working on a spree application, if you override the orders/edit with the following content:

app/views/spree/orders/edit.html.slim

== form_tag empty_cart_path, method: :put, id: 'emptycart' do
  = submit_tag t('empty_cart')

It will produce the following html:

<form accept-charset="UTF-8" action="/cart/empty" id="emptycart" method="post">
  <div style="margin:0;padding:0;display:inline">
    <input name="utf8" type="hidden" value="&#x2713;" />
    <input name="_method" type="hidden" value="put" />
    <input name="authenticity_token" type="hidden" value="poZGCRzjhZcK0Yp3kI7rpx925o8NZJJJ7S/L74PLnNg=" />
  </div>
  &lt;input name=&quot;commit&quot; type=&quot;submit&quot; value=&quot;Empty Cart&quot; /&gt;
</form>

My system is as follows:

ruby (both 2.1.2 and 2.1.3)
deface @ade84f0460ce
nokogiri (both 1.6.3.1 and 1.6.2.1)
slim (both 2.0.3 and 2.1.0)
spree 1.2
rails 3.2.19

I have tried nokogiri with packaged libxml-2.8.0 and also system libxml-2.9.1 as suggested in #120 but it does not make any difference.

I have also tried disabling all deface overrides that affect that page with no luck. (Note pages that do not have any deface overrides work as expected)

I have also tried to force raw and html_safe content in the template but this didn't help:

== form_tag empty_cart_path, method: :put, id: 'emptycart' do
  == submit_tag(t('empty_cart')).html_safe

However the following template works as you would expect (but is ugly):

- f = form_tag empty_cart_path, method: :put, id: 'emptycart' do
  = submit_tag t('empty_cart')
= f

Thanks for all your help :)

DavidBennettPIO avatar Oct 29 '14 01:10 DavidBennettPIO

Hey @complistic-gaff , Have you had any luck with this issue? I've been banging my head against it for a few days now...

yonahforst avatar Feb 09 '15 12:02 yonahforst

@joshblour, I gave up soon after I made this issue and I'm only using erb where I need to use blocks.

You could store the content in a variable and then render it later like in my last example... though it's very ugly.

The core of the issue is that content from blocks like form_tag get converted to erb in a way that makes rails think there not html_safe... so rails escapes the content.

haml doesn't seem to have this issue... so I don't think this would be impossible to fix, I just don't know enough about defaces internals to fix it myself.

One other way I see of fixing the "problem" would be not to convert the template to erb at all if all of it's overrides are disabled. This would allow you to disable all the overrides and just replace the whole template with a slim one.

Or even a global "disable deface on slim" might work also.

DavidBennettPIO avatar Feb 10 '15 02:02 DavidBennettPIO

curious if there's any movement on this one? thx!!

edword avatar Apr 16 '15 23:04 edword

This is probably not an acceptable workaround for most folks, but since I never use Deface, I just disabled it globally in development.rb, test.rb, and production.rb, by adding this line:

config.deface.enabled = false

helloluis avatar Sep 07 '15 01:09 helloluis

Same problem with me

rails 4.2-stable spree 3.0-stable deface 1.0.1

BTW, @complistic-gaff how does the solution work?(I mean, ugly one). Could you explain this, plz?

johnwook avatar Oct 06 '15 07:10 johnwook

Same with me. But seems i found the issue. Cache. Try clear the cache.

sveredyuk avatar May 05 '16 09:05 sveredyuk

Dropping the following monkey patch into Rails initializers helped me out:

require 'slim/erb_converter'

module Deface
  class SlimConverter

    def initialize(template, options = {})
      @template = template
    end

    def result
      conv = if defined?(Slim::RailsTemplate)
               ::Slim::ERBConverter.new(Slim::RailsTemplate.options)
             else
               ::Slim::ERBConverter.new
             end
      conv.call(@template).gsub(/<%\s*%>/, '')
    end

  end
end

It seems like in the original version the offending disable_capture option isn't getting properly passed to ERBConverter. Hence, SLIM behaves in a Rails-incompatible manner. This monkey patch passes the required options along.

Gosh, it took me an extensive debugging session to figure out!

SkyWriter avatar Jan 25 '17 09:01 SkyWriter