emoji.go (2133B)
1 // Copyright 2016 The Hugo Authors. All rights reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // http://www.apache.org/licenses/LICENSE-2.0 7 // 8 // Unless required by applicable law or agreed to in writing, software 9 // distributed under the License is distributed on an "AS IS" BASIS, 10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 package helpers 15 16 import ( 17 "bytes" 18 "sync" 19 20 "github.com/kyokomi/emoji/v2" 21 ) 22 23 var ( 24 emojiInit sync.Once 25 26 emojis = make(map[string][]byte) 27 28 emojiDelim = []byte(":") 29 emojiWordDelim = []byte(" ") 30 emojiMaxSize int 31 ) 32 33 // Emoji returns the emojy given a key, e.g. ":smile:", nil if not found. 34 func Emoji(key string) []byte { 35 emojiInit.Do(initEmoji) 36 return emojis[key] 37 } 38 39 // Emojify "emojifies" the input source. 40 // Note that the input byte slice will be modified if needed. 41 // See http://www.emoji-cheat-sheet.com/ 42 func Emojify(source []byte) []byte { 43 emojiInit.Do(initEmoji) 44 45 start := 0 46 k := bytes.Index(source[start:], emojiDelim) 47 48 for k != -1 { 49 50 j := start + k 51 52 upper := j + emojiMaxSize 53 54 if upper > len(source) { 55 upper = len(source) 56 } 57 58 endEmoji := bytes.Index(source[j+1:upper], emojiDelim) 59 nextWordDelim := bytes.Index(source[j:upper], emojiWordDelim) 60 61 if endEmoji < 0 { 62 start++ 63 } else if endEmoji == 0 || (nextWordDelim != -1 && nextWordDelim < endEmoji) { 64 start += endEmoji + 1 65 } else { 66 endKey := endEmoji + j + 2 67 emojiKey := source[j:endKey] 68 69 if emoji, ok := emojis[string(emojiKey)]; ok { 70 source = append(source[:j], append(emoji, source[endKey:]...)...) 71 } 72 73 start += endEmoji 74 } 75 76 if start >= len(source) { 77 break 78 } 79 80 k = bytes.Index(source[start:], emojiDelim) 81 } 82 83 return source 84 } 85 86 func initEmoji() { 87 emojiMap := emoji.CodeMap() 88 89 for k, v := range emojiMap { 90 emojis[k] = []byte(v) 91 92 if len(k) > emojiMaxSize { 93 emojiMaxSize = len(k) 94 } 95 } 96 }