diff --git a/frontend_tests/node_tests/alert_words.js b/frontend_tests/node_tests/alert_words.js index 341c11ad8d..08f4324d6e 100644 --- a/frontend_tests/node_tests/alert_words.js +++ b/frontend_tests/node_tests/alert_words.js @@ -3,7 +3,7 @@ add_dependencies({ }); set_global('page_params', { - alert_words: ['alertone', 'alerttwo', 'alertthree', 'al*rt.*s', '.+'], + alert_words: ['alertone', 'alerttwo', 'alertthree', 'al*rt.*s', '.+', 'emoji'], }); set_global('feature_flags', { @@ -41,7 +41,9 @@ var question_word_message = { sender_email: 'another@zulip.com', content: '

st var alert_domain_message = { sender_email: 'another@zulip.com', content: '

now with link www.alerttwo.us/foo/bar

', alerted: true }; - +// This test ensure we are not mucking up rendered HTML content. +var message_with_emoji = { sender_email: 'another@zulip.com', content: '

I :heart: emoji!

', + alerted: true }; (function test_notifications() { assert(!alert_words.notifies(regular_message)); @@ -52,6 +54,7 @@ var alert_domain_message = { sender_email: 'another@zulip.com', content: '

now assert(alert_words.notifies(multialert_message)); assert(alert_words.notifies(unsafe_word_message)); assert(alert_words.notifies(alert_domain_message)); + assert(alert_words.notifies(message_with_emoji)); }()); (function test_munging() { @@ -82,4 +85,7 @@ var alert_domain_message = { sender_email: 'another@zulip.com', content: '

now alert_words.process_message(alert_domain_message); assert.equal(alert_domain_message.content, '

now with link www.alerttwo.us/foo/bar

'); + + alert_words.process_message(message_with_emoji); + assert.equal(message_with_emoji.content, '

I :heart: emoji!

'); }()); diff --git a/static/js/alert_words.js b/static/js/alert_words.js index fb0bdc0dbb..fed423e0f4 100644 --- a/static/js/alert_words.js +++ b/static/js/alert_words.js @@ -13,9 +13,6 @@ function escape_user_regex(value) { return value.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&"); } -var find_href_backwards = /href=['"][\w:\/\.]+$/; -var find_title_backwards = /title=['"][\w:\/\.]+$/; - exports.process_message = function (message) { if (!exports.notifies(message)) { return; @@ -32,9 +29,16 @@ exports.process_message = function (message) { '(' + after_punctuation + ')' , 'ig'); message.content = message.content.replace(regex, function (match, before, word, after, offset, content) { - // Don't munge URL hrefs + // Logic for ensuring that we don't muck up rendered HTML. var pre_match = content.substring(0, offset); - if (find_href_backwards.exec(pre_match) || find_title_backwards.exec(pre_match)) { + // We want to find the position of the `<` and `>` only in the + // match and the string before it. So, don't include the last + // character of match in `check_string`. This covers the corner + // case when there is an alert word just before `<` or `>`. + var check_string = pre_match + match.substring(0, match.length - 1); + var in_tag = check_string.lastIndexOf('<') > check_string.lastIndexOf('>'); + // Matched word is inside a HTML tag so don't perform any highlighting. + if (in_tag === true) { return before + word + after; } return before + "" + word + "" + after;