gitech

Форк
0
/
generate-emoji.go 
223 строки · 4.7 Кб
1
// Copyright 2020 The Gitea Authors. All rights reserved.
2
// Copyright 2015 Kenneth Shaw
3
// SPDX-License-Identifier: MIT
4

5
//go:build ignore
6

7
package main
8

9
import (
10
	"flag"
11
	"fmt"
12
	"go/format"
13
	"io"
14
	"log"
15
	"net/http"
16
	"os"
17
	"regexp"
18
	"sort"
19
	"strconv"
20
	"strings"
21
	"unicode/utf8"
22

23
	"code.gitea.io/gitea/modules/json"
24
)
25

26
const (
27
	gemojiURL         = "https://raw.githubusercontent.com/github/gemoji/master/db/emoji.json"
28
	maxUnicodeVersion = 15
29
)
30

31
var flagOut = flag.String("o", "modules/emoji/emoji_data.go", "out")
32

33
// Gemoji is a set of emoji data.
34
type Gemoji []Emoji
35

36
// Emoji represents a single emoji and associated data.
37
type Emoji struct {
38
	Emoji          string   `json:"emoji"`
39
	Description    string   `json:"description,omitempty"`
40
	Aliases        []string `json:"aliases"`
41
	UnicodeVersion string   `json:"unicode_version,omitempty"`
42
	SkinTones      bool     `json:"skin_tones,omitempty"`
43
}
44

45
// Don't include some fields in JSON
46
func (e Emoji) MarshalJSON() ([]byte, error) {
47
	type emoji Emoji
48
	x := emoji(e)
49
	x.UnicodeVersion = ""
50
	x.Description = ""
51
	x.SkinTones = false
52
	return json.Marshal(x)
53
}
54

55
func main() {
56
	var err error
57

58
	flag.Parse()
59

60
	// generate data
61
	buf, err := generate()
62
	if err != nil {
63
		log.Fatalf("generate err: %v", err)
64
	}
65

66
	// write
67
	err = os.WriteFile(*flagOut, buf, 0o644)
68
	if err != nil {
69
		log.Fatalf("WriteFile err: %v", err)
70
	}
71
}
72

73
var replacer = strings.NewReplacer(
74
	"main.Gemoji", "Gemoji",
75
	"main.Emoji", "\n",
76
	"}}", "},\n}",
77
	", Description:", ", ",
78
	", Aliases:", ", ",
79
	", UnicodeVersion:", ", ",
80
	", SkinTones:", ", ",
81
)
82

83
var emojiRE = regexp.MustCompile(`\{Emoji:"([^"]*)"`)
84

85
func generate() ([]byte, error) {
86
	var err error
87

88
	// load gemoji data
89
	res, err := http.Get(gemojiURL)
90
	if err != nil {
91
		return nil, err
92
	}
93
	defer res.Body.Close()
94

95
	// read all
96
	body, err := io.ReadAll(res.Body)
97
	if err != nil {
98
		return nil, err
99
	}
100

101
	// unmarshal
102
	var data Gemoji
103
	err = json.Unmarshal(body, &data)
104
	if err != nil {
105
		return nil, err
106
	}
107

108
	skinTones := make(map[string]string)
109

110
	skinTones["\U0001f3fb"] = "Light Skin Tone"
111
	skinTones["\U0001f3fc"] = "Medium-Light Skin Tone"
112
	skinTones["\U0001f3fd"] = "Medium Skin Tone"
113
	skinTones["\U0001f3fe"] = "Medium-Dark Skin Tone"
114
	skinTones["\U0001f3ff"] = "Dark Skin Tone"
115

116
	var tmp Gemoji
117

118
	// filter out emoji that require greater than max unicode version
119
	for i := range data {
120
		val, _ := strconv.ParseFloat(data[i].UnicodeVersion, 64)
121
		if int(val) <= maxUnicodeVersion {
122
			tmp = append(tmp, data[i])
123
		}
124
	}
125
	data = tmp
126

127
	sort.Slice(data, func(i, j int) bool {
128
		return data[i].Aliases[0] < data[j].Aliases[0]
129
	})
130

131
	aliasMap := make(map[string]int, len(data))
132

133
	for i, e := range data {
134
		if e.Emoji == "" || len(e.Aliases) == 0 {
135
			continue
136
		}
137
		for _, a := range e.Aliases {
138
			if a == "" {
139
				continue
140
			}
141
			aliasMap[a] = i
142
		}
143
	}
144

145
	// gitea customizations
146
	i, ok := aliasMap["tada"]
147
	if ok {
148
		data[i].Aliases = append(data[i].Aliases, "hooray")
149
	}
150
	i, ok = aliasMap["laughing"]
151
	if ok {
152
		data[i].Aliases = append(data[i].Aliases, "laugh")
153
	}
154

155
	// write a JSON file to use with tribute (write before adding skin tones since we can't support them there yet)
156
	file, _ := json.Marshal(data)
157
	_ = os.WriteFile("assets/emoji.json", file, 0o644)
158

159
	// Add skin tones to emoji that support it
160
	var (
161
		s              []string
162
		newEmoji       string
163
		newDescription string
164
		newData        Emoji
165
	)
166

167
	for i := range data {
168
		if data[i].SkinTones {
169
			for k, v := range skinTones {
170
				s = strings.Split(data[i].Emoji, "")
171

172
				if utf8.RuneCountInString(data[i].Emoji) == 1 {
173
					s = append(s, k)
174
				} else {
175
					// insert into slice after first element because all emoji that support skin tones
176
					// have that modifier placed at this spot
177
					s = append(s, "")
178
					copy(s[2:], s[1:])
179
					s[1] = k
180
				}
181

182
				newEmoji = strings.Join(s, "")
183
				newDescription = data[i].Description + ": " + v
184
				newAlias := data[i].Aliases[0] + "_" + strings.ReplaceAll(v, " ", "_")
185

186
				newData = Emoji{newEmoji, newDescription, []string{newAlias}, "12.0", false}
187
				data = append(data, newData)
188
			}
189
		}
190
	}
191

192
	sort.Slice(data, func(i, j int) bool {
193
		return data[i].Aliases[0] < data[j].Aliases[0]
194
	})
195

196
	// add header
197
	str := replacer.Replace(fmt.Sprintf(hdr, gemojiURL, data))
198

199
	// change the format of the unicode string
200
	str = emojiRE.ReplaceAllStringFunc(str, func(s string) string {
201
		var err error
202
		s, err = strconv.Unquote(s[len("{Emoji:"):])
203
		if err != nil {
204
			panic(err)
205
		}
206
		return "{" + strconv.QuoteToASCII(s)
207
	})
208

209
	// format
210
	return format.Source([]byte(str))
211
}
212

213
const hdr = `
214
// Copyright 2020 The Gitea Authors. All rights reserved.
215
// SPDX-License-Identifier: MIT
216

217

218
package emoji
219

220
// Code generated by build/generate-emoji.go. DO NOT EDIT.
221
// Sourced from %s
222
var GemojiData = %#v
223
`
224

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.