parser.go (view raw)
1package emoji
2
3import (
4 "fmt"
5 "regexp"
6 "strings"
7 "unicode"
8)
9
10var (
11 flagRegex = regexp.MustCompile(`^:flag-([a-zA-Z]{2}):$`)
12)
13
14// Parse replaces emoji aliases (:pizza:) with unicode representation.
15func Parse(input string) string {
16 var matched strings.Builder
17 var output strings.Builder
18
19 for _, r := range input {
20 // when it's not `:`, it might be inner or outer of the emoji alias
21 if r != ':' {
22 // if matched is empty, it's the outer of the emoji alias
23 if matched.Len() == 0 {
24 output.WriteRune(r)
25 continue
26 }
27
28 matched.WriteRune(r)
29
30 // if it's space, the alias's not valid.
31 // reset matched for breaking the emoji alias
32 if unicode.IsSpace(r) {
33 output.WriteString(matched.String())
34 matched.Reset()
35 }
36 continue
37 }
38
39 // r is `:` now
40 // if matched is empty, it's the beginning of the emoji alias
41 if matched.Len() == 0 {
42 matched.WriteRune(r)
43 continue
44 }
45
46 // it's the end of the emoji alias
47 match := matched.String()
48 alias := match + ":"
49
50 // check for emoji alias
51 if code, ok := emojiMap[alias]; ok {
52 output.WriteString(code)
53 matched.Reset()
54 continue
55 }
56
57 // check for `flag-[CODE]` emoji
58 if flag := checkFlag(alias); len(flag) > 0 {
59 output.WriteString(flag)
60 matched.Reset()
61 continue
62 }
63
64 // not found any emoji
65 output.WriteString(match)
66 // it might be the beginning of the another emoji alias
67 matched.Reset()
68 matched.WriteRune(r)
69
70 }
71
72 // if matched not empty, add it to output
73 if matched.Len() != 0 {
74 output.WriteString(matched.String())
75 matched.Reset()
76 }
77
78 return output.String()
79}
80
81// checkFlag finds flag emoji for `flag-[CODE]` pattern
82func checkFlag(alias string) string {
83 if matches := flagRegex.FindStringSubmatch(alias); len(matches) == 2 {
84 flag, _ := CountryFlag(matches[1])
85
86 return flag.String()
87 }
88
89 return ""
90}
91
92// Map returns the emojis map.
93// Key is the alias of the emoji.
94// Value is the code of the emoji.
95func Map() map[string]string {
96 return emojiMap
97}
98
99// AppendAlias adds new emoji pair to the emojis map.
100func AppendAlias(alias, code string) error {
101 if c, ok := emojiMap[alias]; ok {
102 return fmt.Errorf("emoji already exist: %q => %+q", alias, c)
103 }
104
105 for _, r := range alias {
106 if unicode.IsSpace(r) {
107 return fmt.Errorf("emoji alias is not valid: %q", alias)
108 }
109 }
110
111 emojiMap[alias] = code
112
113 return nil
114}
115
116// Exist checks existence of the emoji by alias.
117func Exist(alias string) bool {
118 _, ok := emojiMap[alias]
119
120 return ok
121}
122
123// Find returns the emoji code by alias.
124func Find(alias string) (string, bool) {
125 code, ok := emojiMap[alias]
126 if !ok {
127 return "", false
128 }
129
130 return code, true
131}