goveal/rendering/emoji/emoji_parser.go

110 lines
2.4 KiB
Go
Raw Normal View History

2022-03-15 14:44:53 +00:00
package emoji
import (
"bytes"
"fmt"
"strconv"
"strings"
"unicode/utf8"
"github.com/gomarkdown/markdown/ast"
)
func NewEmojiParser() *EmojiParser {
return &EmojiParser{
seen: make(map[string]bool),
}
}
// Node is a node containing an emoji
type Node struct {
ast.Leaf
}
type EmojiParser struct {
seen map[string]bool
}
func (p *EmojiParser) EmojiParser(data []byte) (parsedNode ast.Node, result []byte, newLength int) {
if p.seen[string(data)] {
// Already processed
return nil, nil, 0
}
if bytes.Contains(data, []byte("class=\"emoji\"")) {
// Already processed
return nil, nil, 0
}
dataLen := len(data)
if dataLen <= 1 {
// Not long enough to be an emoji
return nil, nil, 0
}
if bytes.IndexByte(data, ':') == -1 {
// No emoji delimiters
return nil, nil, 0
}
// Translate emojis to HTML
resData := make([]byte, 0)
startIndex := bytes.IndexByte(data, ':')
resData = append(resData, data[0:startIndex]...)
for {
if startIndex >= len(data) {
// Done
break
}
endIndex := bytes.IndexByte(data[startIndex+1:], ':') + startIndex + 1
if endIndex > startIndex {
name := string(data[startIndex+1 : endIndex])
if isValidEmoji([]byte(name)) {
startIndex = endIndex + 1
url := fmt.Sprintf(`<img class="emoji" src=%q alt=":%s:"></img>`, GenerateEmojiURL(name), name)
resData = append(resData, []byte(url)...)
} else {
resData = append(resData, data[startIndex:endIndex]...)
startIndex = endIndex
}
if startIndex == dataLen {
break
}
} else {
break
}
}
if startIndex < dataLen {
resData = append(resData, data[startIndex:]...)
}
if !bytes.Contains(resData, []byte("class=\"emoji\"")) {
// Processed with no changes
p.seen[string(resData)] = true
}
return &ast.Softbreak{}, resData, dataLen
}
func GenerateEmojiURL(emoji string) string {
code, exists := emojiMap[emoji]
if !exists {
return ""
}
res := ""
chars := utf8.RuneCountInString(code)
curChar := 1
for _, c := range code {
tmp := strings.Trim(strings.ToLower(strconv.QuoteRuneToASCII(c)), "'")
if tmp != `\ufe0f` || (chars > 2 && curChar == chars) {
// Valid character to add
if curChar > 1 {
res += "-"
}
if len(tmp) == 1 {
res += fmt.Sprintf("%x", []byte(tmp))
} else {
res += strings.TrimLeft(tmp[2:], "0")
}
}
curChar++
}
return fmt.Sprintf("https://twemoji.maxcdn.com/2/svg/%s.svg", res)
}