perf: pre-check raw class attribute in HasClass

HasClass normalized every matching element's class attribute with
classTrimReplacer before checking for the target token, even when the
raw attribute value could not possibly contain that class at all.

Add a cheap strings.Contains(attr.Val, rawClass) pre-check and only run
the replacer on plausible matches. This preserves behavior for class
attributes containing tabs/newlines while skipping most of the work on
misses.

BenchmarkHasClass on arm64 over 10 runs:

name         old time/op   new time/op   delta
HasClass-8    9.809µs       2.660µs      -72.89% (p=0.000)
This commit is contained in:
jvoisin
2026-05-27 15:26:22 +02:00
parent e2468fa06d
commit 3b71495757
+4
View File
@@ -137,12 +137,16 @@ func (s *Selection) AddClass(class ...string) *Selection {
// HasClass determines whether any of the matched elements are assigned the
// given class.
func (s *Selection) HasClass(class string) bool {
rawClass := class
class = " " + class + " "
for _, n := range s.Nodes {
if n.Type != html.ElementNode {
continue
}
if attr := getAttributePtr("class", n); attr != nil {
if !strings.Contains(attr.Val, rawClass) {
continue
}
val := classTrimReplacer.Replace(attr.Val)
if strings.Contains(" "+val+" ", class) {
return true