Rails Button_to 因 W3C 验证器而失败

Mas*_*ano 5 html forms ruby-on-rails w3c-validation

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

\n
\n

具有隐藏值的 type 属性的输入元素不得具有值为 on 或 off 的 autocomplete 属性。

\n
\n

所以我想摆脱这个错误。

\n

button_toRails-7.0.4中View(ERB)中对应的语句是

\n
<%= button_to "Add Entry", new_article_path, form_class: "inline_form button_to",\n  method: :get, params: { a_token: "abc" } %>\n
Run Code Online (Sandbox Code Playgroud)\n

它会生成一个 HTML(简化的!):

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

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

\n

显然,W3C 验证器不喜欢带有 的标记autocomplete中存在该属性。但这是(Rails 7.0 中)的默认输出。inputtype="hidden"button_to

\n

根据Rails 存储库中的Issue #42610, Rails 团队autocomplete=off去年添加了使 HTML 输出防Firefox 的功能。在相关讨论中,用户 jpwynn表示 (2021-06-27)该更改不会破坏 W3C 验证。但似乎现在\xe2\x80\xa6\xe2\x80\xa6

\n
\n

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

\n

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

\n
 # /test/test_helper.rb\nrequire \'w3c_validators\'\n\ndef my_w3c_validate\n  arerr = @validator.validate_text(response.body).errors\n  assert_equal 0, arerr.size,\n    "Failed in W3C-validation: ("+arerr.map(&:to_s).join(") (")+")"\nend\n
Run Code Online (Sandbox Code Playgroud)\n

Gemfile

\n
group :development, :test do\n  gem \'w3c_validators\', \'~> 1\', \'>= 1.3.6\'  # => 1.3.7 in reality\nend\n
Run Code Online (Sandbox Code Playgroud)\n

那么,Rails 的输出是button_to有效的 HTML 吗?如果不是,我该如何修改它以使输出 HTML 成为有效的 HTML?\n我使用的是最新的稳定版本 Rails-7.0.4。

\n

Mas*_*ano 0

W3C HTML 检查器(验证器)的维护者@sideshowbarker 友善地提供了信息(请参阅问题中的评论)。

\n

总结如下:

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

      \n
      \n

      当佩戴自动填充锚斗篷时,自动完成属性(如果指定)必须具有一个值,该值是一组仅由自动填充详细信息标记组成的空格分隔标记的有序集合(即不允许使用“on”和“off”关键字)\ xe2\x80\x9d \xe2\x80\x94 其中 \xe2\x80\x9c 佩戴自动填充锚地幔

      \n
      \n

      这基本上应用于标签<input type=hidden>

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

现在,由于 W3C 验证器运行正常,您有两个选择:

\n
    \n
  1. 改变Rails生成HTML的方式\'button_to
  2. \n
  3. 在这方面修改 W3C 验证的结果,以便验证不会仅仅因为此错误而失败,并且您仍然可以使用所有其他验证。
  4. \n
\n

这是第二个政策中的措施。您传递的数组W3CValidators::Message,此方法返回相同的数组,但删除了上述错误。原来的相关错误信息可以记录在Logger. 我也将脚本(但有更广泛的描述)放在了Github Gist中。

\n
# @example Usage, maybe in /test/test_helper.rb\n#   # Make sure to write in /config/environments/test.rb\n#   #    config.ignore_w3c_validate_hidden_autocomplete = true\n#   #\n#   #require \'w3c_validators\'\n#   errors = @validator.validate_text(response.body).errors\n#   errors = _may_ignore_autocomplete_errors_for_hidden(errors, "W3C validaiton failed: ")\n#   assert_empty errors, "Failed in W3C validation: "+errors.map(&:to_s).inspect\n#\n# @param errs [Array<W3CValidators::Message>] Output of +@validator.validate_text(response.body).errors+\n# @param prefix [String] Prefix of the warning message recorded with Logger.\n#    If empty, no message is recorded in Logger.\n# @return [Array<String>]\ndef may_ignore_autocomplete_errors_for_hidden(errs, prefix="")\n  removeds = []\n  return errs if !Rails.configuration.ignore_w3c_validate_hidden_autocomplete\n  errs.map{ |es|\n    # Example of an Error:\n    #   ERROR; line 165: An \xe2\x80\x9cinput\xe2\x80\x9d element with a \xe2\x80\x9ctype\xe2\x80\x9d attribute whose value is \xe2\x80\x9chidden\xe2\x80\x9d must not have an \xe2\x80\x9cautocomplete\xe2\x80\x9d attribute whose value is \xe2\x80\x9con\xe2\x80\x9d or \xe2\x80\x9coff\xe2\x80\x9d\n    if /\\AERROR\\b.+\\binput\\b[^a-z]+\\belement.+\\btype\\b.+\\bhidden\\b.+\\bautocomplete\\b[^a-z]+\\battribute\\b/i =~ es.to_s\n      removeds << es\n      nil\n    else\n      es\n    end\n  }.compact\n\nensure\n  # Records it in Logger\n  if !removeds.empty? && !prefix.blank?\n    Rails.logger.warn(prefix + removeds.map(&:to_s).uniq.inspect)\n  end\nend\n
Run Code Online (Sandbox Code Playgroud)\n