Last active
August 29, 2015 14:04
-
-
Save aroben/3dcf3783fc51c917df84 to your computer and use it in GitHub Desktop.
Test which Unicode code points are rendered as emoji on your system
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<style> | |
body { | |
font-family: monospace, "Segoe UI Emoji"; | |
} | |
</style> | |
</head> | |
<body> | |
<select id="switcher"> | |
<option value="">Show all characters</option> | |
<option value="color">Show only color emoji</option> | |
<option value="nocolor">Show only non-color emoji</option> | |
</select> | |
<table id="output"></table> | |
<script src="script.js"></script> | |
</body> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var showColorEmoji = location.search !== "?nocolor"; | |
var showNonEmoji = location.search !== "?color"; | |
function log() { | |
var table = document.getElementById("output"); | |
var row = table.insertRow(-1); | |
[].slice.call(arguments).forEach(function (arg) { | |
row.insertCell(-1).textContent = arg; | |
}); | |
} | |
function loaded(event) { | |
var json = JSON.parse(event.target.responseText); | |
var alternates = []; | |
json.filter(function(emoji) { | |
return emoji.emoji; | |
}).forEach(function(emoji) { | |
alternates = alternates.concat((emoji.unicodes || []).map(function(unicode) { | |
return {emoji: unicode, description: emoji.description + " (alias)"}; | |
})); | |
if (emoji.emoji.length === 1 && !isLeadingSurrogate(emoji.emoji.charCodeAt(0))) { | |
alternates.push({emoji: emoji.emoji + String.fromCharCode(0xfe0e), description: emoji.description + " + variation selector-15"}); | |
alternates.push({emoji: emoji.emoji + String.fromCharCode(0xfe0f), description: emoji.description + " + variation selector-16"}); | |
} else if (emoji.emoji.charCodeAt(emoji.emoji.length - 1) === 0xfe0f) { | |
var base = emoji.emoji.substr(0, emoji.emoji.length - 1); | |
alternates.push({emoji: base, description: emoji.description}); | |
alternates.push({emoji: base + String.fromCharCode(0xfe0e), description: emoji.description + " + variation selector-15"}); | |
emoji.description = emoji.description + " + variation selector-16"; | |
} | |
alternates.push(emoji); | |
}); | |
var seen = {}; | |
alternates.filter(function(emoji) { | |
var duplicate = emoji.emoji in seen; | |
seen[emoji.emoji] = true; | |
return !duplicate; | |
}).sort(function(a, b) { | |
var aPoints = codePoints(a.emoji); | |
var bPoints = codePoints(b.emoji); | |
return aPoints[0] - bPoints[0] | |
|| aPoints.length - bPoints.length | |
|| aPoints[1] - bPoints[1]; | |
}).forEach(function(emoji) { | |
testEmoji(emoji.emoji, emoji.description); | |
}); | |
} | |
function testEmoji(emoji, description) { | |
var points = codePoints(emoji).map(function(point) { | |
return "U+" + codePointToHex(point).toUpperCase(); | |
}).join(" "); | |
var color = isColorEmoji(emoji); | |
if (showColorEmoji && color || showNonEmoji && !color) | |
log(emoji, points, description); | |
} | |
function isColorEmoji(emoji) { | |
return color(emoji, "#f00") === color(emoji, "#0f0"); | |
} | |
var canvas = document.createElement("canvas"); | |
function color(emoji, rgb) { | |
var context = canvas.getContext("2d"); | |
context.clearRect(0, 0, 32, 32); | |
context.fillStyle = rgb; | |
context.textBaseline = "top"; | |
context.font = "32px Arial, 'Segoe UI Emoji'"; | |
context.fillText(emoji, 0, 0); | |
var data = context.getImageData(0, 0, 32, 32).data; | |
for (var i = 0; i < data.length; i += 4) { | |
if (data[i] === 0 && data[i + 1] === 0 && data[i + 2] === 0) { | |
continue; | |
} | |
return data[i].toString(16) | |
+ data[i + 1].toString(16) | |
+ data[i + 2].toString(16); | |
} | |
return "nothing"; | |
} | |
function codePoints(utf16) { | |
var points = []; | |
var index = 0; | |
while (index < utf16.length) { | |
var unit = utf16.charCodeAt(index); | |
if (!isLeadingSurrogate(unit)) { | |
points.push(unit); | |
index += 1; | |
continue; | |
} | |
var leading = unit; | |
var trailing = utf16.charCodeAt(index + 1); | |
if (trailing < 0xdc00 || trailing > 0xdfff) { | |
// Invalid surrogate pair | |
return; | |
} | |
// Surrogate pair! | |
points.push(0x10000 + ((leading - 0xd800) << 10) + (trailing - 0xdc00)); | |
index += 2; | |
} | |
return points; | |
} | |
function isLeadingSurrogate(codeUnit) { | |
return codeUnit >= 0xd800 && codeUnit <= 0xdbff; | |
} | |
function codePointToHex(point) { | |
var hex = point.toString(16); | |
while (hex.length < 4) { | |
hex = "0" + "" + hex; | |
} | |
return hex; | |
} | |
var switcher = document.getElementById("switcher"); | |
switcher.value = location.search.substr(1); | |
switcher.addEventListener("change", function(event) { | |
location.href = location.pathname + "?" + event.target.value; | |
}); | |
var xhr = new XMLHttpRequest; | |
xhr.open("GET", "https://rawgit.com/github/gemoji/master/db/emoji.json"); | |
xhr.onload = loaded; | |
xhr.send(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment