diff --git a/parser/v2/elementparser.go b/parser/v2/elementparser.go index 128d50c8e..f7616e608 100644 --- a/parser/v2/elementparser.go +++ b/parser/v2/elementparser.go @@ -96,8 +96,9 @@ var ( // Constant attribute. var ( - attributeConstantValueParser = parse.StringUntil(parse.Rune('"')) - constantAttributeParser = parse.Func(func(pi *parse.Input) (attr ConstantAttribute, ok bool, err error) { + attributeConstantValueParser = parse.StringUntil(parse.Rune('"')) + attributeConstantValueSingleQuoteParser = parse.StringUntil(parse.Rune('\'')) + constantAttributeParser = parse.Func(func(pi *parse.Input) (attr ConstantAttribute, ok bool, err error) { start := pi.Index() // Optional whitespace leader. @@ -112,13 +113,21 @@ var ( } // =" - if _, ok, err = parse.String(`="`).Parse(pi); err != nil || !ok { + result, ok, err := parse.Or(parse.String(`="`), parse.String(`='`)).Parse(pi) + if err != nil || !ok { pi.Seek(start) return } + valueParser := attributeConstantValueParser + closeParser := parse.String(`"`) + if result.B.OK { + valueParser = attributeConstantValueSingleQuoteParser + closeParser = parse.String(`'`) + } + // Attribute value. - if attr.Value, ok, err = attributeConstantValueParser.Parse(pi); err != nil || !ok { + if attr.Value, ok, err = valueParser.Parse(pi); err != nil || !ok { pi.Seek(start) return } @@ -126,7 +135,7 @@ var ( attr.Value = html.UnescapeString(attr.Value) // " - closing quote. - if _, ok, err = Must(parse.String(`"`), fmt.Sprintf("missing closing quote on attribute %q", attr.Name)).Parse(pi); err != nil || !ok { + if _, ok, err = Must(closeParser, fmt.Sprintf("missing closing quote on attribute %q", attr.Name)).Parse(pi); err != nil || !ok { pi.Seek(start) return } diff --git a/parser/v2/elementparser_test.go b/parser/v2/elementparser_test.go index 473b18a76..0a2d14631 100644 --- a/parser/v2/elementparser_test.go +++ b/parser/v2/elementparser_test.go @@ -248,6 +248,15 @@ if test { Value: "test", }, }, + { + name: "single quote constant attribute", + input: ` href='"test"'`, + parser: StripType(constantAttributeParser), + expected: ConstantAttribute{ + Name: "href", + Value: `"test"`, + }, + }, { name: "attribute name with hyphens", input: ` data-turbo-permanent="value"`,