github.com/shohhei1126/hugo@v0.42.2-0.20180623210752-3d5928889ad7/helpers/emoji.go (about)

     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"
    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  // Emojify "emojifies" the input source.
    34  // Note that the input byte slice will be modified if needed.
    35  // See http://www.emoji-cheat-sheet.com/
    36  func Emojify(source []byte) []byte {
    37  	emojiInit.Do(initEmoji)
    38  
    39  	start := 0
    40  	k := bytes.Index(source[start:], emojiDelim)
    41  
    42  	for k != -1 {
    43  
    44  		j := start + k
    45  
    46  		upper := j + emojiMaxSize
    47  
    48  		if upper > len(source) {
    49  			upper = len(source)
    50  		}
    51  
    52  		endEmoji := bytes.Index(source[j+1:upper], emojiDelim)
    53  		nextWordDelim := bytes.Index(source[j:upper], emojiWordDelim)
    54  
    55  		if endEmoji < 0 {
    56  			start++
    57  		} else if endEmoji == 0 || (nextWordDelim != -1 && nextWordDelim < endEmoji) {
    58  			start += endEmoji + 1
    59  		} else {
    60  			endKey := endEmoji + j + 2
    61  			emojiKey := source[j:endKey]
    62  
    63  			if emoji, ok := emojis[string(emojiKey)]; ok {
    64  				source = append(source[:j], append(emoji, source[endKey:]...)...)
    65  			}
    66  
    67  			start += endEmoji
    68  		}
    69  
    70  		if start >= len(source) {
    71  			break
    72  		}
    73  
    74  		k = bytes.Index(source[start:], emojiDelim)
    75  	}
    76  
    77  	return source
    78  }
    79  
    80  func initEmoji() {
    81  	emojiMap := emoji.CodeMap()
    82  
    83  	for k, v := range emojiMap {
    84  		emojis[k] = []byte(v)
    85  
    86  		if len(k) > emojiMaxSize {
    87  			emojiMaxSize = len(k)
    88  		}
    89  	}
    90  
    91  }