我经常将Sinatra用于小型项目。可以满足我的需要,但是我错过了将字符串标记为HTML安全的功能,然后ERB知道何时进行相应的转义或不进行转义的功能。
如果我可以拆下Rails制作给Erubi(around here)的补丁,然后自己将这些补丁应用到Erubi,这样倾斜就可以使用猴子补丁的Erubi,而每个人都可以住,我真的很喜欢从此以后快乐地生活着。但是,在深入研究源代码之后,我不清楚我如何才能真正做到这一点。
我还试图找到某种方法来使接口进入ActionView,例如render
方法,但我什至找不到定义的位置。
如何在Rails之外使用ActionView,理想情况下是通过使用ActionView的猴子补丁到Erubi来实现,或者,如果那行不通,我该如何使用ActionView在Rails之外从模板字符串转换为渲染字符串?
具体来说,我希望能够执行以下操作:
def some_wrapper_func(unescaped_html)
"<div>#{h unescaped_html}</div>".html_safe
end
# test1.erb
hello world <%= "<script>alert('hi');</script>" %> <%= some_wrapper_func("<span>foobar</span>") %>
#=> hello world <script>alert('hi');</script> <div><span>foobar</span></div>
答案 0 :(得分:2)
这里需要的是ActiveSupport。我不确定是否矫over过正,但是您可以这样做:
#app.rb:
require 'sinatra'
require 'active_support/all'
get '/' do
erb :index
end
在视图中:
#views/index.erb
Hello, world!
<%= "<script>alert('Hello!')</script>".html_safe %>
请注意,requre 'active_support'
将不加载任何内容,requre 'active_support'
将加载所有模块。您可以按照说明指定需要哪些模块
在Active Support Core Extensions中。
如果唯一的目标是启用自动转义,则完全不需要ActionView。可以这样做(注意<%== %>
标签):
#app.rb
require 'sinatra'
require 'erubis'
set :erb, :escape_html => true
get '/' do
erb :index
end
#View
<%= "<script>alert('Hello, and it will not produce alert!')</script>" %>
<%== "<script>alert('Hello and it will!')</script>" %>
我们将尝试使ActionView与Sinatra(或任何Ruby程序)一起运行:
require 'sinatra'
require 'action_view'
get '/' do
av_render :index
end
def av_render view
paths = ActionView::PathSet.new(["views"])
lookup_context = ActionView::LookupContext.new(paths)
renderer = ActionView::Renderer.new(lookup_context)
view_context = ActionView::Base.new(renderer)
renderer.render(view_context, template: view)
end
在视图中,我们使用html_safe
:
<%= "<script>alert('Hello, and it will not produce alert!')</script>" %>
<%= "<script>alert('Hello and it will!')</script>".html_safe %>
包装器功能也可以使用这种方法。唯一的问题是自定义渲染方法,但可以避免。
答案 1 :(得分:0)
如果您想完全避免使用ActionView,而只使用Tilt + Erubi,则可以为自己创建一个SafeString
类,并让Erubi使用它进行编译。
Erubi有一些重要的选择,特别是:
-escape
:如果为true,则默认情况下<%= %>
将转义,否则默认情况下仅<%== %>
将转义
-bufval
:在内部,erubi基本上使用累加器来构建模板。这是它将累加器初始化为的值。重要的是,它具有一个<<(str)
方法来连接新片段,以及一个to_s
方法来获取返回值。
-escapefunc
:Erubi将用于转义的功能。覆盖这一点很重要,因为我们要转义不是SafeString的所有内容,而是让SafeString不变地传递。
因此,首先让我们定义这个SafeString
类:
# main.rb
require 'tilt'
require 'erubi'
class SafeString
def initialize(str = '')
@str = str
end
def <<(str)
if str.is_a? String
return (@str << str)
elsif str.is_a? SafeString
@str = @str << str
return self
else
throw "Can't concat"
end
end
def to_s
@str
end
def self.escape(val)
if val.is_a? SafeString
return val.to_s
else
return Erubi.h(val.to_s)
end
end
module Helpers
def raw(content)
SafeString.new(content)
end
end
end
然后,我们需要包含我们定义的raw
帮助程序,并在ERB文件上对其进行测试:
include SafeString::Helpers
puts Tilt::ErubiTemplate.new("somefile.erb", bufval: 'SafeString.new', escapefunc: 'SafeString.escape', escape: true).render
# somefile.erb
<%= "<script>alert('Hello, and it will not produce alert!')</script>" %>
<%= raw("<script>alert('Hello and it will!')</script>") %>
这将为我们提供我们想要的输出!
# stdout
<script>alert('Hello, and it will not produce alert!')</script>
<script>alert('Hello and it will!')</script>
要对此进行改进,可以使用ActiveSupport::SafeBuffer
代替最小的SafeString
类。