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 14package helpers 15 16import ( 17 "bytes" 18 "sync" 19 20 "github.com/kyokomi/emoji/v2" 21) 22 23var ( 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. 34func 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/ 42func 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 86func 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} 97