Repository: a-h/templ (Go)

Issue:
parser: error when a template with arguments on new lines comes after go code
I believe I've narrowed the issue down to a minimal reproduction.

Version: a5c60767ef03cfb52db78cb666df5a8df9f7a7a5

Create an index.templ with the contents:

```
package main

var a = "a"

templ template(
	a string,
) {
}
```

Run `templ generate`:

```
(✗) Error generating code [ file=index.templ source formatting error: 12:1: expected declaration, found templ ]
(✗) Event handler failed [ error=failed to generate code for "index.templ": index.templ source formatting error: 12:1: expected declaration, found templ ]
panic: send on closed channel

goroutine 18 [running]:
github.com/a-h/templ/cmd/templ/generatecmd.Generate.Run.func3.1({{0xc0001160c0?, 0xc000069f80?}, 0x69f70?})
        /Users/joe.davidson/src/joerdav/templ/cmd/templ/generatecmd/cmd.go:173 +0x35f
created by github.com/a-h/templ/cmd/templ/generatecmd.Generate.Run.func3 in goroutine 10
        /Users/joe.davidson/src/joerdav/templ/cmd/templ/generatecmd/cmd.go:166 +0x15f

```


Discussion:
I've narrowed the issue down to this line: https://github.com/a-h/templ/blob/main/parser/v2/templatefile.go#L163

It keeps assuming Go code until it finds a line of code that starts with `templ ` and ends with `{`. Of course this logic breaks down if you have a template whose arguments are split across lines.

I'm proposing we remove the check for `{` entirely, do you see any issue with this @a-h ?
Something to weed out the edge cases might be to check if the line contains an open bracket `(`.
I've also found an issue with having go code with multiple sets of curly braces  after a for loop:

The following produces the error: `■ for: expected nodes, but none were found: line 5, col 7`
```
package views

templ Nav() {
<div>
	for _, l := range links {
	<a>{ l.Title }</a>
	}
</div>
}

var links = []struct { }{ }
```
templ NavBar(links []Links){
    <header>
        <nav>
            <ul>
                for _, link := range links{ 
                    <li><a href = {temp.URL(link.Href)}></a></li>
                    }
            </ul>
        </nav>
    </header>
    <br />
}

keeps giving the error "home.templ parsing error: for: expected nodes, but none were found"
please help
@kamukwamba - the formatting is messed up, I can't really see what you're talking about.

An MRE (https://en.wikipedia.org/wiki/Minimal_reproducible_example) really helps with testing. If you drop a tiny example in a Github repo, it makes it much easier to work out.

Also, this is a closed issue, and your issue seems unrelated. You should probably make a new issue.



Patch:
diff --git a/parser/v2/templatefile.go b/parser/v2/templatefile.go
index af1b7a005..2c2fc55fa 100644
--- a/parser/v2/templatefile.go
+++ b/parser/v2/templatefile.go
@@ -160,7 +160,7 @@ outer:
 				return
 			}
 			hasTemplatePrefix := strings.HasPrefix(l, "templ ") || strings.HasPrefix(l, "css ") || strings.HasPrefix(l, "script ")
-			if hasTemplatePrefix && strings.HasSuffix(l, "{") {
+			if hasTemplatePrefix && strings.Contains(l, "(") {
 				// Unread the line.
 				pi.Seek(last)
 				// Take the code so far.


Test patch:
diff --git a/parser/v2/templatefile_test.go b/parser/v2/templatefile_test.go
index 51f61e409..cd0b91aa9 100644
--- a/parser/v2/templatefile_test.go
+++ b/parser/v2/templatefile_test.go
@@ -125,6 +125,39 @@ const y = ` + "`456`"
 			t.Errorf("2: unexpected expression: %q", expr.Expression.Value)
 		}
 	})
+	// https://github.com/a-h/templ/issues/505
+	t.Run("template files can contain go expressions followed by multiline templates", func(t *testing.T) {
+		input := `package goof
+
+var a = "a"
+
+templ template(
+	a string,
+) {
+}`
+		tf, err := ParseString(input)
+		if err != nil {
+			t.Fatalf("failed to parse template, with t.Fatalf(parser %v", err)
+		}
+		if len(tf.Nodes) != 2 {
+			var nodeTypes []string
+			for _, n := range tf.Nodes {
+				nodeTypes = append(nodeTypes, reflect.TypeOf(n).Name())
+			}
+			t.Fatalf("expected 2 nodes, got %d nodes, %v\n%#v", len(tf.Nodes), nodeTypes, tf)
+		}
+		expr, isGoExpression := tf.Nodes[0].(TemplateFileGoExpression)
+		if !isGoExpression {
+			t.Errorf("0: expected expression, got %t", tf.Nodes[2])
+		}
+		if expr.Expression.Value != `var a = "a"` {
+			t.Errorf("0: unexpected expression: %q", expr.Expression.Value)
+		}
+		_, isGoExpression = tf.Nodes[1].(HTMLTemplate)
+		if !isGoExpression {
+			t.Errorf("2: expected expression, got %t", tf.Nodes[2])
+		}
+	})
 }
 
 func TestTemplateFileRoundTrip(t *testing.T) {