| ... | @@ -39,7 +39,11 @@ fn do(writer: anytype, comptime value: astgen.Value, data: anytype, ctx: anytype | ... | @@ -39,7 +39,11 @@ fn do(writer: anytype, comptime value: astgen.Value, data: anytype, ctx: anytype |
| 39 | } | 39 | } |
| 40 | | 40 | |
| 41 | if (v.children.len == 0) { | 41 | if (v.children.len == 0) { |
| 42 | try writer.writeAll(" />\n"); | 42 | if (contains(std.meta.fieldNames(HtmlVoidElements), v.name)) { |
| | 43 | try writer.writeAll(" />\n"); |
| | 44 | } else { |
| | 45 | try writer.print("></{s}>\n", .{v.name}); |
| | 46 | } |
| 43 | } else { | 47 | } else { |
| 44 | try writer.writeAll(">"); | 48 | try writer.writeAll(">"); |
| 45 | | 49 | |
| ... | @@ -179,3 +183,29 @@ fn entityLookupBefore(in: []const u8) ?htmlentities.Entity { | ... | @@ -179,3 +183,29 @@ fn entityLookupBefore(in: []const u8) ?htmlentities.Entity { |
| 179 | fn assertEqual(comptime a: usize, comptime b: usize) void { | 183 | fn assertEqual(comptime a: usize, comptime b: usize) void { |
| 180 | if (a != b) @compileError(std.fmt.comptimePrint("{d} != {d}", .{ a, b })); | 184 | if (a != b) @compileError(std.fmt.comptimePrint("{d} != {d}", .{ a, b })); |
| 181 | } | 185 | } |
| | 186 | |
| | 187 | const HtmlVoidElements = enum { |
| | 188 | area, |
| | 189 | base, |
| | 190 | br, |
| | 191 | col, |
| | 192 | embed, |
| | 193 | hr, |
| | 194 | img, |
| | 195 | input, |
| | 196 | link, |
| | 197 | meta, |
| | 198 | param, |
| | 199 | source, |
| | 200 | track, |
| | 201 | wbr, |
| | 202 | }; |
| | 203 | |
| | 204 | fn contains(haystack: []const []const u8, needle: []const u8) bool { |
| | 205 | for (haystack) |v| { |
| | 206 | if (std.mem.eql(u8, v, needle)) { |
| | 207 | return true; |
| | 208 | } |
| | 209 | } |
| | 210 | return false; |
| | 211 | } |