diff --git a/spec/blueprint/html/attributes_handling_spec.cr b/spec/blueprint/html/attributes_handling_spec.cr
index 983bd6a..c92b5c4 100644
--- a/spec/blueprint/html/attributes_handling_spec.cr
+++ b/spec/blueprint/html/attributes_handling_spec.cr
@@ -114,4 +114,36 @@ describe "attributes handling" do
actual_html.should eq expected_html
end
+
+ it "raises error if attribute names include unsafe characters" do
+ # Hash
+ {% for character in ["<", ">", "&", %("), "'"] %}
+ expect_raises(Blueprint::HTML::ArgumentError, %(Unsafe attribute name: `attr-{{character.id}}`)) do
+ Blueprint::HTML.build do
+ div({ %(attr-{{character.id}}) => "some value"}) do
+ "Blueprint"
+ end
+ end
+ end
+ {% end %}
+
+ # NamedTuple
+ {% for character in ["<", ">", "&", "'"] %}
+ expect_raises(Blueprint::HTML::ArgumentError, %(Unsafe attribute name: `attr-{{character.id}}`)) do
+ Blueprint::HTML.build do
+ div("attr-{{character.id}}": "some value") do
+ "Blueprint"
+ end
+ end
+ end
+ {% end %}
+
+ expect_raises(Blueprint::HTML::ArgumentError, %(Unsafe attribute name: `attr-"`)) do
+ Blueprint::HTML.build do
+ div("attr-\"": "some value") do
+ "Blueprint"
+ end
+ end
+ end
+ end
end
diff --git a/src/blueprint/html/attributes_renderer.cr b/src/blueprint/html/attributes_renderer.cr
index 172dfb2..1477493 100644
--- a/src/blueprint/html/attributes_renderer.cr
+++ b/src/blueprint/html/attributes_renderer.cr
@@ -76,11 +76,15 @@ module Blueprint::HTML::AttributesRenderer
append_value buffer, value.to_s
end
- private def parse_name(name : Symbol) : String
- name.to_s.gsub("_", "-")
- end
-
private def parse_name(name : String) : String
+ if name.matches?(/[<>&"']/)
+ raise Blueprint::HTML::ArgumentError.new("Unsafe attribute name: `#{name}`")
+ end
+
name
end
+
+ private def parse_name(name : Symbol) : String
+ parse_name(name.to_s.gsub("_", "-"))
+ end
end
diff --git a/src/blueprint/html/errors.cr b/src/blueprint/html/errors.cr
new file mode 100644
index 0000000..af51ff0
--- /dev/null
+++ b/src/blueprint/html/errors.cr
@@ -0,0 +1,2 @@
+class Blueprint::HTML::ArgumentError < ArgumentError
+end