You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Rails 6:ActionText编码URL、Trix过滤HTML如何禁用?

我之前也碰到过这个一模一样的问题,折腾了好一阵子才搞定,给你拆解两个核心问题的解决方案:

1. 阻止ActionText编码URL中的Liquid变量/自定义标签

ActionText默认会对URL里的特殊字符(比如{{}})进行URI编码,我们需要自定义它的URL sanitizer来绕过这个行为。具体步骤如下:

  1. 创建自定义的Sanitizer类
    app/lib/custom_action_text_sanitizer.rb中添加:
class CustomActionTextSanitizer < ActionText::Sanitizer
  private
    def sanitize_url(url)
      # 先把Liquid变量临时替换成占位符,避免被编码
      liquid_vars = {}
      url = url.gsub(/{{\s*[\w.]+\s*}}/) do |match|
        key = "LIQUID_VAR_#{liquid_vars.size}"
        liquid_vars[key] = match
        key
      end

      # 对剩余部分执行默认的URL sanitize逻辑
      sanitized_url = super(url)

      # 把占位符换回原来的Liquid变量
      liquid_vars.each do |key, value|
        sanitized_url = sanitized_url.gsub(key, value)
      end

      sanitized_url
    end
end
  1. 配置ActionText使用这个自定义Sanitizer
    config/initializers/action_text.rb里添加:
Rails.application.config.action_text.sanitizer = CustomActionTextSanitizer.new

如果你的自定义标签是类似[domain_name]这种,只需要把上面正则表达式改成/\[\w+\]/就行,灵活调整匹配规则即可。

2. 让Trix保留表格、Div及Data属性

Trix和ActionText默认会过滤掉非白名单内的HTML标签和属性,我们需要扩展白名单并配置Trix编辑器:

步骤1:扩展ActionText的Sanitizer白名单

同样在config/initializers/action_text.rb中添加:

# 允许表格相关标签和div
ActionText::ContentHelper.ALLOWED_TAGS.add('table', 'thead', 'tbody', 'tr', 'th', 'td', 'div')

# 允许所有data-开头的属性
ActionText::ContentHelper.ALLOWED_ATTRIBUTES.add(/data-.+/)

步骤2:配置Trix编辑器支持这些元素

根据你的Rails版本,选择对应的配置方式:

如果你用的是Rails 7+(Importmap方式)

创建app/javascript/initializers/trix_config.js

import Trix from "trix"

// 初始化Trix时注册允许的块级元素
document.addEventListener('trix-initialize', (event) => {
  const editor = event.target.editor
  
  // 注册div作为块级元素
  editor.registerBlockType('div', {
    tagName: 'div',
    terminal: true,
    breakOnReturn: true,
    group: 'block'
  })

  // 允许所有data-属性
  editor.enableAttribute('data-*')
})

// 处理粘贴HTML时不被Trix自动转换
document.addEventListener('trix-paste', (event) => {
  const html = event.clipboardData.getData('text/html')
  if (html) {
    event.preventDefault()
    event.target.editor.insertHTML(html)
  }
})

然后在app/javascript/application.js中导入这个初始化文件:

import "@hotwired/turbo-rails"
import "controllers"
import "./initializers/trix_config" // 添加这一行
import "trix"
import "@rails/actiontext"

如果你用的是Rails 6及以下(Sprockets方式)

创建app/assets/javascripts/initializers/trix_config.js

document.addEventListener('trix-initialize', function(event) {
  const editor = event.target.editor
  
  editor.registerBlockType('div', {
    tagName: 'div',
    terminal: true,
    breakOnReturn: true,
    group: 'block'
  })

  editor.enableAttribute('data-*')
})

document.addEventListener('trix-paste', function(event) {
  const html = event.clipboardData.getData('text/html')
  if (html) {
    event.preventDefault()
    event.target.editor.insertHTML(html)
  }
})

然后在app/assets/javascripts/application.js中引入:

//= require trix
//= require_tree ./initializers
//= require rails/actiontext

最后提醒

修改完这些配置后,一定要重启你的Rails服务器,否则初始化文件的修改不会生效。测试的时候直接输入或粘贴你的目标HTML,就能看到它完全保留原样,同时Trix的基础编辑功能(加粗、下划线、段落等)也能正常使用。

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

火山引擎 最新活动