Merge pull request #2186 from MaxLeiter/emoji-tip

Improve accessibility for emoji
This commit is contained in:
Jérémie Astori 2018-03-18 15:50:57 -04:00 committed by GitHub
commit 8ecacc9978
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 2696 additions and 8 deletions

File diff suppressed because it is too large Load diff

View file

@ -9,6 +9,7 @@ const findEmoji = require("./ircmessageparser/findEmoji");
const findNames = require("./ircmessageparser/findNames"); const findNames = require("./ircmessageparser/findNames");
const merge = require("./ircmessageparser/merge"); const merge = require("./ircmessageparser/merge");
const colorClass = require("./colorClass"); const colorClass = require("./colorClass");
const emojiMap = require("../fullnamemap.json");
// Create an HTML `span` with styling information for a given fragment // Create an HTML `span` with styling information for a given fragment
function createFragment(fragment) { function createFragment(fragment) {
@ -114,7 +115,11 @@ module.exports = function parse(text, users) {
const escapedChannel = Handlebars.Utils.escapeExpression(textPart.channel); const escapedChannel = Handlebars.Utils.escapeExpression(textPart.channel);
return `<span class="inline-channel" role="button" tabindex="0" data-chan="${escapedChannel}">${fragments}</span>`; return `<span class="inline-channel" role="button" tabindex="0" data-chan="${escapedChannel}">${fragments}</span>`;
} else if (textPart.emoji) { } else if (textPart.emoji) {
return `<span class="emoji">${fragments}</span>`; if (!emojiMap[textPart.emoji]) {
return `<span class="emoji" role="img">${fragments}</span>`;
}
return `<span class="emoji" role="img" aria-label="Emoji: ${emojiMap[textPart.emoji]}" title="${emojiMap[textPart.emoji]}">${fragments}</span>`;
} else if (textPart.nick) { } else if (textPart.nick) {
const nick = Handlebars.Utils.escapeExpression(textPart.nick); const nick = Handlebars.Utils.escapeExpression(textPart.nick);
return `<span role="button" class="user ${colorClass(nick)}" data-name="${nick}">${fragments}</span>`; return `<span role="button" class="user ${colorClass(nick)}" data-name="${nick}">${fragments}</span>`;

View file

@ -10,18 +10,19 @@ request.get({
json: true, json: true,
}, (error, response, emojiStrategy) => { }, (error, response, emojiStrategy) => {
const emojiMap = {}; const emojiMap = {};
const fullNameEmojiMap = {};
for (const key in emojiStrategy) { for (const key in emojiStrategy) {
if (emojiStrategy.hasOwnProperty(key)) { if (emojiStrategy.hasOwnProperty(key)) {
const shortname = prepareShortName(emojiStrategy[key].shortname); const shortname = prepareShortName(emojiStrategy[key].shortname);
const unicode = stringToUnicode(emojiStrategy[key].unicode_output);
fullNameEmojiMap[unicode] = emojiStrategy[key].name;
// Skip tones, at least for now // Skip tones, at least for now
if (shortname.includes("tone")) { if (shortname.includes("tone")) {
continue; continue;
} }
const unicode = stringToUnicode(emojiStrategy[key].unicode_output);
emojiMap[shortname] = unicode; emojiMap[shortname] = unicode;
for (let alternative of emojiStrategy[key].shortname_alternates) { for (let alternative of emojiStrategy[key].shortname_alternates) {
@ -36,7 +37,8 @@ request.get({
} }
} }
const output = JSON.stringify(emojiMap, null, 2) + "\n"; const emojiMapOutput = JSON.stringify(emojiMap, null, 2) + "\n";
const fullNameEmojiMapOutput = JSON.stringify(fullNameEmojiMap, null, 2) + "\n";
fs.writeFileSync(path.resolve(path.join( fs.writeFileSync(path.resolve(path.join(
__dirname, __dirname,
@ -45,7 +47,16 @@ request.get({
"js", "js",
"libs", "libs",
"simplemap.json" "simplemap.json"
)), output); )), emojiMapOutput);
fs.writeFileSync(path.resolve(path.join(
__dirname,
"..",
"client",
"js",
"libs",
"fullnamemap.json"
)), fullNameEmojiMapOutput);
}); });
function stringToUnicode(key) { function stringToUnicode(key) {

View file

@ -358,16 +358,20 @@ describe("parse Handlebars helper", () => {
[{ [{
name: "in text", name: "in text",
input: "Hello💬", input: "Hello💬",
expected: 'Hello<span class="emoji">💬</span>', expected: 'Hello<span class="emoji" role="img" aria-label="Emoji: speech balloon" title="speech balloon">💬</span>',
}, {
name: "complicated zero-join-width emoji",
input: "🤦🏿‍♀️",
expected: '<span class="emoji" role="img" aria-label="Emoji: woman facepalming: dark skin tone" title="woman facepalming: dark skin tone">🤦🏿‍♀️</span>',
}, { }, {
name: "with modifiers", name: "with modifiers",
input: "🤷‍♀️", input: "🤷‍♀️",
expected: '<span class="emoji">🤷‍♀️</span>', expected: '<span class="emoji" role="img" aria-label="Emoji: woman shrugging" title="woman shrugging">🤷‍♀️</span>',
}, { }, {
// FIXME: These multiple `span`s should be optimized into a single one. See https://github.com/thelounge/thelounge/issues/1783 // FIXME: These multiple `span`s should be optimized into a single one. See https://github.com/thelounge/thelounge/issues/1783
name: "wrapped in style", name: "wrapped in style",
input: "Super \x034💚 green!", input: "Super \x034💚 green!",
expected: 'Super <span class="emoji"><span class="irc-fg4">💚</span></span><span class="irc-fg4"> green!</span>', expected: 'Super <span class="emoji" role="img" aria-label="Emoji: green heart" title="green heart"><span class="irc-fg4">💚</span></span><span class="irc-fg4"> green!</span>',
}, { }, {
name: "wrapped in URLs", name: "wrapped in URLs",
input: "https://i.❤️.thelounge.chat", input: "https://i.❤️.thelounge.chat",