Ensure SVG elements are closed.

Changes introduced in https://github.com/rails/rails/pull/43232 break SVGs
that have mulitple of the same descendant tag because they weren't being
closed. SVG elements must be closed accodoring to spec
https://html.spec.whatwg.org/multipage/syntax.html#elements-2.

Fixes https://github.com/rails/rails/issues/44563
This commit is contained in:
Dave Kroondyk 2022-02-28 17:52:00 -05:00
parent 0a5839fdfd
commit 3814826885
2 changed files with 5 additions and 4 deletions

@ -46,7 +46,7 @@ class TagBuilder # :nodoc:
include OutputSafetyHelper
HTML_VOID_ELEMENTS = %i(area base br col circle embed hr img input keygen link meta param source track wbr).to_set
SVG_VOID_ELEMENTS = %i(animate animateMotion animateTransform circle ellipse line path polygon polyline rect set stop use view).to_set
SVG_SELF_CLOSING_ELEMENTS = %i(animate animateMotion animateTransform circle ellipse line path polygon polyline rect set stop use view).to_set
def initialize(view_context)
@view_context = view_context
@ -67,8 +67,9 @@ def p(*arguments, **options, &block)
def tag_string(name, content = nil, escape_attributes: true, **options, &block)
content = @view_context.capture(self, &block) if block_given?
if (HTML_VOID_ELEMENTS.include?(name) || SVG_VOID_ELEMENTS.include?(name)) && content.nil?
"<#{name.to_s.dasherize}#{tag_options(options, escape_attributes)}>".html_safe
self_closing = SVG_SELF_CLOSING_ELEMENTS.include?(name)
if (HTML_VOID_ELEMENTS.include?(name) || self_closing) && content.nil?
"<#{name.to_s.dasherize}#{tag_options(options, escape_attributes)}#{self_closing ? " />" : ">"}".html_safe
else
content_tag_string(name.to_s.dasherize, content || "", options, escape_attributes)
end

@ -21,7 +21,7 @@ def test_tag_builder
def test_tag_builder_void_tag
assert_equal "<br>", tag.br
assert_equal "<br class=\"some_class\">", tag.br(class: "some_class")
assert_equal "<svg><use href=\"#cool-icon\"></svg>", tag.svg { tag.use("href" => "#cool-icon") }
assert_equal "<svg><use href=\"#cool-icon\" /></svg>", tag.svg { tag.use("href" => "#cool-icon") }
end
def test_tag_builder_void_tag_with_forced_content