-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathkrasivo.js
145 lines (132 loc) · 4.29 KB
/
krasivo.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
var symbols = require('./build/symbols.json')
var emoji = require('./build/emoji.json')
var SYMBOL_HEIGHT = 7
var BACKGROUND_SYMBOL = '.'
var FOREGROUND_SYMBOL = '#'
var BACKGROUND_REGEXP = new RegExp('\\' + BACKGROUND_SYMBOL, 'g')
var FOREGROUND_REGEXP = new RegExp('\\' + FOREGROUND_SYMBOL, 'g')
var EMOJI_WITH_SKIN_COLOUR_REGEXP = /:([\+\w-]+):(?::(skin-tone-\d):)?/g
var EMOJI_NAME_REGEXP = /:([\+\w-]+):/g // word character, '_', or '-'
var isArray =
Array.isArray || function (arg) { Object.prototype.toString.call(arg) === '[object Array]' }
var arrayIncludes = Array.prototype.includes
? function (arr, arg) { return arr.includes(arg) }
: function (arr, arg) { arr.indexOf(arg) > -1 }
var defaultOptions = {
shortEmoji: true
}
module.exports = function krasivo (string, foreground, background, options) {
var str = string.toString().toLowerCase()
var rows = []
var rowFragments = []
var symbol // for use in inner cycle
options = Object.assign({}, defaultOptions, options || {})
for (var i = 0; i < SYMBOL_HEIGHT; i += 1) {
rowFragments.length = 0
for (var j = 0, l = str.length; j < l; j += 1) {
symbol = str[j]
try {
rowFragments.push(symbols[symbol][i])
} catch (e) {
throw new Error('Unsupported symbol: ' + symbol)
}
}
rows.push(rowFragments.join(BACKGROUND_SYMBOL))
}
return replaceForegroundAndBackground(
rows.join('\n'),
foreground.toString(),
background.toString(),
options
)
}
/**
* Replaces foreground and background placeholders with given foreground and background strings.
* Example:
* replaceForegroundAndBackground(
* `
* #....
* #....
* #....
* #....
* #....
* #....
* #####
* `,
* 'X',
* ' '
* )
* => `
* X
* X
* X
* X
* X
* X
* XXXXX
* `
*/
function replaceForegroundAndBackground(string, foreground, background, options) {
var matches, match // temporary storage for regexp matches
if (options.skinTone) {
while (match = EMOJI_WITH_SKIN_COLOUR_REGEXP.exec(foreground)) {
// if skin tone is not specified AND the emoji supports skin tones
if (match[2] === undefined && arrayIncludes(emoji.emojiWithSkinVariations, match[1])) {
foreground = foreground.replace(match[0], match[0] + ':skin-tone-' + options.skinTone + ':')
}
}
while (match = EMOJI_WITH_SKIN_COLOUR_REGEXP.exec(background)) {
// if skin tone is not specified AND the emoji supports skin tones
if (match[2] === undefined && arrayIncludes(emoji.emojiWithSkinVariations, match[1])) {
background = background.replace(match[0], match[0] + ':skin-tone-' + options.skinTone + ':')
}
}
}
if (options.shortEmoji) {
matches = foreground.match(EMOJI_NAME_REGEXP)
if (matches) {
for (var i = 0, l = matches.length; i < l; i += 1) {
match = matches[i]
foreground = foreground.replace(match, getEmojiByName(match))
}
}
matches = background.match(EMOJI_NAME_REGEXP)
if (matches) {
for (var i = 0, l = matches.length; i < l; i += 1) {
match = matches[i]
background = background.replace(match, getEmojiByName(match))
}
}
}
return string
.replace(FOREGROUND_REGEXP, foreground)
.replace(BACKGROUND_REGEXP, background)
}
/**
* Returns the emoji symbol from a given emoji name. If no emoji is found by given name,
* returns the given string as is.
* Examples:
* getEmojiByName(':100:') => '\u{1f4af}'
* getEmojiByName(':hash:') => '\u{0023}\u{feof}\u{20e3}'
* getEmojiByName(':krasivo:') => ':krasivo:'
*/
function getEmojiByName(name) {
// slice because we have to strip leading and trailing ':'
var emojiCode = emoji.emojiCodePoints[name.slice(1, -1)]
if (emojiCode === undefined) {
// no emoji found by short name, return initial string
return name
}
return isArray(emojiCode)
? emojiCode.map(symbolFromCodePoint).join('')
: symbolFromCodePoint(emojiCode)
}
/**
* Returns the Unicode symbol for a given code point.
* Example:
* symbolFromCodePoint(254) => '\u{feof}'
*/
function symbolFromCodePoint(codePoint) {
// AFAIK, using `eval` is the only way to generate any emoji from code points
return eval('"\\u{' + codePoint + '}"')
}