Skip to content

Commit

Permalink
Support :escape=>:erubi option in the render plugin to use the erubi …
Browse files Browse the repository at this point in the history
…template engine for escaping

Erubi is an Erubis fork that has a number of advantages, this allows
easy use of Erubi in Roda templates.
  • Loading branch information
jeremyevans committed Nov 10, 2016
1 parent 0bd6e21 commit 3f6200d
Show file tree
Hide file tree
Showing 6 changed files with 71 additions and 11 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
= HEAD

* Support :escape=>:erubi option in the render plugin to use the erubi template engine for escaping (jeremyevans)

= 2.19.0 (2016-10-14)

* Don't add Content-Type/Content-Length headers for 1xx, 204, 205, 304 statuses (celsworth, jeremyevans) (#101, #102)
Expand Down
5 changes: 4 additions & 1 deletion README.rdoc
Original file line number Diff line number Diff line change
Expand Up @@ -693,7 +693,8 @@ You can override the default rendering options by passing a hash to the plugin:

class App < Roda
plugin :render,
:escape => true, # Automatically escape output in erb templates
:escape => true, # Automatically escape output in erb templates using Erubis
# can use :erubi instead of true to use Erubi instead of Erubis
:views => 'admin_views', # Default views directory
:layout_opts => {:template=>'admin_layout',
:ext=>'html.erb'}, # Default layout template options
Expand Down Expand Up @@ -763,6 +764,8 @@ if you have helpers that already return escaped output using a
string subclass instance.

This support requires {Erubis}[http://www.kuwata-lab.com/erubis/].
You can use <tt>:escape=>:erubi</tt> to use {Erubi}[https://github.com/jeremyevans/erubi],
a simplified fork of Erubis.

=== Security Related HTTP Headers

Expand Down
13 changes: 8 additions & 5 deletions lib/roda/plugins/render.rb
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,10 @@ module RodaPlugins
# templates, defaults to 'erb'.
# :escape :: Use Roda's Erubis escaping support, which makes <tt><%= %></tt> escape output,
# <tt><%== %></tt> not escape output, and handles postfix conditions inside
# <tt><%= %></tt> tags.
# <tt><%= %></tt> tags. Can have a value of :erubi to use Erubi escaping support.
# :escape_safe_classes :: String subclasses that should not be HTML escaped when used in
# <tt><%= %></tt> tags, when :escape is used. Can be an array for multiple classes.
# :escaper :: Object used for escaping output of <tt><%= %></tt>, when :escape is used,
# <tt><%= %></tt> tags, when :escape=>true is used. Can be an array for multiple classes.
# :escaper :: Object used for escaping output of <tt><%= %></tt>, when :escape=>true is used,
# overriding the default. If given, object should respond to +escape_xml+ with
# a single argument and return an output string.
# :layout :: The base name of the layout file, defaults to 'layout'. This can be provided as a hash
Expand Down Expand Up @@ -146,7 +146,7 @@ module Render
OPTS={}.freeze

def self.load_dependencies(app, opts=OPTS)
if opts[:escape]
if opts[:escape] && opts[:escape] != :erubi
app.plugin :_erubis_escaping
end
end
Expand Down Expand Up @@ -199,7 +199,10 @@ def self.configure(app, opts=OPTS)
if RUBY_VERSION >= "1.9" && !template_opts.has_key?(:default_encoding)
template_opts[:default_encoding] = Encoding.default_external
end
if opts[:escape]
if opts[:escape] == :erubi
require 'tilt/erubi'
template_opts[:escape] = true
elsif opts[:escape]
template_opts[:engine_class] = ErubisEscaping::Eruby

opts[:escaper] ||= if opts[:escape_safe_classes]
Expand Down
1 change: 1 addition & 0 deletions roda.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ Gem::Specification.new do |s|
s.add_development_dependency "minitest", ">= 5.7.0"
s.add_development_dependency "tilt"
s.add_development_dependency "erubis"
s.add_development_dependency "erubi"
s.add_development_dependency "haml"
s.add_development_dependency "rack_csrf"
s.add_development_dependency "sass"
Expand Down
12 changes: 7 additions & 5 deletions spec/plugin/_erubis_escaping_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,17 @@
rescue LoadError
# Tilt 1 support
end

if defined?(Tilt::ErubisTemplate) && ::Tilt['erb'] != Tilt::ErubisTemplate
# Work around error where erubis isn't set as erb template handler
Tilt.register(Tilt::ErubisTemplate, 'erb')
end
rescue LoadError
warn "tilt or erubis not installed, skipping _erubis_escaping plugin test"
else
describe "_erubis_escaping plugin" do
before do
if defined?(Tilt::ErubisTemplate) && ::Tilt['erb'] != Tilt::ErubisTemplate
# Set erubis as default erb template handler
Tilt.register(Tilt::ErubisTemplate, 'erb')
end
end

it "should escape inside <%= %> and not inside <%== %>, and handle postfix conditionals" do
app(:bare) do
plugin :render, :escape=>true
Expand Down
47 changes: 47 additions & 0 deletions spec/plugin/render_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -549,3 +549,50 @@ def test_method

end
end

begin
require 'tilt'
require 'tilt/erubi'
rescue LoadError
warn "tilt 2 or erubi not installed, skipping render :escape=>:erubi test"
else
describe "_erubis_escaping plugin" do
before do
if defined?(Tilt::ErubiTemplate) && ::Tilt['erb'] != Tilt::ErubiTemplate
# Set erubi as default erb template handler
Tilt.register(Tilt::ErubiTemplate, 'erb')
end
end

it "should escape inside <%= %> and not inside <%== %>, and handle postfix conditionals" do
app(:bare) do
plugin :render, :escape=>:erubi

route do |r|
render(:inline=>'<%= "<>" %> <%== "<>" %><%= "<>" if false %>')
end
end

body.must_equal '&lt;&gt; <>'
end

it "should allow for per-branch escaping via set_view options" do
app(:bare) do
plugin :render, :escape=>:erubi
plugin :view_options

route do |r|
set_view_options :template_opts=>{:escape=>false}
r.is 'a' do
set_view_options :template_opts=>{:engine_class=>render_opts[:template_opts][:engine_class]}
render(:inline=>'<%= "<>" %>')
end
render(:inline=>'<%= "<>" %>')
end
end

body('/a').must_equal '&lt;&gt;'
body.must_equal '<>'
end
end
end

0 comments on commit 3f6200d

Please sign in to comment.