You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

generate-emoji.go 3.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. // Copyright 2020 The Gitea Authors. All rights reserved.
  2. // Copyright 2015 Kenneth Shaw
  3. // Use of this source code is governed by a MIT-style
  4. // license that can be found in the LICENSE file.
  5. // +build ignore
  6. package main
  7. import (
  8. "encoding/json"
  9. "flag"
  10. "fmt"
  11. "go/format"
  12. "io/ioutil"
  13. "log"
  14. "net/http"
  15. "regexp"
  16. "sort"
  17. "strconv"
  18. "strings"
  19. )
  20. const (
  21. gemojiURL = "https://raw.githubusercontent.com/github/gemoji/master/db/emoji.json"
  22. maxUnicodeVersion = 12
  23. )
  24. var (
  25. flagOut = flag.String("o", "modules/emoji/emoji_data.go", "out")
  26. )
  27. // Gemoji is a set of emoji data.
  28. type Gemoji []Emoji
  29. // Emoji represents a single emoji and associated data.
  30. type Emoji struct {
  31. Emoji string `json:"emoji"`
  32. Description string `json:"description,omitempty"`
  33. Aliases []string `json:"aliases"`
  34. UnicodeVersion string `json:"unicode_version,omitempty"`
  35. }
  36. // Don't include some fields in JSON
  37. func (e Emoji) MarshalJSON() ([]byte, error) {
  38. type emoji Emoji
  39. x := emoji(e)
  40. x.UnicodeVersion = ""
  41. x.Description = ""
  42. return json.Marshal(x)
  43. }
  44. func main() {
  45. var err error
  46. flag.Parse()
  47. // generate data
  48. buf, err := generate()
  49. if err != nil {
  50. log.Fatal(err)
  51. }
  52. // write
  53. err = ioutil.WriteFile(*flagOut, buf, 0644)
  54. if err != nil {
  55. log.Fatal(err)
  56. }
  57. }
  58. var replacer = strings.NewReplacer(
  59. "main.Gemoji", "Gemoji",
  60. "main.Emoji", "\n",
  61. "}}", "},\n}",
  62. ", Description:", ", ",
  63. ", Aliases:", ", ",
  64. ", UnicodeVersion:", ", ",
  65. )
  66. var emojiRE = regexp.MustCompile(`\{Emoji:"([^"]*)"`)
  67. func generate() ([]byte, error) {
  68. var err error
  69. // load gemoji data
  70. res, err := http.Get(gemojiURL)
  71. if err != nil {
  72. return nil, err
  73. }
  74. defer res.Body.Close()
  75. // read all
  76. body, err := ioutil.ReadAll(res.Body)
  77. if err != nil {
  78. return nil, err
  79. }
  80. // unmarshal
  81. var data Gemoji
  82. err = json.Unmarshal(body, &data)
  83. if err != nil {
  84. return nil, err
  85. }
  86. var re = regexp.MustCompile(`keycap|registered|copyright`)
  87. tmp := data[:0]
  88. // filter out emoji that require greater than max unicode version
  89. for i := range data {
  90. val, _ := strconv.ParseFloat(data[i].UnicodeVersion, 64)
  91. if int(val) <= maxUnicodeVersion {
  92. // remove these keycaps for now they really complicate matching since
  93. // they include normal letters in them
  94. if re.MatchString(data[i].Description) {
  95. continue
  96. }
  97. tmp = append(tmp, data[i])
  98. }
  99. }
  100. data = tmp
  101. sort.Slice(data, func(i, j int) bool {
  102. return data[i].Aliases[0] < data[j].Aliases[0]
  103. })
  104. aliasPairs := make([]string, 0)
  105. aliasMap := make(map[string]int, len(data))
  106. for i, e := range data {
  107. if e.Emoji == "" || len(e.Aliases) == 0 {
  108. continue
  109. }
  110. for _, a := range e.Aliases {
  111. if a == "" {
  112. continue
  113. }
  114. aliasMap[a] = i
  115. aliasPairs = append(aliasPairs, ":"+a+":", e.Emoji)
  116. }
  117. }
  118. // gitea customizations
  119. i, ok := aliasMap["tada"]
  120. if ok {
  121. data[i].Aliases = append(data[i].Aliases, "hooray")
  122. }
  123. i, ok = aliasMap["laughing"]
  124. if ok {
  125. data[i].Aliases = append(data[i].Aliases, "laugh")
  126. }
  127. // add header
  128. str := replacer.Replace(fmt.Sprintf(hdr, gemojiURL, data))
  129. // change the format of the unicode string
  130. str = emojiRE.ReplaceAllStringFunc(str, func(s string) string {
  131. var err error
  132. s, err = strconv.Unquote(s[len("{Emoji:"):])
  133. if err != nil {
  134. panic(err)
  135. }
  136. return "{" + strconv.QuoteToASCII(s)
  137. })
  138. // write a JSON file to use with tribute
  139. file, _ := json.Marshal(data)
  140. _ = ioutil.WriteFile("assets/emoji.json", file, 0644)
  141. // format
  142. return format.Source([]byte(str))
  143. }
  144. const hdr = `
  145. // Copyright 2020 The Gitea Authors. All rights reserved.
  146. // Use of this source code is governed by a MIT-style
  147. // license that can be found in the LICENSE file.
  148. package emoji
  149. // Code generated by gen.go. DO NOT EDIT.
  150. // Sourced from %s
  151. //
  152. var GemojiData = %#v
  153. `