-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtag.go
96 lines (87 loc) · 2 KB
/
tag.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
package node
import (
"regexp"
"strings"
)
var (
_ TagFilter = True
_ TagFilter = tag[string]{}
)
// These variables are used to represent common tags.
var (
A = Tag("A")
B = Tag("b")
Body = Tag("body")
Div = Tag("div")
Em = Tag("em")
Form = Tag("form")
H1 = Tag("h1")
H2 = Tag("h2")
Head = Tag("head")
I = Tag("i")
Img = Tag("img")
Input = Tag("input")
Label = Tag("label")
Li = Tag("li")
Option = Tag("option")
P = Tag("p")
Select = Tag("select")
Span = Tag("span")
Svg = Tag("svg")
Table = Tag("table")
Td = Tag("td")
Th = Tag("th")
Title = Tag("title")
Tr = Tag("tr")
Ul = Tag("ul")
)
// TagFilter represents an interface that can be used to filter node based on node element's tag.
type TagFilter interface {
Ignore() bool
IsMatch(node Node) bool
}
// tag represents a specific HTML tag that can be used as a tag filter.
type tag[T Value] struct {
tag T
}
// Tag creates a new TagFilter based on a given tag value.
func Tag[T Value](t T) TagFilter {
return tag[T]{t}
}
// Tags creates a new TagFilter based on a list of tag values.
func Tags(tag ...string) TagFilter {
return Tag(tag)
}
// Ignore returns a boolean value indicating whether the given tag filter should be ignored or not.
func (tag tag[T]) Ignore() bool {
switch v := (any(tag.tag)).(type) {
case string:
return v == ""
case []string:
return len(v) == 0
case everything:
return false
default:
return v == nil
}
}
// IsMatch returns a boolean value indicating whether a given node matches the specified tag filter.
func (tag tag[T]) IsMatch(node Node) bool {
switch v := (any(tag.tag)).(type) {
case string:
return strings.ToLower(v) == node.Raw().Data
case []string:
for _, v := range v {
if strings.ToLower(v) == node.Raw().Data {
return true
}
}
case *regexp.Regexp:
return v.MatchString(node.Raw().Data)
case everything:
return true
case func(string, Node) bool:
return v(node.Raw().Data, node)
}
return false
}