Rails button_to在W3C验证器中失败



Ruby on Railsbutton_to的输出最近在W3C验证中开始失败,返回的消息为:

具有隐藏值的类型属性的输入元素不能具有值为开或关的自动完成属性。

所以我想消除这个错误。

Rails-7.0.4中View(ERB(中对应的button_to语句是

<%= button_to "Add Entry", new_article_path, form_class: "inline_form button_to",
method: :get, params: { a_token: "abc" } %>

它生成HTML(简化!(:

<!DOCTYPE html>
<html lang="en"> <head> <meta charset="utf-8"> <title>My Title</title> </head>
<body>
<form class="inline_form button_to" method="get" action="/articles/new?locale=en">
<input type="submit" value="Add Entry" />
<input type="hidden" name="a_token" value="abc" autocomplete="off" />
</form>
</body>
</html>

如果我将其粘贴到W3C验证器表单中,它将失败,并显示上述消息。

显然,W3C验证器不喜欢在具有type="hidden"input标签中存在属性autocomplete。但这是button_to(在Rails7.0中(的默认输出

根据Rails存储库中的问题#42610,Rails团队去年似乎添加了autocomplete=off,以使HTML输出Firefox验证。在相关讨论中,用户jpwynn表示(2021-06-27(这一变化不会破坏W3C的验证。但现在似乎是这样……


据我所知,我在Rails应用程序中没有修改任何相关部分。然而,我注意到W3C验证的常规测试已经开始失败。因此,我怀疑W3C最近更改了规范(但我可能错了!(。

我的Rails测试非常简单,如下所示,使用Gem w3c_validators版本1.3.7;它只是检测到任何错误,如果有错误就会失败:

# /test/test_helper.rb
require 'w3c_validators'
def my_w3c_validate
arerr = @validator.validate_text(response.body).errors
assert_equal 0, arerr.size,
"Failed in W3C-validation: ("+arerr.map(&:to_s).join(") (")+")"
end

Gemfile:

group :development, :test do
gem 'w3c_validators', '~> 1', '>= 1.3.6'  # => 1.3.7 in reality
end

那么,Railsbutton_to的输出是一个有效的HTML吗?如果没有,我如何修改它,使输出的HTML成为有效的HTML?我使用的是最新的稳定版本Rails-7.0.4。

W3C HTML检查器(验证器(@sideshowbarker的维护人员友好地提供了信息(请参阅问题中的注释(。

以下是摘要:

  1. W3C HTML检查器做得绝对正确:
    <input type="hidden" name="abc" autocomplete="off">无效。
    • 根据HTML表单规范,

      当佩戴自动填充锚套时,如果指定了自动完成属性,则其值必须是一组有序的空间分隔标记,仅由自动填充细节标记组成(即不允许使用"on"one_answers"off"关键字("--where"佩戴自动填充锚点套

      ,它基本上应用于<input type=hidden>标记。

  2. 新的检查项是最近(2022-10-26(在检查器上实现的,因此我的Rails W3C测试结果最近发生了变化。查看Git拉取请求
  3. Rails的button_to方法生成的HTML违反了<input>标记的规范。具有讽刺意味的是,button_to的HTML生成最近(去年(发生了变化,以应对Firefox的不良行为;它当时确实通过了W3C HTML验证!请参阅Rails Github Issue#42610

现在,由于W3C验证器做得很好,您有两个选项:

  1. 改变Rails的button_to生成HTML的方式
  2. 在这方面修改W3C验证的结果,这样验证就不会因为这个错误而失败,并且您仍然可以使用所有其他验证

这是第二个策略中的度量。您传递W3CValidators::Message的Array,此方法返回相同的Array,但删除了上述错误。原始的相关错误消息可以记录在Logger中。我也把脚本(但有更广泛的描述(放在了GithubGist中。

# @example Usage, maybe in /test/test_helper.rb
#   # Make sure to write in /config/environments/test.rb
#   #    config.ignore_w3c_validate_hidden_autocomplete = true
#   #
#   #require 'w3c_validators'
#   errors = @validator.validate_text(response.body).errors
#   errors = _may_ignore_autocomplete_errors_for_hidden(errors, "W3C validaiton failed: ")
#   assert_empty errors, "Failed in W3C validation: "+errors.map(&:to_s).inspect
#
# @param errs [Array<W3CValidators::Message>] Output of +@validator.validate_text(response.body).errors+
# @param prefix [String] Prefix of the warning message recorded with Logger.
#    If empty, no message is recorded in Logger.
# @return [Array<String>]
def may_ignore_autocomplete_errors_for_hidden(errs, prefix="")
removeds = []
return errs if !Rails.configuration.ignore_w3c_validate_hidden_autocomplete
errs.map{ |es|
# Example of an Error:
#   ERROR; line 165: An “input” element with a “type” attribute whose value is “hidden” must not have an “autocomplete” attribute whose value is “on” or “off”
if /AERRORb.+binputb[^a-z]+belement.+btypeb.+bhiddenb.+bautocompleteb[^a-z]+battributeb/i =~ es.to_s
removeds << es
nil
else
es
end
}.compact
ensure
# Records it in Logger
if !removeds.empty? && !prefix.blank?
Rails.logger.warn(prefix + removeds.map(&:to_s).uniq.inspect)
end
end

最新更新