diff --git a/test/client/unit/specs/libs/highlightUsers.js b/test/client/unit/specs/libs/highlightUsers.js index 4f1436708c..22d33564a7 100644 --- a/test/client/unit/specs/libs/highlightUsers.js +++ b/test/client/unit/specs/libs/highlightUsers.js @@ -3,9 +3,10 @@ import habiticaMarkdown from 'habitica-markdown'; describe('highlightUserAndEmail', () => { it('highlights displayname', () => { - const text = 'hello @displayedUser'; + const text = 'hello @displayedUser with text after'; const result = highlightUsers(text, 'user', 'displayedUser'); + expect(result).to.contain('@displayedUser'); }); @@ -16,17 +17,23 @@ describe('highlightUserAndEmail', () => { expect(result).to.contain('@user'); }); - it('highlights email with username', () => { - const text = habiticaMarkdown.render('hello hello@user.com'); + it('not highlights any email', () => { + const text = habiticaMarkdown.render('hello@example.com'); - const result = highlightUsers(text, 'user', 'displayedUser'); - expect(result).to.contain('>hello@user.com'); + const result = highlightUsers(text, 'example', 'displayedUser'); + expect(result).to.not.contain('@example'); }); - it('highlights any mention', () => { - const text = habiticaMarkdown.render('hello y.@user.com other words'); - const result = highlightUsers(text, 'test', 'displayedUser'); - expect(result).to.contain('@user'); + it('complex highlight', () => { + const plainText = 'a bit more @mentions to @use my@mentions.com broken.@mail.com'; + + const text = habiticaMarkdown.render(plainText); + + const result = highlightUsers(text, 'use', 'mentions'); + + expect(result).to.contain('@mentions'); + expect(result).to.contain('@use'); + expect(result).to.not.contain('@mentions.com'); }); }); diff --git a/website/client/libs/highlightUsers.js b/website/client/libs/highlightUsers.js index 5740577ca1..7a0daeace7 100644 --- a/website/client/libs/highlightUsers.js +++ b/website/client/libs/highlightUsers.js @@ -1,18 +1,24 @@ +import escapeRegExp from 'lodash/escapeRegExp'; + +const optionalAnchorTagRegExStr = '(<\\w[^>]*)?'; // everything including the anchor tag is recognized +const mentionRegExStr = '(@[\\w-]+)'; +const optionalPostMentionRegExStr = '(\\.\\w+)?'; // like dot-TLD + +const finalMentionRegEx = new RegExp(`${optionalAnchorTagRegExStr}${mentionRegExStr}${optionalPostMentionRegExStr}`, 'gi'); + export function highlightUsers (text, userName, displayName) { - const findAnyMentionRegex = '@[\\w-]+(?:\\b)'; + const currentUser = [`@${userName}`, `@${displayName}`].map(escapeRegExp); - const atRegex = new RegExp(`${findAnyMentionRegex}`, 'gi'); - const currentUser = [`@${userName}`, `@${displayName}`]; - if (atRegex.test(text)) { - text = text.replace(atRegex, match => { - if (currentUser.includes(match)) { - return `${match}`; - } + text = text.replace(finalMentionRegEx, (fullMatched, preMention, mentionStr, postMention) => { + if (preMention && preMention.includes('${match}`; - }); - } + const isUserMention = currentUser.includes(mentionStr) ? 'at-text' : ''; + + return fullMatched.replace(mentionStr, `${mentionStr}`); + }); return text; }