-
Notifications
You must be signed in to change notification settings - Fork 20
/
parser.go
127 lines (101 loc) · 2.5 KB
/
parser.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
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
package emoji
import (
"fmt"
"regexp"
"strings"
"unicode"
)
var (
flagRegex = regexp.MustCompile(`^:flag-([a-zA-Z]{2}):$`)
)
// Parse replaces emoji aliases (:pizza:) with unicode representation.
func Parse(input string) string {
var matched strings.Builder
var output strings.Builder
for _, r := range input {
// when it's not `:`, it might be inner or outer of the emoji alias
if r != ':' {
// if matched is empty, it's the outer of the emoji alias
if matched.Len() == 0 {
output.WriteRune(r)
continue
}
matched.WriteRune(r)
// if it's space, the alias's not valid.
// reset matched for breaking the emoji alias
if unicode.IsSpace(r) {
output.WriteString(matched.String())
matched.Reset()
}
continue
}
// r is `:` now
// if matched is empty, it's the beginning of the emoji alias
if matched.Len() == 0 {
matched.WriteRune(r)
continue
}
// it's the end of the emoji alias
match := matched.String()
alias := match + ":"
// check for emoji alias
if code, ok := Find(alias); ok {
output.WriteString(code)
matched.Reset()
continue
}
// not found any emoji
output.WriteString(match)
// it might be the beginning of the another emoji alias
matched.Reset()
matched.WriteRune(r)
}
// if matched not empty, add it to output
if matched.Len() != 0 {
output.WriteString(matched.String())
matched.Reset()
}
return output.String()
}
// Map returns the emojis map.
// Key is the alias of the emoji.
// Value is the code of the emoji.
func Map() map[string]string {
return emojiMap
}
// AppendAlias adds new emoji pair to the emojis map.
func AppendAlias(alias, code string) error {
if c, ok := emojiMap[alias]; ok {
return fmt.Errorf("emoji already exist: %q => %+q", alias, c)
}
for _, r := range alias {
if unicode.IsSpace(r) {
return fmt.Errorf("emoji alias is not valid: %q", alias)
}
}
emojiMap[alias] = code
return nil
}
// Exist checks existence of the emoji by alias.
func Exist(alias string) bool {
_, ok := Find(alias)
return ok
}
// Find returns the emoji code by alias.
func Find(alias string) (string, bool) {
if code, ok := emojiMap[alias]; ok {
return code, true
}
if flag := checkFlag(alias); len(flag) > 0 {
return flag, true
}
return "", false
}
// checkFlag finds flag emoji for `flag-[CODE]` pattern
func checkFlag(alias string) string {
if matches := flagRegex.FindStringSubmatch(alias); len(matches) == 2 {
flag, _ := CountryFlag(matches[1])
return flag.String()
}
return ""
}