diff --git a/app/assets/javascripts/discourse/tests/acceptance/admin-watched-words-test.js b/app/assets/javascripts/discourse/tests/acceptance/admin-watched-words-test.js index 532e79904b7..ae17562d630 100644 --- a/app/assets/javascripts/discourse/tests/acceptance/admin-watched-words-test.js +++ b/app/assets/javascripts/discourse/tests/acceptance/admin-watched-words-test.js @@ -138,6 +138,33 @@ acceptance("Admin - Watched Words", function (needs) { }); }); +acceptance("Admin - Watched Words - Emoji Replacement", function (needs) { + needs.user(); + needs.site({ + watched_words_replace: { + "(?:\\W|^)(betis)(?=\\W|$)": { + replacement: ":poop:", + case_sensitive: false, + }, + }, + }); + + test("emoji renders successfully after replacement", async function (assert) { + await visit("/t/internationalization-localization/280"); + await click("button.reply-to-post"); + await fillIn(".d-editor-input", "betis betis betis"); + const cooked = query(".d-editor-preview p"); + const cookedChildren = Array.from(cooked.children); + const emojis = cookedChildren.filter((child) => child.nodeName === "IMG"); + assert.strictEqual(emojis.length, 3, "three emojis have been rendered"); + assert.strictEqual( + emojis.every((emoji) => emoji.title === ":poop:"), + true, + "all emojis are :poop:" + ); + }); +}); + acceptance("Admin - Watched Words - Bad regular expressions", function (needs) { needs.user(); needs.pretender((server, helper) => { diff --git a/app/assets/javascripts/pretty-text/engines/discourse-markdown/emoji.js b/app/assets/javascripts/pretty-text/engines/discourse-markdown/emoji.js index df735a5fd1c..ce7f619e94b 100644 --- a/app/assets/javascripts/pretty-text/engines/discourse-markdown/emoji.js +++ b/app/assets/javascripts/pretty-text/engines/discourse-markdown/emoji.js @@ -195,7 +195,8 @@ function applyEmoji( emojiUnicodeReplacer, enableShortcuts, inlineEmoji, - customEmojiTranslation + customEmojiTranslation, + watchedWordsReplacer ) { let result = null; let start = 0; @@ -204,6 +205,25 @@ function applyEmoji( content = emojiUnicodeReplacer(content); } + if (watchedWordsReplacer) { + const watchedWordRegex = Object.keys(watchedWordsReplacer); + + watchedWordRegex.forEach((watchedWord) => { + if (content?.match(watchedWord)) { + const regex = new RegExp(watchedWord, "g"); + const matches = content.match(regex); + const replacement = watchedWordsReplacer[watchedWord].replacement; + + matches.forEach(() => { + const matchingRegex = regex.exec(content); + if (matchingRegex) { + content = content.replace(matchingRegex[1], replacement); + } + }); + } + }); + } + let end = content.length; for (let i = 0; i < content.length - 1; i++) { @@ -337,7 +357,8 @@ export function setup(helper) { md.options.discourse.emojiUnicodeReplacer, md.options.discourse.features.emojiShortcuts, md.options.discourse.features.inlineEmoji, - md.options.discourse.customEmojiTranslation + md.options.discourse.customEmojiTranslation, + md.options.discourse.watchedWordsReplace ) ) );