mirror of
				https://codeberg.org/forgejo/forgejo.git
				synced 2025-10-25 11:33:11 +00:00 
			
		
		
		
	Update emoji set to Unicode 15 which was added upstream here:
cb5c514d47
<img width="854" alt="Screenshot 2023-06-29 at 11 02 56 AM"
src="https://github.com/go-gitea/gitea/assets/1669571/7bfb663d-0804-4d23-a62d-f585a6783ca6">
---------
Co-authored-by: silverwind <me@silverwind.io>
		
	
			
		
			
				
	
	
		
			223 lines
		
	
	
	
		
			4.7 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			223 lines
		
	
	
	
		
			4.7 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| // Copyright 2020 The Gitea Authors. All rights reserved.
 | |
| // Copyright 2015 Kenneth Shaw
 | |
| // SPDX-License-Identifier: MIT
 | |
| 
 | |
| //go:build ignore
 | |
| 
 | |
| package main
 | |
| 
 | |
| import (
 | |
| 	"flag"
 | |
| 	"fmt"
 | |
| 	"go/format"
 | |
| 	"io"
 | |
| 	"log"
 | |
| 	"net/http"
 | |
| 	"os"
 | |
| 	"regexp"
 | |
| 	"sort"
 | |
| 	"strconv"
 | |
| 	"strings"
 | |
| 	"unicode/utf8"
 | |
| 
 | |
| 	"code.gitea.io/gitea/modules/json"
 | |
| )
 | |
| 
 | |
| const (
 | |
| 	gemojiURL         = "https://raw.githubusercontent.com/github/gemoji/master/db/emoji.json"
 | |
| 	maxUnicodeVersion = 15
 | |
| )
 | |
| 
 | |
| var flagOut = flag.String("o", "modules/emoji/emoji_data.go", "out")
 | |
| 
 | |
| // Gemoji is a set of emoji data.
 | |
| type Gemoji []Emoji
 | |
| 
 | |
| // Emoji represents a single emoji and associated data.
 | |
| type Emoji struct {
 | |
| 	Emoji          string   `json:"emoji"`
 | |
| 	Description    string   `json:"description,omitempty"`
 | |
| 	Aliases        []string `json:"aliases"`
 | |
| 	UnicodeVersion string   `json:"unicode_version,omitempty"`
 | |
| 	SkinTones      bool     `json:"skin_tones,omitempty"`
 | |
| }
 | |
| 
 | |
| // Don't include some fields in JSON
 | |
| func (e Emoji) MarshalJSON() ([]byte, error) {
 | |
| 	type emoji Emoji
 | |
| 	x := emoji(e)
 | |
| 	x.UnicodeVersion = ""
 | |
| 	x.Description = ""
 | |
| 	x.SkinTones = false
 | |
| 	return json.Marshal(x)
 | |
| }
 | |
| 
 | |
