Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove extra line between comments and templ code #351

Merged
merged 11 commits into from
Dec 26, 2023
2 changes: 1 addition & 1 deletion .version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.2.503
0.2.507
9 changes: 9 additions & 0 deletions generator/generator.go
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,15 @@ func (g *generator) writeGoExpression(n parser.TemplateFileGoExpression) (err er
return err
}
g.sourceMap.Add(n.Expression, r)
v := n.Expression.Value
lineSlice := strings.Split(v, "\n")
lastLine := lineSlice[len(lineSlice)-1]
if strings.HasPrefix(lastLine, "//") {
if _, err = g.w.WriteIndent(0, "\n"); err != nil {
return err
}
return err
}
if _, err = g.w.WriteIndent(0, "\n\n"); err != nil {
return err
}
Expand Down
22 changes: 18 additions & 4 deletions generator/generator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,22 +14,36 @@ func TestGeneratorSourceMap(t *testing.T) {
w: NewRangeWriter(w),
sourceMap: parser.NewSourceMap(),
}
exp := parser.TemplateFileGoExpression{
invalidExp := parser.TemplateFileGoExpression{
Expression: parser.Expression{
Value: "line1\nline2",
},
}
err := g.writeGoExpression(exp)
if err != nil {
if err := g.writeGoExpression(invalidExp); err != nil {
t.Fatalf("failed to write Go expression: %v", err)
}
expected := parser.NewPosition(0, 0, 0)

expected := parser.NewPosition(0, 0, 0)
actual, ok := g.sourceMap.TargetPositionFromSource(0, 0)
if !ok {
t.Errorf("failed to get matching target")
}
if diff := cmp.Diff(expected, actual); diff != "" {
t.Errorf("unexpected target:\n%v", diff)
}

withCommentExp := parser.TemplateFileGoExpression{
Expression: parser.Expression{
Value: `package main

// A comment.
templ h1() {
<h1></h1>
}
`,
},
}
if err := g.writeGoExpression(withCommentExp); err != nil {
t.Fatalf("failed to write Go expression: %v", err)
}
}
6 changes: 0 additions & 6 deletions generator/test-css-usage/template.templ
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package testcssusage

// Constant class.

templ StyleTagsAreSupported() {
<style>
.test {
Expand All @@ -25,15 +24,13 @@ templ CSSComponentsAreSupported() {

// Both CSS components and constants are supported.
// Only string names are really required. There is no need to use templ.Class or templ.SafeClass.

templ CSSComponentsAndConstantsAreSupported() {
<div class={ cssComponentGreen(), "classA", templ.Class("&&&classB"), templ.SafeClass("classC"), "d e" } type="button">Both CSS components and constants are supported</div>
// The following is also valid, but not required - you can put the class names in directly.
<div class={ templ.Classes(cssComponentGreen(), "classA", templ.Class("&&&classB"), templ.SafeClass("classC")), "d e" } type="button">Both CSS components and constants are supported</div>
}

// Maps can be used to determine if a class should be added or not.

templ MapsCanBeUsedToConditionallySetClasses() {
<div class={ map[string]bool{"a": true, "b": false, "c": true} }>Maps can be used to determine if a class should be added or not.</div>
}
Expand All @@ -53,19 +50,16 @@ templ KVCanBeUsedToConditionallySetClasses() {
}

// Pseudo attributes can be used without any special syntax.

templ PsuedoAttributesAndComplexClassNamesAreSupported() {
<div class={ "bg-violet-500", "hover:bg-red-600", "hover:bg-sky-700", "text-[#50d71e]", "w-[calc(100%-4rem)" }>Psuedo attributes and complex class names are supported.</div>
}

// Class names are HTML escaped.

templ ClassNamesAreHTMLEscaped() {
<div class={ "a\" onClick=\"alert('hello')\"" }>Class names are HTML escaped.</div>
}

// Combine all tests.

templ TestComponent() {
@StyleTagsAreSupported()
@CSSComponentsAreSupported()
Expand Down
7 changes: 0 additions & 7 deletions generator/test-css-usage/template_templ.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

32 changes: 21 additions & 11 deletions parser/v2/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,27 +125,37 @@ func (tf TemplateFile) Write(w io.Writer) error {
if err := tf.Package.Write(w, indent); err != nil {
return err
}
if _, err := w.Write([]byte("\n\n")); err != nil {
if _, err := io.WriteString(w, "\n\n"); err != nil {
return err
}
count := len(tf.Nodes)
for i := 0; i < count; i++ {
var err error
if err = tf.Nodes[i].Write(w, indent); err != nil {
for i := 0; i < len(tf.Nodes); i++ {
if err := tf.Nodes[i].Write(w, indent); err != nil {
return err
}
if i == count-1 {
_, err = w.Write([]byte("\n"))
} else {
_, err = w.Write([]byte("\n\n"))
}
if err != nil {
if _, err := io.WriteString(w, getNodeWhitespace(tf.Nodes, i)); err != nil {
return err
}
}
return nil
}

func getNodeWhitespace(nodes []TemplateFileNode, i int) string {
if i == len(nodes)-1 {
return "\n"
}
if _, nextIsTemplate := nodes[i+1].(HTMLTemplate); nextIsTemplate {
if e, isGo := nodes[i].(TemplateFileGoExpression); isGo && endsWithComment(e.Expression.Value) {
return "\n"
}
}
return "\n\n"
}

func endsWithComment(s string) bool {
lineSlice := strings.Split(s, "\n")
return strings.HasPrefix(lineSlice[len(lineSlice)-1], "//")
}

// TemplateFileNode can be a Template, CSS, Script or Go.
type TemplateFileNode interface {
IsTemplateFileNode() bool
Expand Down
19 changes: 19 additions & 0 deletions parser/v2/types_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -776,6 +776,25 @@ templ test() {
Leave this alone.
*/
}
`,
},
{
name: "godoc comments are preserved",
input: ` // first line removed to make indentation clear
package main

// test the comment handling.
templ test() {
Test
}
`,
expected: ` // first line removed to make indentation clear
package main

// test the comment handling.
templ test() {
Test
}
`,
},
}
Expand Down