From ed692691cde3fdcf483f0b8cb065adfcee4e58a2 Mon Sep 17 00:00:00 2001 From: Kevin Aleman Date: Mon, 9 Dec 2024 12:45:36 -0600 Subject: [PATCH] fix: Ignore mention-like text inside Markdown links (#34127) --- .changeset/six-snails-study.md | 5 ++ .../meteor/app/mentions/lib/MentionsParser.ts | 10 +++- .../tests/unit/app/mentions/server.tests.js | 60 +++++++++++++++++++ 3 files changed, 73 insertions(+), 2 deletions(-) create mode 100644 .changeset/six-snails-study.md diff --git a/.changeset/six-snails-study.md b/.changeset/six-snails-study.md new file mode 100644 index 000000000000..331bfacbbec1 --- /dev/null +++ b/.changeset/six-snails-study.md @@ -0,0 +1,5 @@ +--- +"@rocket.chat/meteor": patch +--- + +Fixes a behavior of the mentions parser that identified mentions inside markdown links text. Now, these components will be removed from the text before trying to parse mentions. diff --git a/apps/meteor/app/mentions/lib/MentionsParser.ts b/apps/meteor/app/mentions/lib/MentionsParser.ts index c4180eecf845..7a600c7d5636 100644 --- a/apps/meteor/app/mentions/lib/MentionsParser.ts +++ b/apps/meteor/app/mentions/lib/MentionsParser.ts @@ -119,11 +119,17 @@ export class MentionsParser { return this.roomTemplate({ prefix, reference, channel, mention }); }); - getUserMentions(str: string) { + getUserMentions(msg: string) { + // First remove the text inside md links + const str = msg.replace(/\[[^\]]*\]\([^)]+\)/g, ''); + // Then do the match return (str.match(this.userMentionRegex) || []).map((match) => match.trim()); } - getChannelMentions(str: string) { + getChannelMentions(msg: string) { + // First remove the text inside md links + const str = msg.replace(/\[[^\]]*\]\([^)]+\)/g, ''); + // Then do the match return (str.match(this.channelMentionRegex) || []).map((match) => match.trim()); } diff --git a/apps/meteor/tests/unit/app/mentions/server.tests.js b/apps/meteor/tests/unit/app/mentions/server.tests.js index 335f72af491d..04064de7c3ca 100644 --- a/apps/meteor/tests/unit/app/mentions/server.tests.js +++ b/apps/meteor/tests/unit/app/mentions/server.tests.js @@ -224,4 +224,64 @@ describe('Mention Server', () => { expect(result).to.be.deep.equal(expected); }); }); + + describe('getUserMentions', () => { + describe('for message with only an md link', () => { + const result = []; + [ + '[@rocket.cat](https://rocket.chat)', + '[@rocket.cat](https://rocket.chat) hello', + '[@rocket.cat](https://rocket.chat) hello how are you?', + '[test](https://rocket.chat)', + ].forEach((text) => { + it(`should return "${JSON.stringify(result)}" from "${text}"`, () => { + expect(result).to.be.deep.equal(mention.getUserMentions(text)); + }); + }); + }); + + describe('for message with md link and text', () => { + const result = ['@sauron']; + [ + '@sauron please work on [user@password](https://rocket.chat)', + '@sauron hello [user@password](https://rocket.chat) hello', + '[user@password](https://rocket.chat) hello @sauron', + '@sauron please work on [user@password](https://rocket.chat) hello', + ].forEach((text) => { + it(`should return "${JSON.stringify(result)}" from "${text}"`, () => { + expect(result).to.be.deep.equal(mention.getUserMentions(text)); + }); + }); + }); + }); + + describe('getChannelMentions', () => { + describe('for message with md link', () => { + const result = []; + [ + '[#general](https://rocket.chat)', + '[#general](https://rocket.chat) hello', + '[#general](https://rocket.chat) hello how are you?', + '[test #general #other](https://rocket.chat)', + ].forEach((text) => { + it(`should return "${JSON.stringify(result)}" from "${text}"`, () => { + expect(result).to.be.deep.equal(mention.getChannelMentions(text)); + }); + }); + }); + + describe('for message with md link and text', () => { + const result = ['#somechannel']; + [ + '#somechannel please [user#password](https://rocket.chat)', + '#somechannel hello [user#password](https://rocket.chat) hello', + '[user#password](https://rocket.chat) hello #somechannel', + '#somechannel join [#general on #other](https://rocket.chat)', + ].forEach((text) => { + it(`should return "${JSON.stringify(result)}" from "${text}"`, () => { + expect(result).to.be.deep.equal(mention.getChannelMentions(text)); + }); + }); + }); + }); });