Implement backslash escaping for emoticons (#30101)

Co-authored-by: Ben Schumacher <ben.schumacher@mattermost.com>
Co-authored-by: Mattermost Build <build@mattermost.com>
Этот коммит содержится в:
Lucas van Beek
2025-04-11 21:35:21 +02:00
коммит произвёл GitHub
родитель f54acdf100
Коммит 698de05545
2 изменённых файлов: 30 добавлений и 18 удалений

Просмотреть файл

@@ -31,6 +31,11 @@ describe('Emoticons', () => {
expect(Emoticons.handleEmoticons(emoticon, new Map())).toEqual('$MM_EMOTICON0$');
});
});
Array.prototype.concat(...Object.values(emoticonPatterns)).forEach((emoticon) => {
test(`escaped text sequence '${emoticon}' should not be recognized as an emoticon`, () => {
expect(Emoticons.handleEmoticons('\\' + emoticon, new Map())).toEqual(emoticon);
});
});
// test various uses of emoticons
test('should replace emoticons with tokens', () => {

Просмотреть файл

@@ -5,24 +5,24 @@ import {formatWithRenderer} from './markdown';
import PlainRenderer from './markdown/plain_renderer';
export const emoticonPatterns: { [key: string]: RegExp } = {
slightly_smiling_face: /(^|\B)(:-?\))($|\B)/g, // :)
wink: /(^|\B)(;-?\))($|\B)/g, // ;)
open_mouth: /(^|\B)(:o)($|\b)/gi, // :o
scream: /(^|\B)(:-o)($|\b)/gi, // :-o
smirk: /(^|\B)(:-?])($|\B)/g, // :]
smile: /(^|\B)(:-?d)($|\b)/gi, // :D
stuck_out_tongue_closed_eyes: /(^|\b)(x-d)($|\b)/gi, // x-d
stuck_out_tongue: /(^|\B)(:-?p)($|\b)/gi, // :p
rage: /(^|\B)(:-?[[@])($|\B)/g, // :@
slightly_frowning_face: /(^|\B)(:-?\()($|\B)/g, // :(
cry: /(^|\B)(:[`']-?\(|:&#x27;\(|:&#39;\()($|\B)/g, // :`(
confused: /(^|\B)(:-?\/)($|\B)/g, // :/
confounded: /(^|\B)(:-?s)($|\b)/gi, // :s
neutral_face: /(^|\B)(:-?\|)($|\B)/g, // :|
flushed: /(^|\B)(:-?\$)($|\B)/g, // :$
mask: /(^|\B)(:-x)($|\b)/gi, // :-x
heart: /(^|\B)(<3|&lt;3)($|\b)/g, // <3
broken_heart: /(^|\B)(<\/3|&lt;\/3)($|\b)/g, // </3
slightly_smiling_face: /(^|\B)(\\?:-?\))($|\B)/g, // :)
wink: /(^|\B)(\\?;-?\))($|\B)/g, // ;)
open_mouth: /(^|\B)(\\?:o)($|\b)/gi, // :o
scream: /(^|\B)(\\?:-o)($|\b)/gi, // :-o
smirk: /(^|\B)(\\?:-?])($|\B)/g, // :]
smile: /(^|\B)(\\?:-?d)($|\b)/gi, // :D
stuck_out_tongue_closed_eyes: /(^|\b)(\\?x-d)($|\b)/gi, // x-d
stuck_out_tongue: /(^|\B)(\\?:-?p)($|\b)/gi, // :p
rage: /(^|\B)(\\?:-?[[@])($|\B)/g, // :@
slightly_frowning_face: /(^|\B)(\\?:-?\()($|\B)/g, // :(
cry: /(^|\B)(\\?:[`']-?\(|\\?:&#x27;\(|\\?:&#39;\()($|\B)/g, // :`(
confused: /(^|\B)(\\?:-?\/)($|\B)/g, // :/
confounded: /(^|\B)(\\?:-?s)($|\b)/gi, // :s
neutral_face: /(^|\B)(\\?:-?\|)($|\B)/g, // :|
flushed: /(^|\B)(\\?:-?\$)($|\B)/g, // :$
mask: /(^|\B)(\\?:-x)($|\b)/gi, // :-x
heart: /(^|\B)(\\?<3|\\?&lt;3)($|\b)/g, // <3
broken_heart: /(^|\B)(\\?<\/3|\\?&lt;\/3)($|\b)/g, // </3
};
export const EMOJI_PATTERN = /(:([a-zA-Z0-9_+-]+):)/g;
@@ -62,6 +62,13 @@ export function handleEmoticons(
const index = tokens.size;
const alias = `$MM_EMOTICON${index}$`;
// escape and ignore emoticons that are prefixed with a backslash
const escaped = matchText.startsWith('\\');
if (escaped) {
return prefix + matchText.substring(1);
}
tokens.set(alias, {
value: renderEmoji(name, matchText),
originalText: fullMatch,