gitea-tea/vendor/github.com/enescakir/emoji/parser.go
Norwin 58aaa17e7e Show issue reactions (#421)
```
$ tea issue 230

   #230 issue/pull details: show reactions (open)

  @6543 created 2020-10-22 16:39

  since reactions are utf8 now and most terminals too, we can display them nicely :)

  https://gitea.com/api/v1/repos/gitea/tea/issues/230/reactions

  --------

  1x 🎉  |  1x 👀  |  1x :gitea:  |  1x 👍  |  1x 👎  |  1x 😆  |  1x 😕  |  1x ❤️
```

caveats:
- reactions are not returned as UTF8 (as was claimed in #230), so they need to be parsed. the library I use doesn't (and can't → :gitea:) support all reactions available in gitea
- currently only for issues, as reactions for comments mean an additional API request for each comment..

fixes #230

Co-authored-by: Norwin <git@nroo.de>
Reviewed-on: https://gitea.com/gitea/tea/pulls/421
Reviewed-by: Lunny Xiao <xiaolunwen@gmail.com>
Reviewed-by: techknowlogick <techknowlogick@gitea.io>
Co-authored-by: Norwin <noerw@noreply.gitea.io>
Co-committed-by: Norwin <noerw@noreply.gitea.io>
2021-10-01 16:13:32 +08:00

128 lines
2.5 KiB
Go

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 ""
}