parser.go 2.5 KB

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