You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

非Rails环境下如何让ERB/ERUBI默认转义模板变量HTML而非全模板转义

解决方案

要实现Rails风格的ERB默认HTML转义(<%= %>自动转义变量,保留模板本身的HTML结构),可以通过自定义ERB上下文或扩展Tilt模板类来实现,以下是具体方法:

方法一:自定义ERB上下文类

通过重写ERB的输出逻辑,让<%= %>自动调用HTML转义方法,同时提供raw方法输出未转义内容:

require 'erb'
require 'erb/util'

class ERBSafeContext
  include ERB::Util

  def initialize(variables = {})
    variables.each do |key, value|
      instance_variable_set("@#{key}", value)
    end
    @_erbout = +''
  end

  # 重写concat方法,自动转义非安全内容
  def concat(value)
    if value.is_a?(ERB::Util::HTMLSafeString)
      @_erbout << value
    else
      @_erbout << html_escape(value)
    end
  end

  # 标记内容为安全,跳过转义
  def raw(value)
    ERB::Util.html_safe(value.to_s)
  end

  def render(template_path)
    template = ERB.new(File.read(template_path), trim_mode: '-')
    template.result(binding)
  end
end

使用示例

假设file.html.erb模板内容:

<h1>用户名称</h1>
<p>转义后的输出:<%= name %></p>
<p>原始HTML输出:<%= raw(name) %></p>

渲染代码:

context = ERBSafeContext.new(name: '<b>Pat</b>')
puts context.render('file.html.erb')

输出结果:

<h1>用户名称</h1>
<p>转义后的输出:&lt;b&gt;Pat&lt;/b&gt;</p>
<p>原始HTML输出:<b>Pat</b></p>

方法二:扩展Tilt模板类

如果你需要继续使用Tilt工具,可以扩展其ERB模板类,修改默认渲染逻辑:

require 'tilt'
require 'erb/util'

class SafeERBTemplate < Tilt::ERBTemplate
  def prepare
    @engine = ERB.new(data, options[:safe], options[:trim_mode], '@_erbout')
    @engine.def_method(@scope, :render) do |*args|
      variables = args.first || {}
      variables.each { |k, v| instance_variable_set("@#{k}", v) }
      @_erbout = +''

      # 注入转义逻辑
      def concat(value)
        if value.is_a?(ERB::Util::HTMLSafeString)
          @_erbout << value
        else
          @_erbout << ERB::Util.html_escape(value)
        end
      end

      def raw(value)
        ERB::Util.html_safe(value.to_s)
      end

      eval(@engine.src)
      @_erbout
    end
  end
end

# 将自定义模板注册到Tilt
Tilt.register SafeERBTemplate, 'erb'

使用示例

template = Tilt.new('file.html.erb')
puts template.render(nil, name: '<b>Pat</b>')

输出效果和方法一完全一致,模板本身的HTML保持不变,变量输出自动转义。

说明

你之前使用Tilt.new("file.html.erb", escape_html: true)无效的原因是:该选项会转义整个模板的所有内容(包括模板里的原生HTML标签),而不是仅转义<%= %>输出的变量,因此不符合需求。

内容的提问来源于stack exchange,提问作者davetron5000

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 18:32:37