17

I'm trying to render a link preceded by an icon. I'm using Slim templating engine along with Bootstrap CSS.

Usually you could do this the following way:

<a href="#"><i class="icon-user"></i> My Profile</a>

According to Slim's documentation, we can use == to render without escaping HTML. So, translating this to Slim, I tried the following variations:

li== link_to "<i class='icon-user'></i> My Profile", current_user
li== link_to "#{'<i class="icon-user"></i>'.html_safe} My Profile", current_user
li= link_to "#{'<i class="icon-user"></i>'.html_safe} My Profile", current_user

All variations rendered <a href="/users/1"><i class="icon-user"></i> My Profile</a> escaping the i tag.

How can I stop Slim or Rails from escaping html?

(Rails 3.2 with Slim 1.2.1)

ylluminate
  • 12,102
  • 17
  • 78
  • 152
Mohamad
  • 34,731
  • 32
  • 140
  • 219

5 Answers5

15

This has been answered, but if you actually have some html and you want to render it in a slim template, use double equal.

== "<i>test</i>"

Will be the same as

= "<i>test</i>".html_safe
nroose
  • 1,689
  • 2
  • 21
  • 28
  • Cool, I guess it won't work when we have a line having code too, instead of mere html. – ARK Dec 13 '19 at 12:49
  • 1
    @ARK I think it does https://github.com/slim-template/slim#output-without-html-escaping- – nroose Dec 19 '19 at 23:19
13

You want to disable HTML escaping for the link_to argument, not the entire link_to result. You're pretty close with your html_safe but your string interpolation is eating your "safe for HTML" flag. This should work better:

li= link_to '<i class="icon-user"></i> My Profile'.html_safe, current_user
mu is too short
  • 426,620
  • 70
  • 833
  • 800
11

Alternatively, you could write this as

li
  a href=url_for(current_user)
    i.icon-user My Profile

which arguably is a little easier to read.

Alexander Presber
  • 6,429
  • 2
  • 37
  • 66
  • Adding that if you have an attribute value which should be rendered as safe html, use double "=": `span data-icon==icon` (where the last icon is a variable that contains ...;) – elado Sep 09 '13 at 20:19
  • @elado: doesn't the slim documentation tell the exact opposite: https://github.com/slim-template/slim#output-without-html-escaping- ? – Alexander Presber Sep 10 '13 at 20:46
  • 3
    `==` doesn't escape, `=` does. You can use `tag attr=variable` to render an escaped variable. if you don't wish to escape it, use `tag attr==variable`. For example, to render an html entity as an attribute correctly, you shouldn't escape it: ruby: `icon = "{"` slim: `span.icon data-icon==icon` – elado Sep 11 '13 at 02:08
  • I do not approve of the edit to my answer. The extra brackets and the pipe do add too much noise and yield little benefit imho. I chose my code on purpose. Can I undo the edit? – Alexander Presber Apr 07 '14 at 10:34
1

There's another way of tackling this below in case it helps anyone. Using a block is especially useful if you have more complex code to include within the link.

li
  = link_to current_user do
    i.icon-user>
    | My Profile
Mike
  • 987
  • 11
  • 13
0

You can do a similar technique using slim syntax instead of 'raw' html, if you prefer:

li = link_to Slim::Template.new{ "i.icon-user\n| My Profile" }.render.html_safe, current_user

renders to be:

  • My Profile
  • or raw:

    <li>
      <a href="/current_user_url">
        <i class="icon-user"></i>
        My Profile
      </a>
    </li>
    

    In the above example to render the 'My Profile' text as asked in the question, you will need to use " which allows the use of \n or new line to form the correct slim syntax. \t would give you the tab you need if doing nested slim.

    If it is okay to render the text inside the icon element, then the following would work:

    li = link_to Slim::Template.new{ 'i.icon-user My Profile' }.render.html_safe, current_user
    

  • My Profile
  • <li>
      <a href="/current_user_url">
        <i class="icon-user">My Profile</i>
      </a>
    </li>
    

    if put the behavior in your own helper method:

    # ApplicationController.rb
    
    def string_to_slim(string)
      Slim::Template.new{ string }.render.html_safe
    end
    helper_method :string_to_slim # allows you to call the method in a view via ERB or Slim
    

    Then you could implement like this in view .slim being rendered by controller inheriting from your base controller:

    li = link_to string_to_slim('i.icon-user My Profile'), current_user
    
    SMAG
    • 652
    • 6
    • 12