refactor: allow more flexible parsing of expression attributes#1197
refactor: allow more flexible parsing of expression attributes#1197
Conversation
a-h
commented
Jun 17, 2025
- chore: bump version [no-ci]
- refactor: allow more flexible parsing of expression attributes
There was a problem hiding this comment.
Pull Request Overview
This PR refactors the attribute parsing logic to accept optional whitespace around the = and { in expression attributes, adds a new test for that behavior, updates templating formatter test data to reflect spacing rules, and bumps the version.
- Bump version to 0.3.903
- Allow optional whitespace in attribute value parsing and introduce
expressionAttributeStartParser - Add test case for space before
={in expression attributes and update formatting tests
Reviewed Changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| parser/v2/elementparser_test.go | Added test for parsing an expression attribute with space before ={ |
| parser/v2/elementparser.go | Updated attributeValueParsers to use parse.OptionalWhitespace and introduced expressionAttributeStartParser |
| cmd/templ/fmtcmd/testdata.txtar | Updated testdata to include cases with spaces around = and { |
| .version | Bumped version from 0.3.896 to 0.3.903 |
Comments suppressed due to low confidence (2)
parser/v2/elementparser_test.go:1795
- [nitpick] The test name is slightly misleading because it mentions
space before name=rather thanspace before ={. Consider renaming to"element: space before = { is still parsed as an expression"to more accurately describe the scenario.
name: "element: space before name= { is still parsed as an expression",
parser/v2/elementparser.go:291
- Add a comment explaining that this parser matches optional whitespace around
= {at the start of an expression attribute, so readers immediately understand its purpose and structure.
var expressionAttributeStartParser = parse.StringFrom(parse.OptionalWhitespace, parse.String("="), parse.OptionalWhitespace, parse.String("{"), parse.OptionalWhitespace)
| attributeValueParsers = []attributeValueParser{ | ||
| // Double quoted. | ||
| {EqualsAndQuote: parse.String(`="`), Suffix: parse.String(`"`), UseSingleQuote: false}, | ||
| {EqualsAndQuote: parse.StringFrom(parse.OptionalWhitespace, parse.String(`="`)), Suffix: parse.String(`"`), UseSingleQuote: false}, | ||
| // Single quoted. | ||
| {EqualsAndQuote: parse.String(`='`), Suffix: parse.String(`'`), UseSingleQuote: true}, | ||
| {EqualsAndQuote: parse.StringFrom(parse.OptionalWhitespace, parse.String(`='`)), Suffix: parse.String(`'`), UseSingleQuote: true}, | ||
| // Unquoted. | ||
| // A valid unquoted attribute value in HTML is any string of text that is not an empty string, | ||
| // and that doesn’t contain spaces, tabs, line feeds, form feeds, carriage returns, ", ', `, =, <, or >. | ||
| {EqualsAndQuote: parse.String("="), Suffix: parse.Any(parse.RuneIn(" \t\n\r\"'`=<>/"), parse.EOF[string]()), UseSingleQuote: false}, | ||
| {EqualsAndQuote: parse.StringFrom(parse.OptionalWhitespace, parse.String("=")), Suffix: parse.Any(parse.RuneIn(" \t\n\r\"'`=<>/"), parse.EOF[string]()), UseSingleQuote: false}, |
There was a problem hiding this comment.
[nitpick] There’s repeated use of parse.OptionalWhitespace in each attributeValueParsers entry. You could extract a small helper like withOptWS(p parse.Parser) parse.Parser to wrap the parser and reduce duplication.
joerdav
left a comment
There was a problem hiding this comment.
This looks good to me. I agree this change makes sense. It brings us in line with the HTML Standard:
The attribute name, followed by zero or more ASCII whitespace, followed by a single U+003D EQUALS SIGN character, followed by zero or more ASCII whitespace, followed by a single U+0022 QUOTATION MARK character ("), followed by the attribute value, which, in addition to the requirements given above for attribute values, must not contain any literal U+0022 QUOTATION MARK characters ("), and finally followed by a second single U+0022 QUOTATION MARK character (").