diff --git a/.version b/.version
index 61cca7fec..2e6eccf36 100644
--- a/.version
+++ b/.version
@@ -1 +1 @@
-0.2.508
\ No newline at end of file
+0.2.513
\ No newline at end of file
diff --git a/README.md b/README.md
index 2c9ef26e4..433d96a4e 100644
--- a/README.md
+++ b/README.md
@@ -78,18 +78,20 @@ Run Go tests.
# Create test profile directories.
mkdir -p coverage/fmt
mkdir -p coverage/generate
+mkdir -p coverage/version
mkdir -p coverage/unit
# Build the test binary.
go build -cover -o ./coverage/templ-cover ./cmd/templ
# Run the covered generate command.
GOCOVERDIR=coverage/fmt ./coverage/templ-cover fmt .
GOCOVERDIR=coverage/generate ./coverage/templ-cover generate -include-version=false
+GOCOVERDIR=coverage/version ./coverage/templ-cover version
# Run the unit tests.
go test -cover ./... -args -test.gocoverdir="$PWD/coverage/unit"
# Display the combined percentage.
-go tool covdata percent -i=./coverage/fmt,./coverage/generate,./coverage/unit
+go tool covdata percent -i=./coverage/fmt,./coverage/generate,./coverage/version,./coverage/unit
# Generate a text coverage profile for tooling to use.
-go tool covdata textfmt -i=./coverage/fmt,./coverage/generate,./coverage/unit -o coverage.out
+go tool covdata textfmt -i=./coverage/fmt,./coverage/generate,./coverage/version,./coverage/unit -o coverage.out
# Print total
go tool cover -func coverage.out | grep total
```
diff --git a/generator/test-attribute-escaping/expected.html b/generator/test-attribute-escaping/expected.html
index 9d7518fb4..fcf154db4 100644
--- a/generator/test-attribute-escaping/expected.html
+++ b/generator/test-attribute-escaping/expected.html
@@ -1,3 +1,6 @@
+
+ Click
+
diff --git a/generator/test-attribute-escaping/template.templ b/generator/test-attribute-escaping/template.templ
index 232096bfc..1f1926f09 100644
--- a/generator/test-attribute-escaping/template.templ
+++ b/generator/test-attribute-escaping/template.templ
@@ -4,4 +4,11 @@ templ BasicTemplate(url string) {
+
+ Click
+
}
diff --git a/generator/test-attribute-escaping/template_templ.go b/generator/test-attribute-escaping/template_templ.go
index 2ec88a2a2..f246967d9 100644
--- a/generator/test-attribute-escaping/template_templ.go
+++ b/generator/test-attribute-escaping/template_templ.go
@@ -40,7 +40,16 @@ func BasicTemplate(url string) templ.Component {
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("")
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Var4 := `Click`
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var4)
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
diff --git a/parser/v2/elementparser.go b/parser/v2/elementparser.go
index e8b9d71c7..590016f0b 100644
--- a/parser/v2/elementparser.go
+++ b/parser/v2/elementparser.go
@@ -131,6 +131,7 @@ var (
if result.B.OK {
valueParser = attributeConstantValueSingleQuoteParser
closeParser = parse.String(`'`)
+ attr.SingleQuote = true
}
// Attribute value.
@@ -140,6 +141,10 @@ var (
}
attr.Value = html.UnescapeString(attr.Value)
+ // Only use single quotes if actually required, due to double quote in the value (prefer double quotes).
+ if attr.SingleQuote && !strings.Contains(attr.Value, "\"") {
+ attr.SingleQuote = false
+ }
// " - closing quote.
if _, ok, err = closeParser.Parse(pi); err != nil || !ok {
diff --git a/parser/v2/elementparser_test.go b/parser/v2/elementparser_test.go
index 89cd455ff..3d673e83e 100644
--- a/parser/v2/elementparser_test.go
+++ b/parser/v2/elementparser_test.go
@@ -271,12 +271,23 @@ if test {
},
},
{
- name: "single quote constant attribute",
+ name: "single quote not required constant attribute",
+ input: ` href='no double quote in value'`,
+ parser: StripType(constantAttributeParser),
+ expected: ConstantAttribute{
+ Name: "href",
+ Value: `no double quote in value`,
+ SingleQuote: false,
+ },
+ },
+ {
+ name: "single quote required constant attribute",
input: ` href='"test"'`,
parser: StripType(constantAttributeParser),
expected: ConstantAttribute{
- Name: "href",
- Value: `"test"`,
+ Name: "href",
+ Value: `"test"`,
+ SingleQuote: true,
},
},
{
diff --git a/parser/v2/templelementparser_test.go b/parser/v2/templelementparser_test.go
index 60c6853bc..4cf93f48f 100644
--- a/parser/v2/templelementparser_test.go
+++ b/parser/v2/templelementparser_test.go
@@ -108,7 +108,10 @@ func TestTemplElementExpressionParser(t *testing.T) {
Children: []Node{
Whitespace{Value: "\n\t\t\t"},
Element{Name: "a", Attributes: []Attribute{
- ConstantAttribute{"href", "someurl"},
+ ConstantAttribute{
+ Name: "href",
+ Value: "someurl",
+ },
},
TrailingSpace: SpaceVertical,
},
diff --git a/parser/v2/types.go b/parser/v2/types.go
index fc3dcec7e..2bd7242e5 100644
--- a/parser/v2/types.go
+++ b/parser/v2/types.go
@@ -690,12 +690,17 @@ func (bca BoolConstantAttribute) Write(w io.Writer, indent int) error {
// href=""
type ConstantAttribute struct {
- Name string
- Value string
+ Name string
+ Value string
+ SingleQuote bool
}
func (ca ConstantAttribute) String() string {
- return ca.Name + `="` + ca.Value + `"`
+ quote := `"`
+ if ca.SingleQuote {
+ quote = `'`
+ }
+ return ca.Name + `=` + quote + ca.Value + quote
}
func (ca ConstantAttribute) Write(w io.Writer, indent int) error {
diff --git a/parser/v2/types_test.go b/parser/v2/types_test.go
index e0ef4926c..756c9578b 100644
--- a/parser/v2/types_test.go
+++ b/parser/v2/types_test.go
@@ -236,6 +236,28 @@ package test
templ nested() {
}
+`,
+ },
+ {
+ name: "constant attributes prerfer double quotes, but use single quotes if required",
+ input: ` // first line removed to make indentation clear in Go code
+package test
+
+templ nested() {
+ double
+ single-not-required
+ single-required
+}
+
+`,
+ expected: `// first line removed to make indentation clear in Go code
+package test
+
+templ nested() {
+ double
+ single-not-required
+ single-required
+}
`,
},
{