| func main() {
 | |
| 	var err error
 | |
| 
 | |
| 	flag.Parse()
 | |
| 
 | |
| 	// generate data
 | |
| 	buf, err := generate()
 | |
| 	if err != nil {
 | |
| 		log.Fatalf("generate err: %v", err)
 | |
| 	}
 | |
| 
 | |
| 	// write
 | |
| 	err = os.WriteFile(*flagOut, buf, 0o644)
 | |
| 	if err != nil {
 | |
| 		log.Fatalf("WriteFile err: %v", err)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| var replacer = strings.NewReplacer(
 | |
| 	"main.Gemoji", "Gemoji",
 | |
| 	"main.Emoji", "\n",
 | |
| 	"}}", "},\n}",
 | |
| 	", Description:", ", ",
 | |
| 	", Aliases:", ", ",
 | |
| 	", UnicodeVersion:", ", ",
 | |
| 	", SkinTones:", ", ",
 | |
| )
 | |
| 
 | |
| var emojiRE = regexp.MustCompile(`\{Emoji:"([^"]*)"`)
 | |
| 
 | |
| func generate() ([]byte, error) {
 | |
| 	var err error
 | |
| 
 | |
| 	// load gemoji data
 | |
| 	res, err := http.Get(gemojiURL)
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	defer res.Body.Close()
 | |
| 
 | |
| 	// read all
 | |
| 	body, err := io.ReadAll(res.Body)
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 
 | |
| 	// unmarshal
 | |
| 	var data Gemoji
 | |
| 	err = json.Unmarshal(body, &data)
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 
 | |
| 	skinTones := make(map[string]string)
 | |
| 
 | |
| 	skinTones["\U0001f3fb"] = "Light Skin Tone"
 | |
| 	skinTones["\U0001f3fc"] = "Medium-Light Skin Tone"
 | |
| 	skinTones["\U0001f3fd"] = "Medium Skin Tone"
 | |
| 	skinTones["\U0001f3fe"] = "Medium-Dark Skin Tone"
 | |
| 	skinTones["\U0001f3ff"] = "Dark Skin Tone"
 | |
| 
 | |
| 	var tmp Gemoji
 | |
| 
 | |
| 	// filter out emoji that require greater than max unicode version
 | |
| 	for i := range data {
 | |
| 		val, _ := strconv.ParseFloat(data[i].UnicodeVersion, 64)
 | |
| 		if int(val) <= maxUnicodeVersion {
 | |
| 			tmp = append(tmp, data[i])
 | |
| 		}
 | |
| 	}
 | |
| 	data = tmp
 | |
| 
 | |
| 	sort.Slice(data, func(i, j int) bool {
 | |
| 		return data[i].Aliases[0] < data[j].Aliases[0]
 | |
| 	})
 | |
| 
 | |
| 	aliasMap := make(map[string]int, len(data))
 | |
| 
 | |
| 	for i, e := range data {
 | |
| 		if e.Emoji == "" || len(e.Aliases) == 0 {
 | |
| 			continue
 | |
| 		}
 | |
| 		for _, a := range e.Aliases {
 | |
| 			if a == "" {
 | |
| 				continue
 | |
| 			}
 | |
| 			aliasMap[a] = i
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	// gitea customizations
 | |
| 	i, ok := aliasMap["tada"]
 | |
| 	if ok {
 | |
| 		data[i].Aliases = append(data[i].Aliases, "hooray")
 | |
| 	}
 | |
| 	i, ok = aliasMap["laughing"]
 | |
| 	if ok {
 | |
| 		data[i].Aliases = append(data[i].Aliases, "laugh")
 | |
| 	}
 | |
| 
 | |
| 	// write a JSON file to use with tribute (write before adding skin tones since we can't support them there yet)
 | |
| 	file, _ := json.Marshal(data)
 | |
| 	_ = os.WriteFile("assets/emoji.json", file, 0o644)
 | |
| 
 | |
| 	// Add skin tones to emoji that support it
 | |
| 	var (
 | |
| 		s              []string
 | |
| 		newEmoji       string
 | |
| 		newDescription string
 | |
| 		newData        Emoji
 | |
| 	)
 | |
| 
 | |
| 	for i := range data {
 | |
| 		if data[i].SkinTones {
 | |
| 			for k, v := range skinTones {
 | |
| 				s = strings.Split(data[i].Emoji, "")
 | |
| 
 | |
| 				if utf8.RuneCountInString(data[i].Emoji) == 1 {
 | |
| 					s = append(s, k)
 | |
| 				} else {
 | |
| 					// insert into slice after first element because all emoji that support skin tones
 | |
| 					// have that modifier placed at this spot
 | |
| 					s = append(s, "")
 | |
| 					copy(s[2:], s[1:])
 | |
| 					s[1] = k
 | |
| 				}
 | |
| 
 | |
| 				newEmoji = strings.Join(s, "")
 | |
| 				newDescription = data[i].Description + ": " + v
 | |
| 				newAlias := data[i].Aliases[0] + "_" + strings.ReplaceAll(v, " ", "_")
 | |
| 
 | |
| 				newData = Emoji{newEmoji, newDescription, []string{newAlias}, "12.0", false}
 | |
| 				data = append(data, newData)
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	sort.Slice(data, func(i, j int) bool {
 | |
| 		return data[i].Aliases[0] < data[j].Aliases[0]
 | |
| 	})
 | |
| 
 | |
| 	// add header
 | |
| 	str := replacer.Replace(fmt.Sprintf(hdr, gemojiURL, data))
 | |
| 
 | |
| 	// change the format of the unicode string
 | |
| 	str = emojiRE.ReplaceAllStringFunc(str, func(s string) string {
 | |
| 		var err error
 | |
| 		s, err = strconv.Unquote(s[len("{Emoji:"):])
 | |
| 		if err != nil {
 | |
| 			panic(err)
 | |
| 		}
 | |
| 		return "{" + strconv.QuoteToASCII(s)
 | |
| 	})
 | |
| 
 | |
| 	// format
 | |
| 	return format.Source([]byte(str))
 | |
| }
 | |
| 
 | |
| const hdr = `
 | |
| // Copyright 2020 The Gitea Authors. All rights reserved.
 | |
| // SPDX-License-Identifier: MIT
 | |
| 
 | |
| 
 | |
| package emoji
 | |
| 
 | |
| // Code generated by build/generate-emoji.go. DO NOT EDIT.
 | |
| // Sourced from %s
 | |
| var GemojiData = %#v
 | |
| `
 |