Bumps the go-modules-updates group with 11 updates in the /backend directory: | Package | From | To | | --- | --- | --- | | [github.com/PuerkitoBio/goquery](https://github.com/PuerkitoBio/goquery) | `1.10.2` | `1.11.0` | | [github.com/alecthomas/chroma/v2](https://github.com/alecthomas/chroma) | `2.15.0` | `2.20.0` | | [github.com/go-chi/chi/v5](https://github.com/go-chi/chi) | `5.2.1` | `5.2.3` | | [github.com/go-chi/cors](https://github.com/go-chi/cors) | `1.2.1` | `1.2.2` | | [github.com/go-pkgz/jrpc](https://github.com/go-pkgz/jrpc) | `0.3.1` | `0.4.0` | | [github.com/go-pkgz/lgr](https://github.com/go-pkgz/lgr) | `0.12.0` | `0.12.1` | | [github.com/go-pkgz/rest](https://github.com/go-pkgz/rest) | `1.20.3` | `1.20.4` | | [github.com/golang-jwt/jwt/v5](https://github.com/golang-jwt/jwt) | `5.2.2` | `5.3.0` | | [github.com/stretchr/testify](https://github.com/stretchr/testify) | `1.10.0` | `1.11.1` | | [go.etcd.io/bbolt](https://github.com/etcd-io/bbolt) | `1.4.0` | `1.4.3` | | [golang.org/x/image](https://github.com/golang/image) | `0.26.0` | `0.33.0` | Updates `github.com/PuerkitoBio/goquery` from 1.10.2 to 1.11.0 - [Release notes](https://github.com/PuerkitoBio/goquery/releases) - [Commits](https://github.com/PuerkitoBio/goquery/compare/v1.10.2...v1.11.0) Updates `github.com/alecthomas/chroma/v2` from 2.15.0 to 2.20.0 - [Release notes](https://github.com/alecthomas/chroma/releases) - [Commits](https://github.com/alecthomas/chroma/compare/v2.15.0...v2.20.0) Updates `github.com/go-chi/chi/v5` from 5.2.1 to 5.2.3 - [Release notes](https://github.com/go-chi/chi/releases) - [Changelog](https://github.com/go-chi/chi/blob/master/CHANGELOG.md) - [Commits](https://github.com/go-chi/chi/compare/v5.2.1...v5.2.3) Updates `github.com/go-chi/cors` from 1.2.1 to 1.2.2 - [Release notes](https://github.com/go-chi/cors/releases) - [Commits](https://github.com/go-chi/cors/compare/v1.2.1...v1.2.2) Updates `github.com/go-pkgz/jrpc` from 0.3.1 to 0.4.0 - [Release notes](https://github.com/go-pkgz/jrpc/releases) - [Commits](https://github.com/go-pkgz/jrpc/compare/v0.3.1...v0.4.0) Updates `github.com/go-pkgz/lgr` from 0.12.0 to 0.12.1 - [Release notes](https://github.com/go-pkgz/lgr/releases) - [Commits](https://github.com/go-pkgz/lgr/compare/v0.12.0...v0.12.1) Updates `github.com/go-pkgz/rest` from 1.20.3 to 1.20.4 - [Release notes](https://github.com/go-pkgz/rest/releases) - [Commits](https://github.com/go-pkgz/rest/compare/v1.20.3...v1.20.4) Updates `github.com/golang-jwt/jwt/v5` from 5.2.2 to 5.3.0 - [Release notes](https://github.com/golang-jwt/jwt/releases) - [Commits](https://github.com/golang-jwt/jwt/compare/v5.2.2...v5.3.0) Updates `github.com/stretchr/testify` from 1.10.0 to 1.11.1 - [Release notes](https://github.com/stretchr/testify/releases) - [Commits](https://github.com/stretchr/testify/compare/v1.10.0...v1.11.1) Updates `go.etcd.io/bbolt` from 1.4.0 to 1.4.3 - [Release notes](https://github.com/etcd-io/bbolt/releases) - [Commits](https://github.com/etcd-io/bbolt/compare/v1.4.0...v1.4.3) Updates `golang.org/x/image` from 0.26.0 to 0.33.0 - [Commits](https://github.com/golang/image/compare/v0.26.0...v0.33.0) --- updated-dependencies: - dependency-name: github.com/PuerkitoBio/goquery dependency-version: 1.11.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go-modules-updates - dependency-name: github.com/alecthomas/chroma/v2 dependency-version: 2.20.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go-modules-updates - dependency-name: github.com/go-chi/chi/v5 dependency-version: 5.2.3 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: go-modules-updates - dependency-name: github.com/go-chi/cors dependency-version: 1.2.2 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: go-modules-updates - dependency-name: github.com/go-pkgz/jrpc dependency-version: 0.4.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go-modules-updates - dependency-name: github.com/go-pkgz/lgr dependency-version: 0.12.1 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: go-modules-updates - dependency-name: github.com/go-pkgz/rest dependency-version: 1.20.4 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: go-modules-updates - dependency-name: github.com/golang-jwt/jwt/v5 dependency-version: 5.3.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go-modules-updates - dependency-name: github.com/stretchr/testify dependency-version: 1.11.1 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go-modules-updates - dependency-name: go.etcd.io/bbolt dependency-version: 1.4.3 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: go-modules-updates - dependency-name: golang.org/x/image dependency-version: 0.33.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go-modules-updates ... Signed-off-by: dependabot[bot] <support@github.com>
276 lines
6.5 KiB
Go
276 lines
6.5 KiB
Go
package goquery
|
|
|
|
import (
|
|
"regexp"
|
|
"strings"
|
|
|
|
"golang.org/x/net/html"
|
|
)
|
|
|
|
var rxClassTrim = regexp.MustCompile("[\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
|
|
// construct such as Each or Map method.
|
|
func (s *Selection) Attr(attrName string) (val string, exists bool) {
|
|
if len(s.Nodes) == 0 {
|
|
return
|
|
}
|
|
return getAttributeValue(attrName, s.Nodes[0])
|
|
}
|
|
|
|
// AttrOr works like Attr but returns default value if attribute is not present.
|
|
func (s *Selection) AttrOr(attrName, defaultValue string) string {
|
|
if len(s.Nodes) == 0 {
|
|
return defaultValue
|
|
}
|
|
|
|
val, exists := getAttributeValue(attrName, s.Nodes[0])
|
|
if !exists {
|
|
return defaultValue
|
|
}
|
|
|
|
return val
|
|
}
|
|
|
|
// RemoveAttr removes the named attribute from each element in the set of matched elements.
|
|
func (s *Selection) RemoveAttr(attrName string) *Selection {
|
|
for _, n := range s.Nodes {
|
|
removeAttr(n, attrName)
|
|
}
|
|
|
|
return s
|
|
}
|
|
|
|
// SetAttr sets the given attribute on each element in the set of matched elements.
|
|
func (s *Selection) SetAttr(attrName, val string) *Selection {
|
|
for _, n := range s.Nodes {
|
|
attr := getAttributePtr(attrName, n)
|
|
if attr == nil {
|
|
n.Attr = append(n.Attr, html.Attribute{Key: attrName, Val: val})
|
|
} else {
|
|
attr.Val = val
|
|
}
|
|
}
|
|
|
|
return s
|
|
}
|
|
|
|
// Text gets the combined text contents of each element in the set of matched
|
|
// elements, including their descendants.
|
|
func (s *Selection) Text() string {
|
|
var builder strings.Builder
|
|
|
|
// Slightly optimized vs calling Each: no single selection object created
|
|
var f func(*html.Node)
|
|
f = func(n *html.Node) {
|
|
if n.Type == html.TextNode {
|
|
// Keep newlines and spaces, like jQuery
|
|
builder.WriteString(n.Data)
|
|
}
|
|
if n.FirstChild != nil {
|
|
for c := n.FirstChild; c != nil; c = c.NextSibling {
|
|
f(c)
|
|
}
|
|
}
|
|
}
|
|
for _, n := range s.Nodes {
|
|
f(n)
|
|
}
|
|
|
|
return builder.String()
|
|
}
|
|
|
|
// Size is an alias for Length.
|
|
func (s *Selection) Size() int {
|
|
return s.Length()
|
|
}
|
|
|
|
// Length returns the number of elements in the Selection object.
|
|
func (s *Selection) Length() int {
|
|
return len(s.Nodes)
|
|
}
|
|
|
|
// Html gets the HTML contents of the first element in the set of matched
|
|
// elements. It includes text and comment nodes.
|
|
func (s *Selection) Html() (ret string, e error) {
|
|
// Since there is no .innerHtml, the HTML content must be re-created from
|
|
// the nodes using html.Render.
|
|
var builder strings.Builder
|
|
|
|
if len(s.Nodes) > 0 {
|
|
for c := s.Nodes[0].FirstChild; c != nil; c = c.NextSibling {
|
|
e = html.Render(&builder, c)
|
|
if e != nil {
|
|
return
|
|
}
|
|
}
|
|
ret = builder.String()
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
// AddClass adds the given class(es) to each element in the set of matched elements.
|
|
// Multiple class names can be specified, separated by a space or via multiple arguments.
|
|
func (s *Selection) AddClass(class ...string) *Selection {
|
|
classStr := strings.TrimSpace(strings.Join(class, " "))
|
|
|
|
if classStr == "" {
|
|
return s
|
|
}
|
|
|
|
tcls := getClassesSlice(classStr)
|
|
for _, n := range s.Nodes {
|
|
curClasses, attr := getClassesAndAttr(n, true)
|
|
for _, newClass := range tcls {
|
|
if !strings.Contains(curClasses, " "+newClass+" ") {
|
|
curClasses += newClass + " "
|
|
}
|
|
}
|
|
|
|
setClasses(n, attr, curClasses)
|
|
}
|
|
|
|
return s
|
|
}
|
|
|
|
// HasClass determines whether any of the matched elements are assigned the
|
|
// given class.
|
|
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
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
// RemoveClass removes the given class(es) from each element in the set of matched elements.
|
|
// Multiple class names can be specified, separated by a space or via multiple arguments.
|
|
// If no class name is provided, all classes are removed.
|
|
func (s *Selection) RemoveClass(class ...string) *Selection {
|
|
var rclasses []string
|
|
|
|
classStr := strings.TrimSpace(strings.Join(class, " "))
|
|
remove := classStr == ""
|
|
|
|
if !remove {
|
|
rclasses = getClassesSlice(classStr)
|
|
}
|
|
|
|
for _, n := range s.Nodes {
|
|
if remove {
|
|
removeAttr(n, "class")
|
|
} else {
|
|
classes, attr := getClassesAndAttr(n, true)
|
|
for _, rcl := range rclasses {
|
|
classes = strings.ReplaceAll(classes, " "+rcl+" ", " ")
|
|
}
|
|
|
|
setClasses(n, attr, classes)
|
|
}
|
|
}
|
|
|
|
return s
|
|
}
|
|
|
|
// ToggleClass adds or removes the given class(es) for each element in the set of matched elements.
|
|
// Multiple class names can be specified, separated by a space or via multiple arguments.
|
|
func (s *Selection) ToggleClass(class ...string) *Selection {
|
|
classStr := strings.TrimSpace(strings.Join(class, " "))
|
|
|
|
if classStr == "" {
|
|
return s
|
|
}
|
|
|
|
tcls := getClassesSlice(classStr)
|
|
|
|
for _, n := range s.Nodes {
|
|
classes, attr := getClassesAndAttr(n, true)
|
|
for _, tcl := range tcls {
|
|
spaceAroundTcl := " " + tcl + " "
|
|
if strings.Contains(classes, spaceAroundTcl) {
|
|
classes = strings.ReplaceAll(classes, spaceAroundTcl, " ")
|
|
} else {
|
|
classes += tcl + " "
|
|
}
|
|
}
|
|
|
|
setClasses(n, attr, classes)
|
|
}
|
|
|
|
return s
|
|
}
|
|
|
|
func getAttributePtr(attrName string, n *html.Node) *html.Attribute {
|
|
if n == nil {
|
|
return nil
|
|
}
|
|
|
|
for i, a := range n.Attr {
|
|
if a.Key == attrName {
|
|
return &n.Attr[i]
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// Private function to get the specified attribute's value from a node.
|
|
func getAttributeValue(attrName string, n *html.Node) (val string, exists bool) {
|
|
if a := getAttributePtr(attrName, n); a != nil {
|
|
val = a.Val
|
|
exists = true
|
|
}
|
|
return
|
|
}
|
|
|
|
// Get and normalize the "class" attribute from the node.
|
|
func getClassesAndAttr(n *html.Node, create bool) (classes string, attr *html.Attribute) {
|
|
// Applies only to element nodes
|
|
if n.Type == html.ElementNode {
|
|
attr = getAttributePtr("class", n)
|
|
if attr == nil && create {
|
|
n.Attr = append(n.Attr, html.Attribute{
|
|
Key: "class",
|
|
Val: "",
|
|
})
|
|
attr = &n.Attr[len(n.Attr)-1]
|
|
}
|
|
}
|
|
|
|
if attr == nil {
|
|
classes = " "
|
|
} else {
|
|
classes = rxClassTrim.ReplaceAllString(" "+attr.Val+" ", " ")
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
func getClassesSlice(classes string) []string {
|
|
return strings.Split(rxClassTrim.ReplaceAllString(" "+classes+" ", " "), " ")
|
|
}
|
|
|
|
func removeAttr(n *html.Node, attrName string) {
|
|
for i, a := range n.Attr {
|
|
if a.Key == attrName {
|
|
n.Attr[i], n.Attr[len(n.Attr)-1], n.Attr =
|
|
n.Attr[len(n.Attr)-1], html.Attribute{}, n.Attr[:len(n.Attr)-1]
|
|
return
|
|
}
|
|
}
|
|
}
|
|
|
|
func setClasses(n *html.Node, attr *html.Attribute, classes string) {
|
|
classes = strings.TrimSpace(classes)
|
|
if classes == "" {
|
|
removeAttr(n, "class")
|
|
return
|
|
}
|
|
|
|
attr.Val = classes
|
|
}
|