first commit
Signed-off-by: Young Xu <xuthus5@gmail.com>
This commit is contained in:
commit
703122b00b
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
.idea
|
15
go.mod
Normal file
15
go.mod
Normal file
@ -0,0 +1,15 @@
|
||||
module gitter.top/common/goh
|
||||
|
||||
go 1.20
|
||||
|
||||
require (
|
||||
github.com/andybalholm/cascadia v1.3.2
|
||||
github.com/stretchr/testify v1.9.0
|
||||
golang.org/x/net v0.29.0
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
48
go.sum
Normal file
48
go.sum
Normal file
@ -0,0 +1,48 @@
|
||||
github.com/andybalholm/cascadia v1.3.2 h1:3Xi6Dw5lHF15JtdcmAHD3i1+T8plmv7BQ/nsViSLyss=
|
||||
github.com/andybalholm/cascadia v1.3.2/go.mod h1:7gtRlve5FxPPgIgX36uWBX58OdBsSS6lUvCFb+h7KvU=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
|
||||
golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo=
|
||||
golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
158
goh.go
Normal file
158
goh.go
Normal file
@ -0,0 +1,158 @@
|
||||
package goh
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io"
|
||||
|
||||
"github.com/andybalholm/cascadia"
|
||||
"golang.org/x/net/html"
|
||||
)
|
||||
|
||||
type Parser interface {
|
||||
// Find the first element that matches the selector.
|
||||
Find(filter string) SingleParser
|
||||
// FindAll the elements that match the selector.
|
||||
FindAll(name string) MultiParser
|
||||
}
|
||||
|
||||
type MultiParser interface {
|
||||
Parser
|
||||
// Attributes returns the attribute values of the elements that match
|
||||
Attributes(filter, attr string) ([]string, error)
|
||||
// Values returns the values of the elements that match
|
||||
Values(filter string) ([]string, error)
|
||||
}
|
||||
|
||||
type SingleParser interface {
|
||||
Parser
|
||||
// Attribute returns the attribute value of the first element that matches
|
||||
Attribute(attr string) (string, error)
|
||||
// Value returns the value of the first element that matches
|
||||
Value() (string, error)
|
||||
}
|
||||
|
||||
type parser struct {
|
||||
doc *html.Node
|
||||
docs []*html.Node
|
||||
err error
|
||||
}
|
||||
|
||||
func NewParser(reader io.Reader) (Parser, error) {
|
||||
doc, err := html.Parse(reader)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &parser{doc: doc}, nil
|
||||
}
|
||||
|
||||
func (p *parser) Find(filter string) SingleParser {
|
||||
if p.err != nil {
|
||||
return p
|
||||
}
|
||||
sel, err := cascadia.Parse(filter)
|
||||
if err != nil {
|
||||
p.err = err
|
||||
return p
|
||||
}
|
||||
if p.doc == nil && len(p.docs) == 0 {
|
||||
p.err = errors.New("no nodes found")
|
||||
return p
|
||||
}
|
||||
if p.doc == nil && len(p.docs) > 0 {
|
||||
p.doc = p.docs[0]
|
||||
}
|
||||
doc := cascadia.Query(p.doc, sel)
|
||||
return &parser{doc: doc}
|
||||
}
|
||||
|
||||
func (p *parser) FindAll(filter string) MultiParser {
|
||||
if p.err != nil {
|
||||
return p
|
||||
}
|
||||
sel, err := cascadia.Parse(filter)
|
||||
if err != nil {
|
||||
p.err = err
|
||||
return p
|
||||
}
|
||||
docs := cascadia.QueryAll(p.doc, sel)
|
||||
return &parser{docs: docs}
|
||||
}
|
||||
|
||||
func (p *parser) Attribute(attr string) (string, error) {
|
||||
if p.err != nil {
|
||||
return "", p.err
|
||||
}
|
||||
if p.doc == nil {
|
||||
return "", nil
|
||||
}
|
||||
for _, attribute := range p.doc.Attr {
|
||||
if attribute.Key == attr {
|
||||
return attribute.Val, nil
|
||||
}
|
||||
}
|
||||
return "", errors.New("attribute not found")
|
||||
}
|
||||
|
||||
func (p *parser) Attributes(filter, attr string) ([]string, error) {
|
||||
if p.err != nil {
|
||||
return nil, p.err
|
||||
}
|
||||
if p.docs == nil {
|
||||
return nil, errors.New("no nodes found")
|
||||
}
|
||||
var attributes []string
|
||||
sel, err := cascadia.Parse(filter)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, doc := range p.docs {
|
||||
nodes := cascadia.Query(doc, sel)
|
||||
if nodes == nil {
|
||||
continue
|
||||
}
|
||||
for _, attribute := range nodes.Attr {
|
||||
if attribute.Key == attr {
|
||||
attributes = append(attributes, attribute.Val)
|
||||
}
|
||||
}
|
||||
}
|
||||
return attributes, nil
|
||||
}
|
||||
|
||||
func (p *parser) Value() (string, error) {
|
||||
if p.err != nil {
|
||||
return "", p.err
|
||||
}
|
||||
if p.doc == nil {
|
||||
return "", nil
|
||||
}
|
||||
if p.doc.FirstChild == nil {
|
||||
return "", nil
|
||||
}
|
||||
return p.doc.FirstChild.Data, nil
|
||||
}
|
||||
|
||||
func (p *parser) Values(filter string) ([]string, error) {
|
||||
if p.err != nil {
|
||||
return nil, p.err
|
||||
}
|
||||
if len(p.docs) == 0 {
|
||||
return nil, errors.New("no nodes found")
|
||||
}
|
||||
var values []string
|
||||
sel, err := cascadia.Parse(filter)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, doc := range p.docs {
|
||||
nodes := cascadia.Query(doc, sel)
|
||||
if nodes == nil {
|
||||
continue
|
||||
}
|
||||
if nodes.FirstChild == nil {
|
||||
continue
|
||||
}
|
||||
values = append(values, nodes.FirstChild.Data)
|
||||
}
|
||||
return values, nil
|
||||
}
|
301
goh_test.go
Normal file
301
goh_test.go
Normal file
@ -0,0 +1,301 @@
|
||||
package goh
|
||||
|
||||
import (
|
||||
"io"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func testData() io.Reader {
|
||||
return strings.NewReader(`
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>The Linux Kernel Archives</title>
|
||||
<meta charset="utf-8" />
|
||||
<link rel="icon" type="image/png" href="https://www.kernel.org/theme/images/logos/favicon.png" />
|
||||
<link rel="stylesheet" href="https://www.kernel.org/theme/css/main.css" type="text/css" />
|
||||
<link href="https://www.kernel.org/feeds/all.atom.xml" type="application/atom+xml" rel="alternate" title="The Linux Kernel Archives Atom Feed" />
|
||||
|
||||
<link href="https://www.kernel.org/feeds/kdist.xml" type="application/atom+xml" rel="alternate" title="Latest Linux Kernel Releases" />
|
||||
|
||||
<!--[if IE]>
|
||||
<script src="https://html5shiv.googlecode.com/svn/trunk/html5.js"></script><![endif]-->
|
||||
|
||||
<!--[if lte IE 7]>
|
||||
<link rel="stylesheet" type="text/css" media="all" href="https://www.kernel.org/css/ie.css"/>
|
||||
<script src="https://www.kernel.org/js/IE8.js" type="text/javascript"></script><![endif]-->
|
||||
|
||||
<!--[if lt IE 7]>
|
||||
<link rel="stylesheet" type="text/css" media="all" href="https://www.kernel.org/css/ie6.css"/><![endif]-->
|
||||
|
||||
</head>
|
||||
|
||||
<body id="index" class="home">
|
||||
<header id="banner" class="body">
|
||||
<div id="tux-gear"></div>
|
||||
<h1><a href="https://www.kernel.org/">The Linux Kernel Archives </a></h1>
|
||||
<nav><ul>
|
||||
<li ><a href="https://www.kernel.org/category/about.html">About</a></li>
|
||||
<li ><a href="https://www.kernel.org/category/contact-us.html">Contact us</a></li>
|
||||
<li ><a href="https://www.kernel.org/category/faq.html">FAQ</a></li>
|
||||
<li ><a href="https://www.kernel.org/category/releases.html">Releases</a></li>
|
||||
<li ><a href="https://www.kernel.org/category/signatures.html">Signatures</a></li>
|
||||
<li ><a href="https://www.kernel.org/category/site-news.html">Site news</a></li>
|
||||
</ul></nav>
|
||||
</header><!-- /#banner -->
|
||||
|
||||
<aside id="featured" class="body">
|
||||
<article>
|
||||
<table id="protocols">
|
||||
<tr>
|
||||
<th>Protocol</th>
|
||||
<th>Location</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="https://www.ietf.org/rfc/rfc2616.txt">HTTP</a></td>
|
||||
<td><a href="https://www.kernel.org/pub/">https://www.kernel.org/pub/</a></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><a href="https://git-scm.com/">GIT</a></td>
|
||||
<td><a href="https://git.kernel.org/">https://git.kernel.org/</a></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><a href="https://rsync.samba.org/">RSYNC</a></td>
|
||||
<td>rsync://rsync.kernel.org/pub/</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<table id="latest">
|
||||
<tr>
|
||||
<td colspan="2" id="latest_label">
|
||||
<strong>Latest Release</strong>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td id="latest_link">
|
||||
<a href="https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.11.tar.xz">6.11</a>
|
||||
</td>
|
||||
<td id="latest_button">
|
||||
<a href="https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.11.tar.xz"><img src="https://www.kernel.org/theme/images/icons/downloadarrow_small.png" width="48" height="48" border="0" alt="Download"/></a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<!--//
|
||||
// Wait! Are you looking at the source because you are trying to parse the releases table?
|
||||
// Save yourself a lot of effort and use these instead:
|
||||
// - https://www.kernel.org/releases.json
|
||||
// - https://www.kernel.org/finger_banner
|
||||
//-->
|
||||
<table id="releases">
|
||||
<tr align="left">
|
||||
<td>mainline:</td>
|
||||
<td><strong>6.11</strong></td>
|
||||
<td>2024-09-15</td>
|
||||
<td>[<a href="https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.11.tar.xz" title="Download complete tarball">tarball</a>] </td>
|
||||
<td>[<a href="https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.11.tar.sign" title="Download PGP verification signature">pgp</a>] </td>
|
||||
<td>[<a href="https://cdn.kernel.org/pub/linux/kernel/v6.x/patch-6.11.xz" title="Download patch to previous mainline">patch</a>] </td>
|
||||
<td> </td>
|
||||
<td>[<a href="https://git.kernel.org/torvalds/ds/v6.11/v6.10" title="View diff in cgit">view diff</a>] </td>
|
||||
<td>[<a href="https://git.kernel.org/torvalds/h/v6.11" title="Browse the git tree using cgit">browse</a>] </td>
|
||||
<td> </td>
|
||||
</tr>
|
||||
<tr align="left">
|
||||
<td>stable:</td>
|
||||
<td><strong>6.10.11</strong></td>
|
||||
<td>2024-09-18</td>
|
||||
<td>[<a href="https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.10.11.tar.xz" title="Download complete tarball">tarball</a>] </td>
|
||||
<td>[<a href="https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.10.11.tar.sign" title="Download PGP verification signature">pgp</a>] </td>
|
||||
<td>[<a href="https://cdn.kernel.org/pub/linux/kernel/v6.x/patch-6.10.11.xz" title="Download patch to previous mainline">patch</a>] </td>
|
||||
<td>[<a href="https://cdn.kernel.org/pub/linux/kernel/v6.x/incr/patch-6.10.10-11.xz" title="Download incremental patch">inc. patch</a>] </td>
|
||||
<td>[<a href="https://git.kernel.org/stable/ds/v6.10.11/v6.10.10" title="View diff in cgit">view diff</a>] </td>
|
||||
<td>[<a href="https://git.kernel.org/stable/h/v6.10.11" title="Browse the git tree using cgit">browse</a>] </td>
|
||||
<td>[<a href="https://cdn.kernel.org/pub/linux/kernel/v6.x/ChangeLog-6.10.11" title="View detailed change logs">changelog</a>] </td>
|
||||
</tr>
|
||||
<tr align="left">
|
||||
<td>longterm:</td>
|
||||
<td><strong>6.6.52</strong></td>
|
||||
<td>2024-09-18</td>
|
||||
<td>[<a href="https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.6.52.tar.xz" title="Download complete tarball">tarball</a>] </td>
|
||||
<td>[<a href="https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.6.52.tar.sign" title="Download PGP verification signature">pgp</a>] </td>
|
||||
<td>[<a href="https://cdn.kernel.org/pub/linux/kernel/v6.x/patch-6.6.52.xz" title="Download patch to previous mainline">patch</a>] </td>
|
||||
<td>[<a href="https://cdn.kernel.org/pub/linux/kernel/v6.x/incr/patch-6.6.51-52.xz" title="Download incremental patch">inc. patch</a>] </td>
|
||||
<td>[<a href="https://git.kernel.org/stable/ds/v6.6.52/v6.6.51" title="View diff in cgit">view diff</a>] </td>
|
||||
<td>[<a href="https://git.kernel.org/stable/h/v6.6.52" title="Browse the git tree using cgit">browse</a>] </td>
|
||||
<td>[<a href="https://cdn.kernel.org/pub/linux/kernel/v6.x/ChangeLog-6.6.52" title="View detailed change logs">changelog</a>] </td>
|
||||
</tr>
|
||||
<tr align="left">
|
||||
<td>longterm:</td>
|
||||
<td><strong>6.1.111</strong></td>
|
||||
<td>2024-09-18</td>
|
||||
<td>[<a href="https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.1.111.tar.xz" title="Download complete tarball">tarball</a>] </td>
|
||||
<td>[<a href="https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.1.111.tar.sign" title="Download PGP verification signature">pgp</a>] </td>
|
||||
<td>[<a href="https://cdn.kernel.org/pub/linux/kernel/v6.x/patch-6.1.111.xz" title="Download patch to previous mainline">patch</a>] </td>
|
||||
<td>[<a href="https://cdn.kernel.org/pub/linux/kernel/v6.x/incr/patch-6.1.110-111.xz" title="Download incremental patch">inc. patch</a>] </td>
|
||||
<td>[<a href="https://git.kernel.org/stable/ds/v6.1.111/v6.1.110" title="View diff in cgit">view diff</a>] </td>
|
||||
<td>[<a href="https://git.kernel.org/stable/h/v6.1.111" title="Browse the git tree using cgit">browse</a>] </td>
|
||||
<td>[<a href="https://cdn.kernel.org/pub/linux/kernel/v6.x/ChangeLog-6.1.111" title="View detailed change logs">changelog</a>] </td>
|
||||
</tr>
|
||||
<tr align="left">
|
||||
<td>longterm:</td>
|
||||
<td><strong>5.15.167</strong></td>
|
||||
<td>2024-09-12</td>
|
||||
<td>[<a href="https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.15.167.tar.xz" title="Download complete tarball">tarball</a>] </td>
|
||||
<td>[<a href="https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.15.167.tar.sign" title="Download PGP verification signature">pgp</a>] </td>
|
||||
<td>[<a href="https://cdn.kernel.org/pub/linux/kernel/v5.x/patch-5.15.167.xz" title="Download patch to previous mainline">patch</a>] </td>
|
||||
<td>[<a href="https://cdn.kernel.org/pub/linux/kernel/v5.x/incr/patch-5.15.166-167.xz" title="Download incremental patch">inc. patch</a>] </td>
|
||||
<td>[<a href="https://git.kernel.org/stable/ds/v5.15.167/v5.15.166" title="View diff in cgit">view diff</a>] </td>
|
||||
<td>[<a href="https://git.kernel.org/stable/h/v5.15.167" title="Browse the git tree using cgit">browse</a>] </td>
|
||||
<td>[<a href="https://cdn.kernel.org/pub/linux/kernel/v5.x/ChangeLog-5.15.167" title="View detailed change logs">changelog</a>] </td>
|
||||
</tr>
|
||||
<tr align="left">
|
||||
<td>longterm:</td>
|
||||
<td><strong>5.10.226</strong></td>
|
||||
<td>2024-09-12</td>
|
||||
<td>[<a href="https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.10.226.tar.xz" title="Download complete tarball">tarball</a>] </td>
|
||||
<td>[<a href="https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.10.226.tar.sign" title="Download PGP verification signature">pgp</a>] </td>
|
||||
<td>[<a href="https://cdn.kernel.org/pub/linux/kernel/v5.x/patch-5.10.226.xz" title="Download patch to previous mainline">patch</a>] </td>
|
||||
<td>[<a href="https://cdn.kernel.org/pub/linux/kernel/v5.x/incr/patch-5.10.225-226.xz" title="Download incremental patch">inc. patch</a>] </td>
|
||||
<td>[<a href="https://git.kernel.org/stable/ds/v5.10.226/v5.10.225" title="View diff in cgit">view diff</a>] </td>
|
||||
<td>[<a href="https://git.kernel.org/stable/h/v5.10.226" title="Browse the git tree using cgit">browse</a>] </td>
|
||||
<td>[<a href="https://cdn.kernel.org/pub/linux/kernel/v5.x/ChangeLog-5.10.226" title="View detailed change logs">changelog</a>] </td>
|
||||
</tr>
|
||||
<tr align="left">
|
||||
<td>longterm:</td>
|
||||
<td><strong>5.4.284</strong></td>
|
||||
<td>2024-09-12</td>
|
||||
<td>[<a href="https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.4.284.tar.xz" title="Download complete tarball">tarball</a>] </td>
|
||||
<td>[<a href="https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.4.284.tar.sign" title="Download PGP verification signature">pgp</a>] </td>
|
||||
<td>[<a href="https://cdn.kernel.org/pub/linux/kernel/v5.x/patch-5.4.284.xz" title="Download patch to previous mainline">patch</a>] </td>
|
||||
<td>[<a href="https://cdn.kernel.org/pub/linux/kernel/v5.x/incr/patch-5.4.283-284.xz" title="Download incremental patch">inc. patch</a>] </td>
|
||||
<td>[<a href="https://git.kernel.org/stable/ds/v5.4.284/v5.4.283" title="View diff in cgit">view diff</a>] </td>
|
||||
<td>[<a href="https://git.kernel.org/stable/h/v5.4.284" title="Browse the git tree using cgit">browse</a>] </td>
|
||||
<td>[<a href="https://cdn.kernel.org/pub/linux/kernel/v5.x/ChangeLog-5.4.284" title="View detailed change logs">changelog</a>] </td>
|
||||
</tr>
|
||||
<tr align="left">
|
||||
<td>longterm:</td>
|
||||
<td><strong>4.19.322</strong></td>
|
||||
<td>2024-09-12</td>
|
||||
<td>[<a href="https://cdn.kernel.org/pub/linux/kernel/v4.x/linux-4.19.322.tar.xz" title="Download complete tarball">tarball</a>] </td>
|
||||
<td>[<a href="https://cdn.kernel.org/pub/linux/kernel/v4.x/linux-4.19.322.tar.sign" title="Download PGP verification signature">pgp</a>] </td>
|
||||
<td>[<a href="https://cdn.kernel.org/pub/linux/kernel/v4.x/patch-4.19.322.xz" title="Download patch to previous mainline">patch</a>] </td>
|
||||
<td>[<a href="https://cdn.kernel.org/pub/linux/kernel/v4.x/incr/patch-4.19.321-322.xz" title="Download incremental patch">inc. patch</a>] </td>
|
||||
<td>[<a href="https://git.kernel.org/stable/ds/v4.19.322/v4.19.321" title="View diff in cgit">view diff</a>] </td>
|
||||
<td>[<a href="https://git.kernel.org/stable/h/v4.19.322" title="Browse the git tree using cgit">browse</a>] </td>
|
||||
<td>[<a href="https://cdn.kernel.org/pub/linux/kernel/v4.x/ChangeLog-4.19.322" title="View detailed change logs">changelog</a>] </td>
|
||||
</tr>
|
||||
<tr align="left">
|
||||
<td>linux-next:</td>
|
||||
<td><strong>next-20240920</strong></td>
|
||||
<td>2024-09-20</td>
|
||||
<td> </td>
|
||||
<td> </td>
|
||||
<td> </td>
|
||||
<td> </td>
|
||||
<td> </td>
|
||||
<td>[<a href="https://git.kernel.org/next/linux-next/h/next-20240920" title="Browse the git tree using cgit">browse</a>] </td>
|
||||
<td> </td>
|
||||
</tr>
|
||||
</table>
|
||||
</article>
|
||||
</aside>
|
||||
<section id="extras" class="body">
|
||||
<div class="blogroll">
|
||||
<h2>Other resources</h2>
|
||||
<ul>
|
||||
<li><a href="https://git.kernel.org/">Git Trees</a></li>
|
||||
<li><a href="https://docs.kernel.org/">Documentation</a></li>
|
||||
<li><a href="https://lore.kernel.org/">Kernel Mailing Lists</a></li>
|
||||
<li><a href="https://patchwork.kernel.org/">Patchwork</a></li>
|
||||
<li><a href="https://www.wiki.kernel.org/">Wikis</a></li>
|
||||
<li><a href="https://bugzilla.kernel.org/">Bugzilla</a></li>
|
||||
<li><a href="https://mirrors.kernel.org/">Mirrors</a></li>
|
||||
<li><a href="https://www.linux.com/">Linux.com</a></li>
|
||||
<li><a href="https://www.linuxfoundation.org/">Linux Foundation</a></li>
|
||||
</ul>
|
||||
</div><!-- /.blogroll -->
|
||||
<div class="social">
|
||||
<h2>Social</h2>
|
||||
<ul>
|
||||
<li><a href="https://www.kernel.org/feeds/all.atom.xml" type="application/atom+xml" rel="alternate">Site Atom feed</a></li>
|
||||
<li><a href="https://www.kernel.org/feeds/kdist.xml" type="application/atom+xml" rel="alternate">Releases Atom Feed</a></li>
|
||||
|
||||
<li><a href="https://planet.kernel.org/">Kernel Planet</a></li>
|
||||
</ul>
|
||||
</div><!-- /.social -->
|
||||
</section><!-- /#extras -->
|
||||
|
||||
<footer id="contentinfo" class="body">
|
||||
<address id="about" class="vcard body">
|
||||
This site is operated by the Linux Kernel Organization, Inc., a <a href="https://www.kernel.org/nonprofit.html">501(c)3 nonprofit corporation</a>, with support from the following sponsors.
|
||||
</address><!-- /#about -->
|
||||
|
||||
<address id="donors">
|
||||
<a href="https://metal.equinix.com/"><img src="https://www.kernel.org/theme/images/logos/equinix-metal.png"
|
||||
alt="Equinix Metal" height="35" width="328" /></a>
|
||||
|
||||
<a href="https://www.fastly.com/"><img src="https://www.kernel.org/theme/images/logos/fastly-logo.png"
|
||||
alt="Fastly" width="91" height="35" /></a>
|
||||
|
||||
<a href="https://www.constellix.com/"><img src="https://www.kernel.org/theme/images/logos/constellix-green-logo.png"
|
||||
alt="Constellix" width="193" height="21" /></a>
|
||||
<br />
|
||||
<a href="https://www.redhat.com/"><img src="https://www.kernel.org/theme/images/logos/redhat-community.png"
|
||||
alt="Red Hat" height="36" width="150" /></a>
|
||||
|
||||
<a href="https://www.purestorage.com/"><img src="https://www.kernel.org/theme/images/logos/purestorage.png"
|
||||
alt="PureStorage" width="179" height="45" /></a>
|
||||
|
||||
<a href="https://www.google.com/"><img src="https://www.kernel.org/theme/images/logos/google.png"
|
||||
alt="Google" height="42" width="128" /></a>
|
||||
<br/> <br/>
|
||||
<a href="https://www.linuxfoundation.org/"><img src="https://www.kernel.org/theme/images/logos/thelinuxfoundation.png"
|
||||
alt="The Linux Foundation" width="137" height="45" /></a>
|
||||
</address><!-- /#about -->
|
||||
</footer><!-- /#contentinfo -->
|
||||
|
||||
</body>
|
||||
</html>`)
|
||||
}
|
||||
|
||||
func TestNewParser(t *testing.T) {
|
||||
parser, err := NewParser(testData())
|
||||
assert.NoError(t, err)
|
||||
value, err := parser.Find("footer#contentinfo.body address#about.vcard.body a").Value()
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "501(c)3 nonprofit corporation", value)
|
||||
}
|
||||
|
||||
func Test_parser_Find(t *testing.T) {
|
||||
parser, err := NewParser(testData())
|
||||
assert.NoError(t, err)
|
||||
value, err := parser.Find("section#extras div.blogroll h2").Value()
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "Other resources", value)
|
||||
value, err = parser.Find("section#extras div.social").Attribute("class")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "social", value)
|
||||
}
|
||||
|
||||
func Test_parser_FindAll(t *testing.T) {
|
||||
parser, err := NewParser(testData())
|
||||
assert.NoError(t, err)
|
||||
values, err := parser.FindAll("section#extras div.blogroll ul li").Values("li a")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, []string{"Git Trees", "Documentation", "Kernel Mailing Lists", "Patchwork", "Wikis", "Bugzilla", "Mirrors", "Linux.com", "Linux Foundation"}, values)
|
||||
attributes, err := parser.FindAll("footer#contentinfo.body address#donors a").Attributes("a img", "alt")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, []string{"Equinix Metal", "Fastly", "Constellix", "Red Hat", "PureStorage", "Google", "The Linux Foundation"}, attributes)
|
||||
}
|
||||
|
||||
func Test_parser_Find_FindAll_Find(t *testing.T) {
|
||||
parser, err := NewParser(testData())
|
||||
assert.NoError(t, err)
|
||||
attribute, err := parser.Find("footer#contentinfo.body").FindAll("address#donors a").Find("a img").Attribute("alt")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "Equinix Metal", attribute)
|
||||
}
|
Loading…
Reference in New Issue
Block a user