emojis: fix rendering of custom emojis
This commit is contained in:
parent
77a0a01eff
commit
be20b8e1a0
@ -12,6 +12,7 @@ module.exports = function(config) {
|
|||||||
{ pattern: "dist/emojis.js", served: true },
|
{ pattern: "dist/emojis.js", served: true },
|
||||||
"dist/converse.js",
|
"dist/converse.js",
|
||||||
"dist/converse.css",
|
"dist/converse.css",
|
||||||
|
{ pattern: "dist/images/**/*.*", included: false },
|
||||||
{ pattern: "dist/webfonts/**/*.*", included: false },
|
{ pattern: "dist/webfonts/**/*.*", included: false },
|
||||||
{ pattern: "dist/\@fortawesome/fontawesome-free/sprites/solid.svg",
|
{ pattern: "dist/\@fortawesome/fontawesome-free/sprites/solid.svg",
|
||||||
watched: false,
|
watched: false,
|
||||||
@ -60,7 +61,8 @@ module.exports = function(config) {
|
|||||||
],
|
],
|
||||||
|
|
||||||
proxies: {
|
proxies: {
|
||||||
"/dist/\@fortawesome/fontawesome-free/sprites/solid.svg": "/base/dist/\@fortawesome/fontawesome-free/sprites/solid.svg"
|
"/dist/\@fortawesome/fontawesome-free/sprites/solid.svg": "/base/dist/\@fortawesome/fontawesome-free/sprites/solid.svg",
|
||||||
|
"/dist/images/custom_emojis/": "/base/dist/images/custom_emojis/"
|
||||||
},
|
},
|
||||||
|
|
||||||
client: {
|
client: {
|
||||||
|
@ -100,7 +100,6 @@ describe("Emojis", function () {
|
|||||||
done();
|
done();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
|
||||||
it("allows you to search for particular emojis",
|
it("allows you to search for particular emojis",
|
||||||
mock.initConverse(
|
mock.initConverse(
|
||||||
['rosterGroupsFetched', 'chatBoxesFetched'], {},
|
['rosterGroupsFetched', 'chatBoxesFetched'], {},
|
||||||
@ -239,5 +238,51 @@ describe("Emojis", function () {
|
|||||||
expect(u.hasClass('chat-msg__text--larger', message)).toBe(true);
|
expect(u.hasClass('chat-msg__text--larger', message)).toBe(true);
|
||||||
done()
|
done()
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
|
||||||
|
it("can show custom emojis",
|
||||||
|
mock.initConverse(
|
||||||
|
['rosterGroupsFetched', 'chatBoxesFetched'],
|
||||||
|
{ emoji_categories: {
|
||||||
|
"smileys": ":grinning:",
|
||||||
|
"people": ":thumbsup:",
|
||||||
|
"activity": ":soccer:",
|
||||||
|
"travel": ":motorcycle:",
|
||||||
|
"objects": ":bomb:",
|
||||||
|
"nature": ":rainbow:",
|
||||||
|
"food": ":hotdog:",
|
||||||
|
"symbols": ":musical_note:",
|
||||||
|
"flags": ":flag_ac:",
|
||||||
|
"custom": ':xmpp:'
|
||||||
|
} },
|
||||||
|
async function (done, _converse) {
|
||||||
|
|
||||||
|
await mock.waitForRoster(_converse, 'current', 1);
|
||||||
|
const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit';
|
||||||
|
await mock.openChatBoxFor(_converse, contact_jid);
|
||||||
|
const view = _converse.api.chatviews.get(contact_jid);
|
||||||
|
|
||||||
|
const toolbar = await u.waitUntil(() => view.el.querySelector('ul.chat-toolbar'));
|
||||||
|
expect(toolbar.querySelectorAll('li.toggle-smiley__container').length).toBe(1);
|
||||||
|
toolbar.querySelector('a.toggle-smiley').click();
|
||||||
|
await u.waitUntil(() => u.isVisible(view.el.querySelector('.emoji-picker__lists')), 1000);
|
||||||
|
const picker = await u.waitUntil(() => view.el.querySelector('.emoji-picker__container'), 1000);
|
||||||
|
const custom_category = picker.querySelector('.pick-category[data-category="custom"]');
|
||||||
|
expect(custom_category.innerHTML.replace(/<!---->/g, '').trim()).toBe(
|
||||||
|
'<img class="emoji" draggable="false" title=":xmpp:" alt=":xmpp:" src="/dist/images/custom_emojis/xmpp.png">');
|
||||||
|
|
||||||
|
const textarea = view.el.querySelector('textarea.chat-textarea');
|
||||||
|
textarea.value = 'Running tests for :converse:';
|
||||||
|
view.onKeyDown({
|
||||||
|
target: textarea,
|
||||||
|
preventDefault: function preventDefault () {},
|
||||||
|
keyCode: 13 // Enter
|
||||||
|
});
|
||||||
|
await new Promise(resolve => view.model.messages.once('rendered', resolve));
|
||||||
|
const body = view.el.querySelector('converse-chat-message-body');
|
||||||
|
expect(body.innerHTML.replace(/<!---->/g, '').trim()).toBe(
|
||||||
|
'Running tests for <img class="emoji" draggable="false" title=":converse:" alt=":converse:" src="/dist/images/custom_emojis/converse.png">');
|
||||||
|
done();
|
||||||
|
}));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -951,21 +951,23 @@ converse.plugins.add('converse-chat', {
|
|||||||
getOutgoingMessageAttributes (text, spoiler_hint) {
|
getOutgoingMessageAttributes (text, spoiler_hint) {
|
||||||
const is_spoiler = this.get('composing_spoiler');
|
const is_spoiler = this.get('composing_spoiler');
|
||||||
const origin_id = u.getUniqueId();
|
const origin_id = u.getUniqueId();
|
||||||
|
const body = text ? u.httpToGeoUri(u.shortnameToUnicode(text), _converse) : undefined;
|
||||||
return {
|
return {
|
||||||
'id': origin_id,
|
|
||||||
'jid': this.get('jid'),
|
|
||||||
'nickname': this.get('nickname'),
|
|
||||||
'msgid': origin_id,
|
|
||||||
'origin_id': origin_id,
|
|
||||||
'fullname': _converse.xmppstatus.get('fullname'),
|
|
||||||
'from': _converse.bare_jid,
|
'from': _converse.bare_jid,
|
||||||
|
'fullname': _converse.xmppstatus.get('fullname'),
|
||||||
|
'id': origin_id,
|
||||||
'is_only_emojis': text ? u.isOnlyEmojis(text) : false,
|
'is_only_emojis': text ? u.isOnlyEmojis(text) : false,
|
||||||
|
'jid': this.get('jid'),
|
||||||
|
'message': body,
|
||||||
|
'msgid': origin_id,
|
||||||
|
'nickname': this.get('nickname'),
|
||||||
'sender': 'me',
|
'sender': 'me',
|
||||||
'time': (new Date()).toISOString(),
|
|
||||||
'message': text ? u.httpToGeoUri(u.shortnameToUnicode(text), _converse) : undefined,
|
|
||||||
'is_spoiler': is_spoiler,
|
|
||||||
'spoiler_hint': is_spoiler ? spoiler_hint : undefined,
|
'spoiler_hint': is_spoiler ? spoiler_hint : undefined,
|
||||||
'type': this.get('message_type')
|
'time': (new Date()).toISOString(),
|
||||||
|
'type': this.get('message_type'),
|
||||||
|
body,
|
||||||
|
is_spoiler,
|
||||||
|
origin_id
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -3,10 +3,11 @@
|
|||||||
* @copyright 2020, the Converse.js contributors
|
* @copyright 2020, the Converse.js contributors
|
||||||
* @license Mozilla Public License (MPLv2)
|
* @license Mozilla Public License (MPLv2)
|
||||||
*/
|
*/
|
||||||
import { Model } from '@converse/skeletor/src/model.js';
|
|
||||||
import { find, uniq } from "lodash-es";
|
|
||||||
import * as twemoji from "twemoji";
|
import * as twemoji from "twemoji";
|
||||||
|
import { Model } from '@converse/skeletor/src/model.js';
|
||||||
import { _converse, api, converse } from "./converse-core";
|
import { _converse, api, converse } from "./converse-core";
|
||||||
|
import { find, isString, uniq } from "lodash-es";
|
||||||
|
import { html } from 'lit-html';
|
||||||
|
|
||||||
const u = converse.env.utils;
|
const u = converse.env.utils;
|
||||||
|
|
||||||
@ -27,6 +28,7 @@ const ASCII_LIST = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
let shortnames_regex;
|
||||||
const ASCII_REGEX = '(\\*\\\\0\\/\\*|\\*\\\\O\\/\\*|\\-___\\-|\\:\'\\-\\)|\'\\:\\-\\)|\'\\:\\-D|\\>\\:\\-\\)|>\\:\\-\\)|\'\\:\\-\\(|\\>\\:\\-\\(|>\\:\\-\\(|\\:\'\\-\\(|O\\:\\-\\)|0\\:\\-3|0\\:\\-\\)|0;\\^\\)|O;\\-\\)|0;\\-\\)|O\\:\\-3|\\-__\\-|\\:\\-Þ|\\:\\-Þ|\\<\\/3|<\\/3|\\:\'\\)|\\:\\-D|\'\\:\\)|\'\\=\\)|\'\\:D|\'\\=D|\\>\\:\\)|>\\:\\)|\\>;\\)|>;\\)|\\>\\=\\)|>\\=\\)|;\\-\\)|\\*\\-\\)|;\\-\\]|;\\^\\)|\'\\:\\(|\'\\=\\(|\\:\\-\\*|\\:\\^\\*|\\>\\:P|>\\:P|X\\-P|\\>\\:\\[|>\\:\\[|\\:\\-\\(|\\:\\-\\[|\\>\\:\\(|>\\:\\(|\\:\'\\(|;\\-\\(|\\>\\.\\<|>\\.<|#\\-\\)|%\\-\\)|X\\-\\)|\\\\0\\/|\\\\O\\/|0\\:3|0\\:\\)|O\\:\\)|O\\=\\)|O\\:3|B\\-\\)|8\\-\\)|B\\-D|8\\-D|\\-_\\-|\\>\\:\\\\|>\\:\\\\|\\>\\:\\/|>\\:\\/|\\:\\-\\/|\\:\\-\\.|\\:\\-P|\\:Þ|\\:Þ|\\:\\-b|\\:\\-O|O_O|\\>\\:O|>\\:O|\\:\\-X|\\:\\-#|\\:\\-\\)|\\(y\\)|\\<3|<3|\\:D|\\=D|;\\)|\\*\\)|;\\]|;D|\\:\\*|\\=\\*|\\:\\(|\\:\\[|\\=\\(|\\:@|;\\(|D\\:|\\:\\$|\\=\\$|#\\)|%\\)|X\\)|B\\)|8\\)|\\:\\/|\\:\\\\|\\=\\/|\\=\\\\|\\:L|\\=L|\\:P|\\=P|\\:b|\\:O|\\:X|\\:#|\\=X|\\=#|\\:\\)|\\=\\]|\\=\\)|\\:\\])';
|
const ASCII_REGEX = '(\\*\\\\0\\/\\*|\\*\\\\O\\/\\*|\\-___\\-|\\:\'\\-\\)|\'\\:\\-\\)|\'\\:\\-D|\\>\\:\\-\\)|>\\:\\-\\)|\'\\:\\-\\(|\\>\\:\\-\\(|>\\:\\-\\(|\\:\'\\-\\(|O\\:\\-\\)|0\\:\\-3|0\\:\\-\\)|0;\\^\\)|O;\\-\\)|0;\\-\\)|O\\:\\-3|\\-__\\-|\\:\\-Þ|\\:\\-Þ|\\<\\/3|<\\/3|\\:\'\\)|\\:\\-D|\'\\:\\)|\'\\=\\)|\'\\:D|\'\\=D|\\>\\:\\)|>\\:\\)|\\>;\\)|>;\\)|\\>\\=\\)|>\\=\\)|;\\-\\)|\\*\\-\\)|;\\-\\]|;\\^\\)|\'\\:\\(|\'\\=\\(|\\:\\-\\*|\\:\\^\\*|\\>\\:P|>\\:P|X\\-P|\\>\\:\\[|>\\:\\[|\\:\\-\\(|\\:\\-\\[|\\>\\:\\(|>\\:\\(|\\:\'\\(|;\\-\\(|\\>\\.\\<|>\\.<|#\\-\\)|%\\-\\)|X\\-\\)|\\\\0\\/|\\\\O\\/|0\\:3|0\\:\\)|O\\:\\)|O\\=\\)|O\\:3|B\\-\\)|8\\-\\)|B\\-D|8\\-D|\\-_\\-|\\>\\:\\\\|>\\:\\\\|\\>\\:\\/|>\\:\\/|\\:\\-\\/|\\:\\-\\.|\\:\\-P|\\:Þ|\\:Þ|\\:\\-b|\\:\\-O|O_O|\\>\\:O|>\\:O|\\:\\-X|\\:\\-#|\\:\\-\\)|\\(y\\)|\\<3|<3|\\:D|\\=D|;\\)|\\*\\)|;\\]|;D|\\:\\*|\\=\\*|\\:\\(|\\:\\[|\\=\\(|\\:@|;\\(|D\\:|\\:\\$|\\=\\$|#\\)|%\\)|X\\)|B\\)|8\\)|\\:\\/|\\:\\\\|\\=\\/|\\=\\\\|\\:L|\\=L|\\:P|\\=P|\\:b|\\:O|\\:X|\\:#|\\=X|\\=#|\\:\\)|\\=\\]|\\=\\)|\\:\\])';
|
||||||
const ASCII_REPLACE_REGEX = new RegExp("<object[^>]*>.*?<\/object>|<span[^>]*>.*?<\/span>|<(?:object|embed|svg|img|div|span|p|a)[^>]*>|((\\s|^)"+ASCII_REGEX+"(?=\\s|$|[!,.?]))", "gi");
|
const ASCII_REPLACE_REGEX = new RegExp("<object[^>]*>.*?<\/object>|<span[^>]*>.*?<\/span>|<(?:object|embed|svg|img|div|span|p|a)[^>]*>|((\\s|^)"+ASCII_REGEX+"(?=\\s|$|[!,.?]))", "gi");
|
||||||
|
|
||||||
@ -54,6 +56,74 @@ function convert (unicode) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function getTonedEmojis () {
|
||||||
|
if (!_converse.toned_emojis) {
|
||||||
|
_converse.toned_emojis = uniq(
|
||||||
|
Object.values(_converse.emojis.json.people)
|
||||||
|
.filter(person => person.sn.includes('_tone'))
|
||||||
|
.map(person => person.sn.replace(/_tone[1-5]/, ''))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return _converse.toned_emojis;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function convertASCII2Emoji (str) {
|
||||||
|
// Replace ASCII smileys
|
||||||
|
return str.replace(ASCII_REPLACE_REGEX, (entire, m1, m2, m3) => {
|
||||||
|
if( (typeof m3 === 'undefined') || (m3 === '') || (!(u.unescapeHTML(m3) in ASCII_LIST)) ) {
|
||||||
|
// if the ascii doesnt exist just return the entire match
|
||||||
|
return entire;
|
||||||
|
}
|
||||||
|
m3 = u.unescapeHTML(m3);
|
||||||
|
const unicode = ASCII_LIST[m3].toUpperCase();
|
||||||
|
return m2+convert(unicode);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function getEmojiMarkup (shortname, unicode_only) {
|
||||||
|
if ((typeof shortname === 'undefined') || (shortname === '') || (!_converse.emoji_shortnames.includes(shortname))) {
|
||||||
|
// if the shortname doesnt exist just return the entire match
|
||||||
|
return shortname;
|
||||||
|
}
|
||||||
|
const codepoint = _converse.emojis_map[shortname].cp;
|
||||||
|
if (codepoint) {
|
||||||
|
return convert(codepoint.toUpperCase());
|
||||||
|
} else if (unicode_only) {
|
||||||
|
return shortname;
|
||||||
|
} else {
|
||||||
|
return html`<img class="emoji" draggable="false" title="${shortname}" alt="${shortname}" src="${_converse.emojis_map[shortname].url}">`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function addEmojisMarkup (text, unicode_only=false) {
|
||||||
|
const original_text = text;
|
||||||
|
let list = [text];
|
||||||
|
const references = [...text.matchAll(shortnames_regex)];
|
||||||
|
if (references.length) {
|
||||||
|
references.map(ref => {
|
||||||
|
ref.begin = ref.index;
|
||||||
|
ref.end = ref.index+ref[0].length;
|
||||||
|
return ref;
|
||||||
|
})
|
||||||
|
.sort((a, b) => b.begin - a.begin)
|
||||||
|
.forEach(ref => {
|
||||||
|
const text = list.shift();
|
||||||
|
const shortname = original_text.slice(ref.begin, ref.end);
|
||||||
|
const emoji = getEmojiMarkup(shortname, unicode_only);
|
||||||
|
if (isString(emoji)) {
|
||||||
|
list = [text.slice(0, ref.begin) + emoji + text.slice(ref.end), ...list];
|
||||||
|
} else {
|
||||||
|
list = [text.slice(0, ref.begin), emoji, text.slice(ref.end), ...list];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
converse.plugins.add('converse-emoji', {
|
converse.plugins.add('converse-emoji', {
|
||||||
|
|
||||||
initialize () {
|
initialize () {
|
||||||
@ -115,42 +185,15 @@ converse.plugins.add('converse-emoji', {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
function getTonedEmojis () {
|
|
||||||
if (!_converse.toned_emojis) {
|
|
||||||
_converse.toned_emojis = uniq(
|
|
||||||
Object.values(_converse.emojis.json.people)
|
|
||||||
.filter(person => person.sn.includes('_tone'))
|
|
||||||
.map(person => person.sn.replace(/_tone[1-5]/, ''))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return _converse.toned_emojis;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/************************ BEGIN Utils ************************/
|
/************************ BEGIN Utils ************************/
|
||||||
// Closured cache
|
// Closured cache
|
||||||
const emojis_by_attribute = {};
|
const emojis_by_attribute = {};
|
||||||
|
|
||||||
Object.assign(u, {
|
Object.assign(u, {
|
||||||
|
|
||||||
/**
|
|
||||||
* Replaces emoji shortnames in the passed-in string with unicode or image-based emojis
|
|
||||||
* (based on the value of `use_system_emojis`).
|
|
||||||
* @method u.addEmoji
|
|
||||||
* @param {string} text = The text
|
|
||||||
* @returns {string} The text with shortnames replaced with emoji
|
|
||||||
* unicodes or images.
|
|
||||||
*/
|
|
||||||
addEmoji (text) {
|
|
||||||
return u.getEmojiRenderer()(text);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Based on the value of `use_system_emojis` will return either
|
* Based on the value of `use_system_emojis` will return either
|
||||||
* a function that converts emoji shortnames into unicode glyphs
|
* a function that converts emoji shortnames into unicode glyphs
|
||||||
* (see {@link u.shortnameToUnicode} or one that converts them into images.
|
* (see {@link u.shortnamesToEmojis} or one that converts them into images.
|
||||||
* unicode emojis
|
|
||||||
* @method u.getEmojiRenderer
|
|
||||||
* @returns {function}
|
* @returns {function}
|
||||||
*/
|
*/
|
||||||
getEmojiRenderer () {
|
getEmojiRenderer () {
|
||||||
@ -164,55 +207,51 @@ converse.plugins.add('converse-emoji', {
|
|||||||
return api.settings.get('use_system_emojis') ? transform : text => twemoji.default.parse(transform(text), how);
|
return api.settings.get('use_system_emojis') ? transform : text => twemoji.default.parse(transform(text), how);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Replaces emoji shortnames in the passed-in string with unicode or image-based emojis
|
||||||
|
* (based on the value of `use_system_emojis`).
|
||||||
|
* @method u.addEmoji
|
||||||
|
* @param {string} text = The text
|
||||||
|
* @returns {string} The text with shortnames replaced with emoji
|
||||||
|
* unicodes or images.
|
||||||
|
*/
|
||||||
|
addEmoji (text) {
|
||||||
|
return u.getEmojiRenderer()(text);
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns an emoji represented by the passed in shortname.
|
* Returns an emoji represented by the passed in shortname.
|
||||||
* Scans the passed in text for shortnames and replaces them with
|
* Scans the passed in text for shortnames and replaces them with
|
||||||
* emoji unicode glyphs or alternatively if it's a custom emoji
|
* emoji unicode glyphs or alternatively if it's a custom emoji
|
||||||
* without unicode representation then markup for an HTML image tag
|
* without unicode representation then a lit-html TemplateResult
|
||||||
* is returned.
|
* which represents image tag markup is returned.
|
||||||
*
|
*
|
||||||
* The shortname needs to be defined in `emojis.json`
|
* The shortname needs to be defined in `emojis.json`
|
||||||
* and needs to have either a `cp` attribute for the codepoint, or
|
* and needs to have either a `cp` attribute for the codepoint, or
|
||||||
* an `url` attribute which points to the source for the image.
|
* an `url` attribute which points to the source for the image.
|
||||||
*
|
*
|
||||||
* @method u.shortnamesToEmojis
|
* @method u.shortnamesToEmojis
|
||||||
* @param {string} str - String containg the shortname(s)
|
* @param {String} str - String containg the shortname(s)
|
||||||
|
* @param {Boolean} unicode_only - Whether emojis are rendered as
|
||||||
|
* unicode codepoints. If so, the returned result will be an array
|
||||||
|
* with containing one string, because the emojis themselves will
|
||||||
|
* also be strings. If set to false, emojis will be represented by
|
||||||
|
* lit-html TemplateResult objects.
|
||||||
|
* @returns {Array} An array of at least one string, or otherwise
|
||||||
|
* strings and lit-html TemplateResult objects.
|
||||||
*/
|
*/
|
||||||
shortnamesToEmojis (str, unicode_only=false) {
|
shortnamesToEmojis (str, unicode_only=false) {
|
||||||
str = str.replace(_converse.emojis.shortnames_regex, shortname => {
|
str = convertASCII2Emoji(str);
|
||||||
if ((typeof shortname === 'undefined') || (shortname === '') || (!_converse.emoji_shortnames.includes(shortname))) {
|
return addEmojisMarkup(str, unicode_only);
|
||||||
// if the shortname doesnt exist just return the entire match
|
|
||||||
return shortname;
|
|
||||||
}
|
|
||||||
const codepoint = _converse.emojis_map[shortname].cp;
|
|
||||||
if (codepoint) {
|
|
||||||
return convert(codepoint.toUpperCase());
|
|
||||||
} else if (unicode_only) {
|
|
||||||
return shortname;
|
|
||||||
} else {
|
|
||||||
return `<img class="emoji" draggable="false" alt="${shortname}" src="${_converse.emojis_map[shortname].url}">`;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
// Also replace ASCII smileys
|
|
||||||
str = str.replace(ASCII_REPLACE_REGEX, (entire, m1, m2, m3) => {
|
|
||||||
if( (typeof m3 === 'undefined') || (m3 === '') || (!(u.unescapeHTML(m3) in ASCII_LIST)) ) {
|
|
||||||
// if the ascii doesnt exist just return the entire match
|
|
||||||
return entire;
|
|
||||||
}
|
|
||||||
m3 = u.unescapeHTML(m3);
|
|
||||||
const unicode = ASCII_LIST[m3].toUpperCase();
|
|
||||||
return m2+convert(unicode);
|
|
||||||
});
|
|
||||||
return str;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns unicode represented by the passed in shortname.
|
* Returns unicode represented by the passed in shortname.
|
||||||
* @method u.shortnameToUnicode
|
* @method u.shortnameToUnicode
|
||||||
* @param {string} str - String containg the shortname(s)
|
* @param {string} str - String containing the shortname(s)
|
||||||
*/
|
*/
|
||||||
shortnameToUnicode (str) {
|
shortnameToUnicode (str) {
|
||||||
return this.shortnamesToEmojis(str, true);
|
return u.shortnamesToEmojis(str, true)[0];
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -290,7 +329,7 @@ converse.plugins.add('converse-emoji', {
|
|||||||
_converse.emoji_shortnames = _converse.emojis_list.map(m => m.sn);
|
_converse.emoji_shortnames = _converse.emojis_list.map(m => m.sn);
|
||||||
|
|
||||||
const getShortNames = () => _converse.emoji_shortnames.map(s => s.replace(/[+]/g, "\\$&")).join('|');
|
const getShortNames = () => _converse.emoji_shortnames.map(s => s.replace(/[+]/g, "\\$&")).join('|');
|
||||||
_converse.emojis.shortnames_regex = new RegExp("<object[^>]*>.*?<\/object>|<span[^>]*>.*?<\/span>|<(?:object|embed|svg|img|div|span|p|a)[^>]*>|("+getShortNames()+")", "gi");
|
shortnames_regex = new RegExp(getShortNames(), "gi");
|
||||||
|
|
||||||
_converse.emojis.toned = getTonedEmojis();
|
_converse.emojis.toned = getTonedEmojis();
|
||||||
_converse.emojis.initialized.resolve();
|
_converse.emojis.initialized.resolve();
|
||||||
|
@ -964,8 +964,6 @@ converse.plugins.add('converse-muc', {
|
|||||||
if (!raw_mentions) return [original_message, []];
|
if (!raw_mentions) return [original_message, []];
|
||||||
|
|
||||||
const known_nicknames = this.getAllKnownNicknames();
|
const known_nicknames = this.getAllKnownNicknames();
|
||||||
const known_nicknames_with_at_regex = this.getAllKnownNicknamesRegex();
|
|
||||||
const getMatchesForNickRegex = nick_regex => [...findRegexInMessage(nick_regex)];
|
|
||||||
const getMatchingNickname = p.findFirstMatchInArray(known_nicknames);
|
const getMatchingNickname = p.findFirstMatchInArray(known_nicknames);
|
||||||
|
|
||||||
const uriFromNickname = nickname => {
|
const uriFromNickname = nickname => {
|
||||||
@ -985,7 +983,7 @@ converse.plugins.add('converse-muc', {
|
|||||||
return { begin, end, value, type, uri }
|
return { begin, end, value, type, uri }
|
||||||
}
|
}
|
||||||
|
|
||||||
const mentions = getMatchesForNickRegex(known_nicknames_with_at_regex);
|
const mentions = [...findRegexInMessage(this.getAllKnownNicknamesRegex())];
|
||||||
const references = mentions.map(matchToReference);
|
const references = mentions.map(matchToReference);
|
||||||
|
|
||||||
const [updated_message, updated_references] = p.reduceTextFromReferences(
|
const [updated_message, updated_references] = p.reduceTextFromReferences(
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"custom": {
|
"custom": {
|
||||||
":converse:":{"sn":":converse:","url":"/dist/custom_emojis/converse.png","c":"custom"},
|
":converse:":{"sn":":converse:","url":"/dist/images/custom_emojis/converse.png","c":"custom"},
|
||||||
":xmpp:":{"sn":":xmpp:","url":"/dist/custom_emojis/xmpp.png","c":"custom"}
|
":xmpp:":{"sn":":xmpp:","url":"/dist/images/custom_emojis/xmpp.png","c":"custom"}
|
||||||
},
|
},
|
||||||
"smileys": {
|
"smileys": {
|
||||||
":smiley:":{"sn":":smiley:","cp":"1f603","sns":[],"c":"smileys"},
|
":smiley:":{"sn":":smiley:","cp":"1f603","sns":[],"c":"smileys"},
|
||||||
|
@ -30,12 +30,12 @@ class MessageBodyRenderer extends String {
|
|||||||
text = text.replace(/\n\n+/g, '\n\n');
|
text = text.replace(/\n\n+/g, '\n\n');
|
||||||
text = u.geoUriToHttp(text, _converse.geouri_replacement);
|
text = u.geoUriToHttp(text, _converse.geouri_replacement);
|
||||||
|
|
||||||
const process = (text) => {
|
let list = await Promise.all(u.addHyperlinks(text));
|
||||||
text = u.addEmoji(text);
|
|
||||||
return addMentionsMarkup(text, this.model.get('references'), this.model.collection.chatbox);
|
list = list.reduce((acc, i) => isString(i) ? [...acc, ...u.addEmoji(i)] : [...acc, i], []);
|
||||||
}
|
|
||||||
const list = await Promise.all(u.addHyperlinks(text));
|
const addMentions = text => addMentionsMarkup(text, this.model.get('references'), this.model.collection.chatbox)
|
||||||
this.list = list.reduce((acc, i) => isString(i) ? [...acc, ...process(i)] : [...acc, i], []);
|
list = list.reduce((acc, i) => isString(i) ? [...acc, ...addMentions(i)] : [...acc, i], []);
|
||||||
/**
|
/**
|
||||||
* Synchronous event which provides a hook for transforming a chat message's body text
|
* Synchronous event which provides a hook for transforming a chat message's body text
|
||||||
* after the default transformations have been applied.
|
* after the default transformations have been applied.
|
||||||
@ -45,8 +45,7 @@ class MessageBodyRenderer extends String {
|
|||||||
* @example _converse.api.listen.on('afterMessageBodyTransformed', (view, text) => { ... });
|
* @example _converse.api.listen.on('afterMessageBodyTransformed', (view, text) => { ... });
|
||||||
*/
|
*/
|
||||||
await api.trigger('afterMessageBodyTransformed', this.model, text, {'Synchronous': true});
|
await api.trigger('afterMessageBodyTransformed', this.model, text, {'Synchronous': true});
|
||||||
|
return list;
|
||||||
return this.list;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async render () {
|
async render () {
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
import { html } from "lit-html";
|
import { html } from "lit-html";
|
||||||
import { __ } from '@converse/headless/i18n';
|
import { __ } from '@converse/headless/i18n';
|
||||||
import { unsafeHTML } from 'lit-html/directives/unsafe-html.js';
|
|
||||||
import xss from "xss/dist/xss";
|
|
||||||
|
|
||||||
|
|
||||||
const i18n_search = __('Search');
|
const i18n_search = __('Search');
|
||||||
@ -10,7 +8,6 @@ const skintones = ['tone1', 'tone2', 'tone3', 'tone4', 'tone5'];
|
|||||||
|
|
||||||
|
|
||||||
const emoji_category = (o) => {
|
const emoji_category = (o) => {
|
||||||
const category_emoji = unsafeHTML(xss.filterXSS(o.transformCategory(o.emoji_categories[o.category]), {'whiteList': {'img': ['class', 'draggable' ,'alt', 'src', 'title']}}));
|
|
||||||
return html`
|
return html`
|
||||||
<li data-category="${o.category}"
|
<li data-category="${o.category}"
|
||||||
class="emoji-category ${o.category} ${(o.current_category === o.category) ? 'picked' : ''}"
|
class="emoji-category ${o.category} ${(o.current_category === o.category) ? 'picked' : ''}"
|
||||||
@ -19,7 +16,7 @@ const emoji_category = (o) => {
|
|||||||
<a class="pick-category"
|
<a class="pick-category"
|
||||||
@click=${o.onCategoryPicked}
|
@click=${o.onCategoryPicked}
|
||||||
href="#emoji-picker-${o.category}"
|
href="#emoji-picker-${o.category}"
|
||||||
data-category="${o.category}">${category_emoji} </a>
|
data-category="${o.category}">${o.transformCategory(o.emoji_categories[o.category])} </a>
|
||||||
</li>
|
</li>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
@ -30,12 +27,10 @@ const emoji_picker_header = (o) => html`
|
|||||||
</ul>
|
</ul>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
|
||||||
const emoji_item = (o) => {
|
const emoji_item = (o) => {
|
||||||
const emoji = unsafeHTML(xss.filterXSS(o.transform(o.emoji.sn), {'whiteList': {'img': ['class', 'draggable' ,'alt', 'src', 'title']}}));
|
|
||||||
return html`
|
return html`
|
||||||
<li class="emoji insert-emoji ${o.shouldBeHidden(o.emoji.sn) ? 'hidden' : ''}" data-emoji="${o.emoji.sn}" title="${o.emoji.sn}">
|
<li class="emoji insert-emoji ${o.shouldBeHidden(o.emoji.sn) ? 'hidden' : ''}" data-emoji="${o.emoji.sn}" title="${o.emoji.sn}">
|
||||||
<a href="#" @click=${o.onEmojiPicked} data-emoji="${o.emoji.sn}">${emoji}</a>
|
<a href="#" @click=${o.onEmojiPicked} data-emoji="${o.emoji.sn}">${o.transform(o.emoji.sn)}</a>
|
||||||
</li>
|
</li>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
@ -58,11 +53,9 @@ const emojis_for_category = (o) => html`
|
|||||||
|
|
||||||
|
|
||||||
const skintone_emoji = (o) => {
|
const skintone_emoji = (o) => {
|
||||||
const shortname = ':'+o.skintone+':';
|
|
||||||
const emoji = unsafeHTML(xss.filterXSS(o.transform(shortname), {'whiteList': {'img': ['class', 'draggable' ,'alt', 'src', 'title']}}));
|
|
||||||
return html`
|
return html`
|
||||||
<li data-skintone="${o.skintone}" class="emoji-skintone ${(o.current_skintone === o.skintone) ? 'picked' : ''}">
|
<li data-skintone="${o.skintone}" class="emoji-skintone ${(o.current_skintone === o.skintone) ? 'picked' : ''}">
|
||||||
<a class="pick-skintone" href="#" data-skintone="${o.skintone}" @click=${o.onSkintonePicked}>${emoji}</a>
|
<a class="pick-skintone" href="#" data-skintone="${o.skintone}" @click=${o.onSkintonePicked}>${o.transform(':'+o.skintone+':')}</a>
|
||||||
</li>
|
</li>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user