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 := Find(alias); ok {
52 output.WriteString(code)
53 matched.Reset()
54 continue
55 }
56
57 // not found any emoji
58 output.WriteString(match)
59 // it might be the beginning of the another emoji alias
60 matched.Reset()
61 matched.WriteRune(r)
62
63 }
64
65 // if matched not empty, add it to output
66 if matched.Len() != 0 {
67 output.WriteString(matched.String())
68 matched.Reset()
69 }
70
71 return output.String()
72}
73
74// Map returns the emojis map.
75// Key is the alias of the emoji.
76// Value is the code of the emoji.
77func Map() map[string]string {
78 return emojiMap
79}
80
81// AppendAlias adds new emoji pair to the emojis map.
82func AppendAlias(alias, code string) error {
83 if c, ok := emojiMap[alias]; ok {
84 return fmt.Errorf("emoji already exist: %q => %+q", alias, c)
85 }
86
87 for _, r := range alias {
88 if unicode.IsSpace(r) {
89 return fmt.Errorf("emoji alias is not valid: %q", alias)
90 }
91 }
92
93 emojiMap[alias] = code
94
95 return nil
96}
97
98// Exist checks existence of the emoji by alias.
99func Exist(alias string) bool {
100 _, ok := Find(alias)
101
102 return ok
103}
104
105// Find returns the emoji code by alias.
106func Find(alias string) (string, bool) {
107 if code, ok := emojiMap[alias]; ok {
108 return code, true
109 }
110
111 if flag := checkFlag(alias); len(flag) > 0 {
112 return flag, true
113 }
114
115 return "", false
116}
117
118// checkFlag finds flag emoji for `flag-[CODE]` pattern
119func checkFlag(alias string) string {
120 if matches := flagRegex.FindStringSubmatch(alias); len(matches) == 2 {
121 flag, _ := CountryFlag(matches[1])
122
123 return flag.String()
124 }
125
126 return ""
127}