From 12905a571e60c1e1aff1428d75184bd462cc1eb0 Mon Sep 17 00:00:00 2001 From: stephann <3025661+stephannv@users.noreply.github.com> Date: Sat, 12 Oct 2024 17:56:39 -0300 Subject: [PATCH] feat: Change attribute value escaper (#84) --- spec/blueprint/html/safety_spec.cr | 4 +- src/blueprint/html/attributes_handler.cr | 58 +++++++++++++++--------- src/blueprint/html/buffer_appender.cr | 8 +++- src/blueprint/html/utils.cr | 2 +- 4 files changed, 46 insertions(+), 26 deletions(-) diff --git a/spec/blueprint/html/safety_spec.cr b/spec/blueprint/html/safety_spec.cr index 1542772..d2029b7 100644 --- a/spec/blueprint/html/safety_spec.cr +++ b/spec/blueprint/html/safety_spec.cr @@ -65,7 +65,7 @@ describe "safety" do it "escapes attribute values" do page = Example.new expected_html = normalize_html <<-HTML -
+
HTML page.to_s.should contain(expected_html) @@ -92,7 +92,7 @@ describe "safety" do it "escapes custom tag content passed via block" do page = Example.new expected_html = normalize_html <<-HTML - <script>alert('hello')</script> + <script>alert('hello')</script> HTML page.to_s.should contain(expected_html) diff --git a/src/blueprint/html/attributes_handler.cr b/src/blueprint/html/attributes_handler.cr index aa2d2e1..4cf0bac 100644 --- a/src/blueprint/html/attributes_handler.cr +++ b/src/blueprint/html/attributes_handler.cr @@ -5,47 +5,63 @@ module Blueprint::HTML::AttributesHandler end end - private def append_attribute(attribute_name, attribute_value) : Nil - case attribute_value + private def append_attribute(name, value) : Nil + case value when Nil, false # does nothing when true - append_boolean_attribute(attribute_name) + append_boolean_attribute(name) when NamedTuple - process_named_tuple_attribute(attribute_name, attribute_value) + process_named_tuple_attribute(name, value) when Array - append_array_attribute(attribute_name, attribute_value) + append_array_attribute(name, value) else - append_normal_attribute(attribute_name, attribute_value) + append_normal_attribute(name, value) end end - private def append_normal_attribute(attribute_name, attribute_value) : Nil + private def append_boolean_attribute(name) : Nil @buffer << " " - @buffer << parse_attribute_name(attribute_name) + @buffer << parse_name(name) + end + + private def append_array_attribute(name, value : Array) : Nil + append_normal_attribute(name, value.flatten.compact.join(" ")) + end + + private def process_named_tuple_attribute(name, value : NamedTuple) : Nil + name_prefix = parse_name(name) + + value.each do |attr_name, attr_value| + append_attribute("#{name_prefix}-#{parse_name(attr_name)}", attr_value) + end + end + + private def append_normal_attribute(name, value) : Nil + @buffer << " " + @buffer << parse_name(name) @buffer << %(=") - append_to_buffer(attribute_value) + append_attribute_value(value) @buffer << %(") end - private def append_boolean_attribute(attribute_name) : Nil - @buffer << " " - @buffer << parse_attribute_name(attribute_name) + private def append_attribute_value(value : String) : Nil + @buffer << value.gsub('"', """) end - private def append_array_attribute(attribute_name, attribute_value : Array) : Nil - append_normal_attribute(attribute_name, attribute_value.flatten.compact.join(" ")) + private def append_attribute_value(value : SafeObject) : Nil + value.to_s @buffer end - private def process_named_tuple_attribute(attribute_name, attribute_value : NamedTuple) : Nil - attribute_name_prefix = parse_attribute_name(attribute_name) + private def append_attribute_value(value : Number) : Nil + value.to_s @buffer + end - attribute_value.each do |name, value| - append_attribute("#{attribute_name_prefix}-#{parse_attribute_name(name)}", value) - end + private def append_attribute_value(value) : Nil + append_attribute_value value.to_s end - private def parse_attribute_name(attribute_name) : String - attribute_name.to_s.gsub("_", "-") + private def parse_name(name) : String + name.to_s.gsub("_", "-") end end diff --git a/src/blueprint/html/buffer_appender.cr b/src/blueprint/html/buffer_appender.cr index 154e98c..9410e8c 100644 --- a/src/blueprint/html/buffer_appender.cr +++ b/src/blueprint/html/buffer_appender.cr @@ -1,6 +1,6 @@ module Blueprint::HTML::BufferAppender private def append_to_buffer(content : String) - ::HTML.escape(content, @buffer) + escape(content, @buffer) end private def append_to_buffer(content : SafeObject) @@ -11,6 +11,10 @@ module Blueprint::HTML::BufferAppender end private def append_to_buffer(content) - ::HTML.escape(content.to_s, @buffer) + escape(content.to_s, @buffer) + end + + private def escape(value : String, io : IO) + ::HTML.escape(value, io) end end diff --git a/src/blueprint/html/utils.cr b/src/blueprint/html/utils.cr index f2eeb0c..253064a 100644 --- a/src/blueprint/html/utils.cr +++ b/src/blueprint/html/utils.cr @@ -17,7 +17,7 @@ module Blueprint::HTML::Utils @buffer << " " end - def raw(content : SafeObject) : Nil + private def raw(content : SafeObject) : Nil append_to_buffer(content) end end