diff --git a/spec/instance_tag_attrs/tag_spec.cr b/spec/instance_tag_attrs/tag_spec.cr
index 080556d..b6b9bc5 100644
--- a/spec/instance_tag_attrs/tag_spec.cr
+++ b/spec/instance_tag_attrs/tag_spec.cr
@@ -47,12 +47,12 @@ module ToHtml::InstanceTagAttrs::TagSpec
expected = <<-HTML
HTML
diff --git a/spec/instance_template/void_element_spec.cr b/spec/instance_template/void_element_spec.cr
new file mode 100644
index 0000000..a49a722
--- /dev/null
+++ b/spec/instance_template/void_element_spec.cr
@@ -0,0 +1,66 @@
+require "../spec_helper"
+
+module ToHtml::InstanceTemplate::VoidElementSpec
+ class MyView
+ ToHtml.class_template do
+ div do
+ span { "First line" }
+ br
+ span { "Second line" }
+ hr
+ embed MyVideo.new("/media/video.mp4")
+ hr
+ form action: "/inputs", method: "POST" do
+ input MyInputField.new("foo"), placeholder: "bar"
+ input type: "submit", name: "submit", value: "Submit"
+ end
+ end
+ end
+ end
+
+ class MyVideo
+ getter path : String
+
+ def initialize(@path); end
+
+ ToHtml.instance_tag_attrs do
+ type = "video/webm"
+ src = path
+ width = "250"
+ height = "200"
+ end
+ end
+
+ class MyInputField
+ getter field_value : String
+
+ def initialize(@field_value); end
+
+ ToHtml.instance_tag_attrs do
+ type = "text"
+ name = "name"
+ value = field_value
+ end
+ end
+
+ describe "MyView.to_html" do
+ it "should render void elements correctly" do
+ expected = <<-HTML.squish
+
+ First line
+
+ Second line
+
+
+ HTML
+
+ MyView.to_html.should eq(expected)
+ end
+ end
+end
diff --git a/src/instance_template.cr b/src/instance_template.cr
index fb4c3fc..7106947 100644
--- a/src/instance_template.cr
+++ b/src/instance_template.cr
@@ -57,7 +57,9 @@ module ToHtml
end
macro to_html_eval_exp(io, indent_level, break_line = true, &blk)
- {% if blk.body.is_a?(Call) && ToHtml::TAG_NAMES.includes?(blk.body.name.stringify) %}
+ {% if blk.body.is_a?(Call) && ToHtml::VOID_TAG_NAMES.includes?(blk.body.name.stringify) %}
+ ToHtml.to_html_add_void_tag({{io}}, {{indent_level}}, {{break_line}}, {{blk.body}})
+ {% elsif blk.body.is_a?(Call) && ToHtml::TAG_NAMES.includes?(blk.body.name.stringify) %}
ToHtml.to_html_add_tag({{io}}, {{indent_level}}, {{break_line}}, {{blk.body}})
{% elsif blk.body.is_a?(Call) && blk.body.name.stringify == "doctype" %}
{{io}} << ""
@@ -127,12 +129,6 @@ module ToHtml
{% else %}
%attr_hash = ToHtml::AttributeHash.new
- {% if call.named_args %}
- {% for named_arg in call.named_args %}
- %attr_hash[{{named_arg.name.stringify}}] = {{named_arg.value}}.to_s
- {% end %}
- {% end %}
-
{% for arg in call.args %}
{% if arg.is_a?(TupleLiteral) %}
%attr_hash[{{arg}}.first] = {{arg}}.last
@@ -141,6 +137,12 @@ module ToHtml
{% end %}
{% end %}
+ {% if call.named_args %}
+ {% for named_arg in call.named_args %}
+ %attr_hash[{{named_arg.name.stringify}}] = {{named_arg.value}}.to_s
+ {% end %}
+ {% end %}
+
{{io}} << "<{{call.name}}"
{{io}} << " " unless %attr_hash.empty?
{{io}} << %attr_hash
@@ -168,4 +170,39 @@ module ToHtml
{% end %}
{% end %}
end
+
+ macro to_html_add_void_tag(io, indent_level, break_line, call)
+ {% if flag?(:to_html_pretty) %}
+ {{io}} << " " * {{indent_level}}
+ {% end %}
+ {% if call.args.empty? && !call.named_args %}
+ {{io}} << "<{{call.name}}>"
+ {% elsif call.args.empty? && call.named_args %}
+ {{io}} << "<{{call.name}} " + {{ call.named_args.map { |a| "#{a.name}=#{a.value}" }.join(" ") }} + ">"
+ {% else %}
+ %attr_hash = ToHtml::AttributeHash.new
+
+ {% for arg in call.args %}
+ {% if arg.is_a?(TupleLiteral) %}
+ %attr_hash[{{arg}}.first] = {{arg}}.last
+ {% else %}
+ {{arg}}.to_html_attrs({{call.name.stringify}}, %attr_hash)
+ {% end %}
+ {% end %}
+
+ {% if call.named_args %}
+ {% for named_arg in call.named_args %}
+ %attr_hash[{{named_arg.name.stringify}}] = {{named_arg.value}}.to_s
+ {% end %}
+ {% end %}
+
+ {{io}} << "<{{call.name}}"
+ {{io}} << " " unless %attr_hash.empty?
+ {{io}} << %attr_hash
+ {{io}} << ">"
+ {% end %}
+ {% if flag?(:to_html_pretty) && break_line %}
+ {{io}} << "\n"
+ {% end %}
+ end
end
diff --git a/src/tag_names.cr b/src/tag_names.cr
index 99f75f0..5ba2a68 100644
--- a/src/tag_names.cr
+++ b/src/tag_names.cr
@@ -3,23 +3,19 @@ module ToHtml
a
abbr
address
- area
article
aside
audio
b
- base
bdi
bdo
blockquote
body
- br
button
canvas
caption
cite
code
- col
colgroup
data
datalist
@@ -32,7 +28,6 @@ module ToHtml
dl
dt
em
- embed
fieldset
figcaption
figure
@@ -46,23 +41,18 @@ module ToHtml
h6
head
header
- hr
html
i
iframe
- img
- input
ins
kbd
label
legend
li
- link
main
map
mark
menu
- meta
meter
nav
noscript
@@ -72,7 +62,6 @@ module ToHtml
option
output
p
- param
picture
pre
progress
@@ -86,7 +75,6 @@ module ToHtml
section
select
small
- source
span
strong
style
@@ -105,11 +93,26 @@ module ToHtml
time
title
tr
- track
u
ul
var
video
+ ]
+
+ VOID_TAG_NAMES = %w[
+ area
+ base
+ br
+ col
+ embed
+ hr
+ img
+ input
+ link
+ meta
+ param
+ source
+ track
wbr
]
end