From 3814826885c910a885dcb6f332408d4839440110 Mon Sep 17 00:00:00 2001 From: Dave Kroondyk Date: Mon, 28 Feb 2022 17:52:00 -0500 Subject: [PATCH] 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 --- actionview/lib/action_view/helpers/tag_helper.rb | 7 ++++--- actionview/test/template/tag_helper_test.rb | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/actionview/lib/action_view/helpers/tag_helper.rb b/actionview/lib/action_view/helpers/tag_helper.rb index 33d633c43a..bfb9c0c81c 100644 --- a/actionview/lib/action_view/helpers/tag_helper.rb +++ b/actionview/lib/action_view/helpers/tag_helper.rb @@ -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 diff --git a/actionview/test/template/tag_helper_test.rb b/actionview/test/template/tag_helper_test.rb index 97191fd5d9..d32ed734db 100644 --- a/actionview/test/template/tag_helper_test.rb +++ b/actionview/test/template/tag_helper_test.rb @@ -21,7 +21,7 @@ def test_tag_builder def test_tag_builder_void_tag assert_equal "
", tag.br assert_equal "
", tag.br(class: "some_class") - assert_equal "", tag.svg { tag.use("href" => "#cool-icon") } + assert_equal "", tag.svg { tag.use("href" => "#cool-icon") } end def test_tag_builder_void_tag_with_forced_content