-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathmention_filter.go
75 lines (60 loc) · 1.62 KB
/
mention_filter.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
package pipeline
import (
"regexp"
"strings"
"github.com/PuerkitoBio/goquery"
"golang.org/x/net/html"
)
var (
// A-Za-z0-9\p{Han}
mentionNameFormat = `\w\p{Han}_-`
)
// MentionFilter mention with @ or # or other prefix
type MentionFilter struct {
// Mention prefix char, default: @
Prefix string
// Format func for format matched names to HTML or other
Format func(name string) string
// NamesCallback return matched names
NamesCallback func(names []string)
mentionRegexp *regexp.Regexp
}
func (f *MentionFilter) initDefault() {
if f.Prefix == "" {
f.Prefix = "@"
}
if f.mentionRegexp == nil {
f.mentionRegexp = regexp.MustCompile(`(^|[^` + mentionNameFormat + `])(` + f.Prefix + `)([` + mentionNameFormat + `]+)`)
}
}
func (f MentionFilter) Call(doc *goquery.Document) (err error) {
f.initDefault()
names := []string{}
rootNode := doc.Find("body")
TraverseTextNodes(rootNode.Nodes[0], func(node *html.Node) {
if !strings.Contains(node.Data, f.Prefix) {
return
}
_names := f.ExtractMentionNames(node.Data)
// Replace text to links html
for _, name := range _names {
nameHTML := f.Format(name)
node.Type = html.RawNode
node.Data = strings.ReplaceAll(node.Data, f.Prefix+name, nameHTML)
}
names = append(names, _names...)
})
if f.NamesCallback != nil {
f.NamesCallback(names)
}
return
}
// ExtractMentionNames 从一段纯文本中提取提及的用户名
func (f MentionFilter) ExtractMentionNames(text string) (names []string) {
f.initDefault()
matches := f.mentionRegexp.FindAllStringSubmatch(text, -1)
for _, match := range matches {
names = append(names, match[3])
}
return
}