diff --git a/.gitignore b/.gitignore
index fbba37a10..805cc1002 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,5 @@
cmd/example/*.go
dist
cmd/templ/templ
-cmd/lspcmd/*log.txt
+cmd/templ/lspcmd/*log.txt
.DS_Store
diff --git a/generator/generator.go b/generator/generator.go
index ccd3b4d77..76c0a83e3 100644
--- a/generator/generator.go
+++ b/generator/generator.go
@@ -393,9 +393,47 @@ func (g *generator) writeErrorHandler(indentLevel int) (err error) {
}
func (g *generator) writeElement(indentLevel int, n templ.Element) error {
- var r templ.Range
- var err error
- // Attributes.
+ if n.IsVoidElement() {
+ return g.writeVoidElement(indentLevel, n)
+ }
+ return g.writeStandardElement(indentLevel, n)
+}
+
+func (g *generator) writeVoidElement(indentLevel int, n templ.Element) (err error) {
+ if len(n.Children) > 0 {
+ return fmt.Errorf("writeVoidElement: void element %q must not have child elements", n.Name)
+ }
+ if len(n.Attributes) == 0 {
+ //
if _, err = g.w.WriteIndent(indentLevel, fmt.Sprintf(`_, err = io.WriteString(w, "<%s>")`+"\n", html.EscapeString(n.Name))); err != nil {
@@ -412,60 +450,8 @@ func (g *generator) writeElement(indentLevel int, n templ.Element) error {
if err = g.writeErrorHandler(indentLevel); err != nil {
return err
}
- for i := 0; i < len(n.Attributes); i++ {
- switch attr := n.Attributes[i].(type) {
- case templ.ConstantAttribute:
- name := html.EscapeString(attr.Name)
- value := html.EscapeString(attr.Value)
- if _, err = g.w.WriteIndent(indentLevel, fmt.Sprintf(`_, err = io.WriteString(w, " %s=\"%s\"")`+"\n", name, value)); err != nil {
- return err
- }
- if err = g.writeErrorHandler(indentLevel); err != nil {
- return err
- }
- case templ.ExpressionAttribute:
- name := html.EscapeString(attr.Name)
- // Name
- if _, err = g.w.WriteIndent(indentLevel, fmt.Sprintf(`_, err = io.WriteString(w, " %s=")`+"\n", name)); err != nil {
- return err
- }
- if err = g.writeErrorHandler(indentLevel); err != nil {
- return err
- }
- // Value.
- // Open quote.
- if _, err = g.w.WriteIndent(indentLevel, `_, err = io.WriteString(w, "\"")`+"\n"); err != nil {
- return err
- }
- if err = g.writeErrorHandler(indentLevel); err != nil {
- return err
- }
- // io.WriteString(w, templ.EscapeString(
- if _, err = g.w.WriteIndent(indentLevel, "_, err = io.WriteString(w, templ.EscapeString("); err != nil {
- return err
- }
- // p.Name()
- if r, err = g.w.Write(attr.Expression.Value); err != nil {
- return err
- }
- g.sourceMap.Add(attr.Expression, r)
- // ))
- if _, err = g.w.Write("))\n"); err != nil {
- return err
- }
- if err = g.writeErrorHandler(indentLevel); err != nil {
- return err
- }
- // Close quote.
- if _, err = g.w.WriteIndent(indentLevel, `_, err = io.WriteString(w, "\"")`+"\n"); err != nil {
- return err
- }
- if err = g.writeErrorHandler(indentLevel); err != nil {
- return err
- }
- default:
- return fmt.Errorf("unknown attribute type %s", reflect.TypeOf(n.Attributes[i]))
- }
+ if err = g.writeElementAttributes(indentLevel, n); err != nil {
+ return err
}
// >
if _, err = g.w.WriteIndent(indentLevel, `_, err = io.WriteString(w, ">")`+"\n"); err != nil {
@@ -484,7 +470,67 @@ func (g *generator) writeElement(indentLevel int, n templ.Element) error {
if err = g.writeErrorHandler(indentLevel); err != nil {
return err
}
- return nil
+ return err
+}
+
+func (g *generator) writeElementAttributes(indentLevel int, n templ.Element) (err error) {
+ var r templ.Range
+ for i := 0; i < len(n.Attributes); i++ {
+ switch attr := n.Attributes[i].(type) {
+ case templ.ConstantAttribute:
+ name := html.EscapeString(attr.Name)
+ value := html.EscapeString(attr.Value)
+ if _, err = g.w.WriteIndent(indentLevel, fmt.Sprintf(`_, err = io.WriteString(w, " %s=\"%s\"")`+"\n", name, value)); err != nil {
+ return err
+ }
+ if err = g.writeErrorHandler(indentLevel); err != nil {
+ return err
+ }
+ case templ.ExpressionAttribute:
+ name := html.EscapeString(attr.Name)
+ // Name
+ if _, err = g.w.WriteIndent(indentLevel, fmt.Sprintf(`_, err = io.WriteString(w, " %s=")`+"\n", name)); err != nil {
+ return err
+ }
+ if err = g.writeErrorHandler(indentLevel); err != nil {
+ return err
+ }
+ // Value.
+ // Open quote.
+ if _, err = g.w.WriteIndent(indentLevel, `_, err = io.WriteString(w, "\"")`+"\n"); err != nil {
+ return err
+ }
+ if err = g.writeErrorHandler(indentLevel); err != nil {
+ return err
+ }
+ // io.WriteString(w, templ.EscapeString(
+ if _, err = g.w.WriteIndent(indentLevel, "_, err = io.WriteString(w, templ.EscapeString("); err != nil {
+ return err
+ }
+ // p.Name()
+ if r, err = g.w.Write(attr.Expression.Value); err != nil {
+ return err
+ }
+ g.sourceMap.Add(attr.Expression, r)
+ // ))
+ if _, err = g.w.Write("))\n"); err != nil {
+ return err
+ }
+ if err = g.writeErrorHandler(indentLevel); err != nil {
+ return err
+ }
+ // Close quote.
+ if _, err = g.w.WriteIndent(indentLevel, `_, err = io.WriteString(w, "\"")`+"\n"); err != nil {
+ return err
+ }
+ if err = g.writeErrorHandler(indentLevel); err != nil {
+ return err
+ }
+ default:
+ return fmt.Errorf("unknown attribute type %s", reflect.TypeOf(n.Attributes[i]))
+ }
+ }
+ return err
}
func (g *generator) writeStringExpression(indentLevel int, e templ.Expression) error {
diff --git a/generator/test-void/render_test.go b/generator/test-void/render_test.go
new file mode 100644
index 000000000..5b0350ff7
--- /dev/null
+++ b/generator/test-void/render_test.go
@@ -0,0 +1,22 @@
+package testvoid
+
+import (
+ "context"
+ "strings"
+ "testing"
+
+ "github.com/google/go-cmp/cmp"
+)
+
+const expected = `
`
+
+func TestRender(t *testing.T) {
+ w := new(strings.Builder)
+ err := render().Render(context.Background(), w)
+ if err != nil {
+ t.Errorf("failed to render: %v", err)
+ }
+ if diff := cmp.Diff(expected, w.String()); diff != "" {
+ t.Error(diff)
+ }
+}
diff --git a/generator/test-void/template.templ b/generator/test-void/template.templ
new file mode 100644
index 000000000..35a255a1b
--- /dev/null
+++ b/generator/test-void/template.templ
@@ -0,0 +1,8 @@
+{% package testvoid %}
+
+{% templ render() %}
+
+
+
+{% endtempl %}
+
diff --git a/generator/test-void/template_templ.go b/generator/test-void/template_templ.go
new file mode 100644
index 000000000..cf90e3712
--- /dev/null
+++ b/generator/test-void/template_templ.go
@@ -0,0 +1,38 @@
+// Code generated by templ DO NOT EDIT.
+
+package testvoid
+
+import "github.com/a-h/templ"
+import "context"
+import "io"
+
+func render() templ.Component {
+ return templ.ComponentFunc(func(ctx context.Context, w io.Writer) (err error) {
+ _, err = io.WriteString(w, "
")
+ if err != nil {
+ return err
+ }
+ _, err = io.WriteString(w, "
")
+ if err != nil {
+ return err
+ }
+ _, err = io.WriteString(w, "
")
+ if err != nil {
+ return err
+ }
+ _, err = io.WriteString(w, "
")
+ if err != nil {
+ return err
+ }
+ return err
+ })
+}
+
diff --git a/types.go b/types.go
index 52e845706..1491e22fb 100644
--- a/types.go
+++ b/types.go
@@ -248,7 +248,7 @@ var voidElements = map[string]struct{}{
"area": {}, "base": {}, "br": {}, "col": {}, "command": {}, "embed": {}, "hr": {}, "img": {}, "input": {}, "keygen": {}, "link": {}, "meta": {}, "param": {}, "source": {}, "track": {}, "wbr": {}}
// https://www.w3.org/TR/2011/WD-html-markup-20110113/syntax.html#void-element
-func (e Element) isVoidElement() bool {
+func (e Element) IsVoidElement() bool {
_, ok := voidElements[e.Name]
return ok
}
@@ -328,7 +328,7 @@ func (e Element) Write(w io.Writer, indent int) error {
}
return nil
}
- if e.isVoidElement() {
+ if e.IsVoidElement() {
if _, err := w.Write([]byte("/>")); err != nil {
return err
}