Merge branch 'master' into spaceclass

This commit is contained in:
Martin Angers
2026-05-26 09:11:05 -04:00
committed by GitHub
3 changed files with 30 additions and 20 deletions
+10 -8
View File
@@ -1,13 +1,12 @@
package goquery
import (
"regexp"
"strings"
"golang.org/x/net/html"
)
var rxClassTrim = regexp.MustCompile("[\t\r\n]")
var classTrimReplacer = strings.NewReplacer("\t", " ", "\r", " ", "\n", " ")
// Attr gets the specified attribute's value for the first element in the
// Selection. To get the value for each element individually, use a looping
@@ -140,9 +139,14 @@ func (s *Selection) AddClass(class ...string) *Selection {
func (s *Selection) HasClass(class string) bool {
class = " " + class + " "
for _, n := range s.Nodes {
classes, _ := getClassesAndAttr(n, false)
if strings.Contains(classes, class) {
return true
if n.Type != html.ElementNode {
continue
}
if attr := getAttributePtr("class", n); attr != nil {
val := classTrimReplacer.Replace(attr.Val)
if strings.Contains(" "+val+" ", class) {
return true
}
}
}
return false
@@ -243,10 +247,8 @@ func getClassesAndAttr(n *html.Node, create bool) (classes string, attr *html.At
if attr == nil {
classes = " "
} else if strings.ContainsAny(attr.Val, "\t\r\n") {
classes = rxClassTrim.ReplaceAllString(" "+attr.Val+" ", " ")
} else {
classes = " " + attr.Val + " "
classes = classTrimReplacer.Replace(" " + attr.Val + " ")
}
return
+16 -3
View File
@@ -24,19 +24,32 @@ func (s *Selection) IsMatcher(m Matcher) bool {
// IsFunction checks the current matched set of elements against a predicate and
// returns true if at least one of these elements matches.
func (s *Selection) IsFunction(f func(int, *Selection) bool) bool {
return s.FilterFunction(f).Length() > 0
for i, n := range s.Nodes {
if f(i, newSingleSelection(n, s.document)) {
return true
}
}
return false
}
// IsSelection checks the current matched set of elements against a Selection object
// and returns true if at least one of these elements matches.
func (s *Selection) IsSelection(sel *Selection) bool {
return s.FilterSelection(sel).Length() > 0
if sel == nil {
return false
}
return s.IsNodes(sel.Nodes...)
}
// IsNodes checks the current matched set of elements against the specified nodes
// and returns true if at least one of these elements matches.
func (s *Selection) IsNodes(nodes ...*html.Node) bool {
return s.FilterNodes(nodes...).Length() > 0
for _, n := range s.Nodes {
if isInSlice(nodes, n) {
return true
}
}
return false
}
// Contains returns true if the specified Node is within,
+4 -9
View File
@@ -562,13 +562,12 @@ func findWithMatcher(nodes []*html.Node, m Matcher) []*html.Node {
func getParentsNodes(nodes []*html.Node, stopm Matcher, stopNodes []*html.Node) []*html.Node {
return mapNodes(nodes, func(i int, n *html.Node) (result []*html.Node) {
for p := n.Parent; p != nil; p = p.Parent {
sel := newSingleSelection(p, nil)
if stopm != nil {
if sel.IsMatcher(stopm) {
if stopm.Match(p) {
break
}
} else if len(stopNodes) > 0 {
if sel.IsNodes(stopNodes...) {
if isInSlice(stopNodes, p) {
break
}
}
@@ -589,13 +588,9 @@ func getSiblingNodes(nodes []*html.Node, st siblingType, untilm Matcher, untilNo
if st == siblingNextUntil || st == siblingPrevUntil {
f = func(n *html.Node) bool {
if untilm != nil {
// Matcher-based condition
sel := newSingleSelection(n, nil)
return sel.IsMatcher(untilm)
return untilm.Match(n)
} else if len(untilNodes) > 0 {
// Nodes-based condition
sel := newSingleSelection(n, nil)
return sel.IsNodes(untilNodes...)
return isInSlice(untilNodes, n)
}
return false
}