parent
aed5735620
commit
423a0fef67
|
@ -44,3 +44,20 @@ img.emoji {
|
||||||
width: 1em;
|
width: 1em;
|
||||||
height: 1em;
|
height: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
img.emoji.small {
|
||||||
|
width: 1.25em;
|
||||||
|
height: 1.25em;
|
||||||
|
}
|
||||||
|
img.emoji.medium {
|
||||||
|
width: 1.5em;
|
||||||
|
height: 1.5em;
|
||||||
|
}
|
||||||
|
img.emoji.large {
|
||||||
|
width: 1.75em;
|
||||||
|
height: 1.75em;
|
||||||
|
}
|
||||||
|
img.emoji.jumbo {
|
||||||
|
width: 2em;
|
||||||
|
height: 2em;
|
||||||
|
}
|
||||||
|
|
|
@ -16,9 +16,83 @@
|
||||||
this.img_sets.apple.path = '/images/emoji/apple/';
|
this.img_sets.apple.path = '/images/emoji/apple/';
|
||||||
this.replace_mode = 'img';
|
this.replace_mode = 'img';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
EmojiConvertor.prototype.getCountOfAllMatches = function(str, regex) {
|
||||||
|
var match = regex.exec(str);
|
||||||
|
var count = 0;
|
||||||
|
|
||||||
|
while (match) {
|
||||||
|
count += 1;
|
||||||
|
match = regex.exec(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
return count;
|
||||||
|
};
|
||||||
|
|
||||||
|
EmojiConvertor.prototype.hasNormalCharacters = function(str) {
|
||||||
|
var self = this;
|
||||||
|
var noEmoji = str.replace(self.rx_unified, '').trim();
|
||||||
|
return noEmoji.length > 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
EmojiConvertor.prototype.getSizeClass = function(str) {
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
if (self.hasNormalCharacters(str)) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
var emojiCount = self.getCountOfAllMatches(str, self.rx_unified);
|
||||||
|
if (emojiCount > 8) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
else if (emojiCount > 6) {
|
||||||
|
return 'small';
|
||||||
|
}
|
||||||
|
else if (emojiCount > 4) {
|
||||||
|
return 'medium';
|
||||||
|
}
|
||||||
|
else if (emojiCount > 2) {
|
||||||
|
return 'large';
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return 'jumbo';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// A stripped-down version of the original: https://github.com/WhisperSystems/Signal-Desktop/blob/aed573562018462fbacd8f2f715e9daeddcde0dd/components/emojijs/lib/emoji.js#L323-L396
|
||||||
|
// One primary change - we inject the second parameter as an additional class
|
||||||
|
EmojiConvertor.prototype.replacement = function(idx, sizeClass, actual, wrapper, variation) {
|
||||||
|
var self = this;
|
||||||
|
var img_set = self.img_set;
|
||||||
|
|
||||||
|
var extra = '';
|
||||||
|
var variation_idx = 0;
|
||||||
|
if (typeof variation === 'object') {
|
||||||
|
extra = self.replacement(variation.idx, null, variation.actual, variation.wrapper);
|
||||||
|
variation_idx = idx + '-' + variation.idx;
|
||||||
|
}
|
||||||
|
|
||||||
|
var img = self.data[idx][7] || self.img_sets[img_set].path + idx + '.png' + self.img_suffix;
|
||||||
|
var title = self.include_title ? ' title="' + (actual || self.data[idx][3][0]) + '"' : '';
|
||||||
|
|
||||||
|
if (variation_idx && self.variations_data[variation_idx] && self.variations_data[variation_idx][2] && !self.data[idx][7]) {
|
||||||
|
if (self.variations_data[variation_idx][2] & self.img_sets[self.img_set].mask) {
|
||||||
|
img = self.img_sets[self.img_set].path + variation_idx + '.png';
|
||||||
|
extra = '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return '<img src="' + img + '" class="emoji' + (sizeClass ? ' ' + sizeClass : '') + '"' + title + '/>';
|
||||||
|
};
|
||||||
|
|
||||||
|
// Modeled after the original: https://github.com/WhisperSystems/Signal-Desktop/blob/aed573562018462fbacd8f2f715e9daeddcde0dd/components/emojijs/lib/emoji.js#L265-L286
|
||||||
EmojiConvertor.prototype.replace_unified = function(str) {
|
EmojiConvertor.prototype.replace_unified = function(str) {
|
||||||
var self = this;
|
var self = this;
|
||||||
self.init_unified();
|
self.init_unified();
|
||||||
|
|
||||||
|
var sizeClass = self.getSizeClass(str);
|
||||||
|
|
||||||
return str.replace(self.rx_unified, function(m, p1, p2) {
|
return str.replace(self.rx_unified, function(m, p1, p2) {
|
||||||
var val = self.map.unified[p1];
|
var val = self.map.unified[p1];
|
||||||
if (!val) { return m; }
|
if (!val) { return m; }
|
||||||
|
@ -29,14 +103,14 @@
|
||||||
if (p2 == '\uD83C\uDFFE') { idx = '1f3fe'; }
|
if (p2 == '\uD83C\uDFFE') { idx = '1f3fe'; }
|
||||||
if (p2 == '\uD83C\uDFFF') { idx = '1f3ff'; }
|
if (p2 == '\uD83C\uDFFF') { idx = '1f3ff'; }
|
||||||
if (idx) {
|
if (idx) {
|
||||||
return self.replacement(val, null, null, {
|
return self.replacement(val, sizeClass, null, null, {
|
||||||
idx : idx,
|
idx : idx,
|
||||||
actual : p2,
|
actual : p2,
|
||||||
wrapper : ':'
|
wrapper : ':'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// wrap names in :'s
|
// wrap names in :'s
|
||||||
return self.replacement(val, ':' + self.data[val][3][0] + ':');
|
return self.replacement(val, sizeClass, ':' + self.data[val][3][0] + ':');
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
window.emoji = new EmojiConvertor();
|
window.emoji = new EmojiConvertor();
|
||||||
|
@ -46,6 +120,7 @@
|
||||||
if (!$el || !$el.length) {
|
if (!$el || !$el.length) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$el.html(emoji.replace_unified($el.html()));
|
$el.html(emoji.replace_unified($el.html()));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -704,6 +704,22 @@ img.emoji {
|
||||||
width: 1em;
|
width: 1em;
|
||||||
height: 1em; }
|
height: 1em; }
|
||||||
|
|
||||||
|
img.emoji.small {
|
||||||
|
width: 1.25em;
|
||||||
|
height: 1.25em; }
|
||||||
|
|
||||||
|
img.emoji.medium {
|
||||||
|
width: 1.5em;
|
||||||
|
height: 1.5em; }
|
||||||
|
|
||||||
|
img.emoji.large {
|
||||||
|
width: 1.75em;
|
||||||
|
height: 1.75em; }
|
||||||
|
|
||||||
|
img.emoji.jumbo {
|
||||||
|
width: 2em;
|
||||||
|
height: 2em; }
|
||||||
|
|
||||||
.settings.modal {
|
.settings.modal {
|
||||||
padding: 50px; }
|
padding: 50px; }
|
||||||
.settings.modal .content {
|
.settings.modal .content {
|
||||||
|
|
|
@ -0,0 +1,102 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
describe('EmojiUtil', function() {
|
||||||
|
describe('getCountOfAllMatches', function() {
|
||||||
|
it('returns zero for string with no matches', function() {
|
||||||
|
var r = /s/g;
|
||||||
|
var str = 'no match';
|
||||||
|
var actual = emoji.getCountOfAllMatches(str, r);
|
||||||
|
assert.equal(actual, 0);
|
||||||
|
});
|
||||||
|
it('returns 1 for one match', function() {
|
||||||
|
var r = /s/g;
|
||||||
|
var str = 'just one match';
|
||||||
|
var actual = emoji.getCountOfAllMatches(str, r);
|
||||||
|
assert.equal(actual, 1);
|
||||||
|
});
|
||||||
|
it('returns 2 for two matches', function() {
|
||||||
|
var r = /s/g;
|
||||||
|
var str = 's + s';
|
||||||
|
var actual = emoji.getCountOfAllMatches(str, r);
|
||||||
|
assert.equal(actual, 2);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('hasNormalCharacters', function() {
|
||||||
|
it('returns true for all normal text', function() {
|
||||||
|
var str = 'normal';
|
||||||
|
var actual = emoji.hasNormalCharacters(str);
|
||||||
|
assert.equal(actual, true);
|
||||||
|
});
|
||||||
|
it('returns false for all emoji text', function() {
|
||||||
|
var str = '🔥🔥🔥🔥';
|
||||||
|
var actual = emoji.hasNormalCharacters(str);
|
||||||
|
assert.equal(actual, false);
|
||||||
|
});
|
||||||
|
it('returns false for emojis mixed with spaces', function() {
|
||||||
|
var str = '🔥 🔥 🔥 🔥';
|
||||||
|
var actual = emoji.hasNormalCharacters(str);
|
||||||
|
assert.equal(actual, false);
|
||||||
|
});
|
||||||
|
it('returns true for emojis and text', function() {
|
||||||
|
var str = '🔥 normal 🔥 🔥 🔥';
|
||||||
|
var actual = emoji.hasNormalCharacters(str);
|
||||||
|
assert.equal(actual, true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('getSizeClass', function() {
|
||||||
|
it('returns nothing for non-emoji text', function() {
|
||||||
|
assert.equal(emoji.getSizeClass('normal text'), '');
|
||||||
|
});
|
||||||
|
it('returns nothing for emojis mixed with text', function() {
|
||||||
|
assert.equal(emoji.getSizeClass('🔥 normal 🔥'), '');
|
||||||
|
});
|
||||||
|
it('returns nothing for more than 8 emojis', function() {
|
||||||
|
assert.equal(emoji.getSizeClass('🔥🔥 🔥🔥 🔥🔥 🔥🔥 🔥'), '');
|
||||||
|
});
|
||||||
|
it('returns "small" for 7-8 emojis', function() {
|
||||||
|
assert.equal(emoji.getSizeClass('🔥🔥 🔥🔥 🔥🔥 🔥🔥'), 'small');
|
||||||
|
assert.equal(emoji.getSizeClass('🔥🔥 🔥🔥 🔥🔥 🔥'), 'small');
|
||||||
|
});
|
||||||
|
it('returns "medium" for 5-6 emojis', function() {
|
||||||
|
assert.equal(emoji.getSizeClass('🔥🔥 🔥🔥 🔥🔥'), 'medium');
|
||||||
|
assert.equal(emoji.getSizeClass('🔥🔥 🔥🔥 🔥'), 'medium');
|
||||||
|
});
|
||||||
|
it('returns "large" for 3-4 emojis', function() {
|
||||||
|
assert.equal(emoji.getSizeClass('🔥🔥 🔥🔥'), 'large');
|
||||||
|
assert.equal(emoji.getSizeClass('🔥🔥 🔥'), 'large');
|
||||||
|
});
|
||||||
|
it('returns "jumbo" for 1-2 emojis', function() {
|
||||||
|
assert.equal(emoji.getSizeClass('🔥🔥'), 'jumbo');
|
||||||
|
assert.equal(emoji.getSizeClass('🔥'), 'jumbo');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('replacement', function() {
|
||||||
|
it('returns an <img> tag', function() {
|
||||||
|
var actual = emoji.replacement('1f525');
|
||||||
|
assert.equal(actual, '<img src="/images/emoji/apple/1f525.png" class="emoji" title="fire"/>');
|
||||||
|
});
|
||||||
|
it('returns an <img> tag with provided sizeClass', function() {
|
||||||
|
var actual = emoji.replacement('1f525', 'large');
|
||||||
|
assert.equal(actual, '<img src="/images/emoji/apple/1f525.png" class="emoji large" title="fire"/>');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('replace_unified', function() {
|
||||||
|
it('returns images for every emoji', function() {
|
||||||
|
var actual = emoji.replace_unified('🏠 🔥');
|
||||||
|
var expected = '<img src="/images/emoji/apple/1f3e0.png" class="emoji jumbo" title=":house:"/>'
|
||||||
|
+ ' <img src="/images/emoji/apple/1f525.png" class="emoji jumbo" title=":fire:"/>';
|
||||||
|
|
||||||
|
assert.equal(expected, actual);
|
||||||
|
});
|
||||||
|
it('properly hyphenates a variation', function() {
|
||||||
|
var actual = emoji.replace_unified('💪🏿'); // muscle with dark skin tone modifier
|
||||||
|
var expected = '<img src="/images/emoji/apple/1f4aa-1f3ff.png" class="emoji jumbo" title="muscle"/>';
|
||||||
|
|
||||||
|
assert.equal(expected, actual);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -576,6 +576,7 @@
|
||||||
<script type="text/javascript" src="models/messages_test.js"></script>
|
<script type="text/javascript" src="models/messages_test.js"></script>
|
||||||
<script type="text/javascript" src="storage_test.js"></script>
|
<script type="text/javascript" src="storage_test.js"></script>
|
||||||
<script type="text/javascript" src="keychange_listener_test.js"></script>
|
<script type="text/javascript" src="keychange_listener_test.js"></script>
|
||||||
|
<script type="text/javascript" src="emoji_util_test.js"></script>
|
||||||
|
|
||||||
<script type="text/javascript" src="fixtures.js"></script>
|
<script type="text/javascript" src="fixtures.js"></script>
|
||||||
<script type="text/javascript" src="fixtures_test.js"></script>
|
<script type="text/javascript" src="fixtures_test.js"></script>
|
||||||
|
|
Loading…
Reference in New Issue