I'm using ERB or ERUB or Tilt here outside of Rails and I want to make my HTML templates work like rails where stuff is HTML escaped by default.
e.g.
<!-- file.html.erb -->
<h1>Hello <%= name %></h1>
When I render this, if name
is <b>Pat</b>
, then the HTML sent to the browser is:
<h1>Hello <b>Pat</b></h1>
I'd like it to render this:
<h1>Hello <b>Pat</b></h1>
And I'd like that behavior to be the default anytime <%=
is used.
I'm trying Tilt, but when I do Tilt.new("file.html.erb",escape_html: true)
it escapes the entire file, rendering <h1>Hello <b>Pat</b></h1>
I tried reading Rails' source to figure this out, but it's highly abstracted and wondering if anyone reading this happens to know how to achieve this.
Answering my own question -> Erubi and Tilt + Erbui does actually work the way I want, but my problem was in using yield
to create a layout-style nested set of templates.
In the most basic case, things work:
<!-- outer.html.erb -->
<h1>Hello! <%= name %></h1>
require "tilt"
name = "<b>Pat</b>"
template = Tilt.new("outer.html.erb",
engine: Erubi::Engine,
escape_html: true)
s = template.render(self, name: name)
puts s
produces:
<h1>Hello! <b>Pat</b></h1>
What I was trying to do, which I omitted from the question because I thought I was simplifying, was to do a layout-style nested template setup.
<!-- inner.html.erb -->
<h2>Yup <%= name %></h2>
<!-- outer.html.erb -->
<h1>Hello! <%= name %></h1>
<%= yield %>
require "tilt"
name = "<b>Pat</b>"
inner = Tilt.new("inner.html.erb",
engine: Erubi::Engine,
escape_html: true)
rendered_inner = inner.render(self, name: name)
template = Tilt.new("outer.html.erb",
engine: Erubi::Engine,
escape_html: true)
s = template.render(self, name: name) do
rendered_inner
end
puts s
Because I'm yielding a string containing HTML to render
, I get the HTML escaped when I didn't want it to:
<h1>Hello! <b>Pat</b></h1>
<h2>Yup &lt;b&gt;Pat&lt;/b&gt;</h2>
To me, it appeared as if escape_html:
was escaping everything.
The solution is to use <%==
in outer.html.erb
:
<!-- outer.html.erb -->
<h1>Hello! <%= name %></h1>
<%== yield %>
Which does what I want:
<h1>Hello! <b>Pat</b></h1>
<h2>Yup <b>Pat</b></h2>
Whew!
Of course, omitted escape_html: true
does not escape by default.