diff --git a/package-lock.json b/package-lock.json index a36b231bbf..f609ebfe87 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13877,6 +13877,14 @@ "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.3.tgz", "integrity": "sha512-U15Q7MXTuZlrbymiz95PJpZxu8IlipAp4dtS3wOdgPXx3mqBnslrWU14kxfHB+Py/+2PVKSr37dMAgM2A4uArw==" }, + "is-builtin-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", + "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", + "requires": { + "builtin-modules": "^1.0.0" + } + }, "is-callable": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz", @@ -25708,6 +25716,11 @@ "punycode": "^1.4.1" } }, + "tributejs": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/tributejs/-/tributejs-3.4.0.tgz", + "integrity": "sha512-BWB2YvfKpa6hZgcP9hKN5/tH3P/Guspn4r+ePgwNpftnQwMb6GVWTUgBpkMtVXkR5dwLLcP/iW87i9C1mp21zQ==" + }, "trim-leading-lines": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/trim-leading-lines/-/trim-leading-lines-0.1.1.tgz", @@ -27112,6 +27125,11 @@ "resolved": "https://registry.npmjs.org/vue-template-es2015-compiler/-/vue-template-es2015-compiler-1.9.1.tgz", "integrity": "sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw==" }, + "vue-tribute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/vue-tribute/-/vue-tribute-1.0.1.tgz", + "integrity": "sha1-ThJfdoEjxUBd4izjQ4NqmaCVRz0=" + }, "vuedraggable": { "version": "2.23.1", "resolved": "https://registry.npmjs.org/vuedraggable/-/vuedraggable-2.23.1.tgz", diff --git a/test/api/unit/libs/highlightMentions.js b/test/api/unit/libs/highlightMentions.js new file mode 100644 index 0000000000..5adf9d29fb --- /dev/null +++ b/test/api/unit/libs/highlightMentions.js @@ -0,0 +1,64 @@ +import { + highlightMentions, +} from '../../../../website/server/libs/highlightMentions'; +import mongoose from 'mongoose'; + +describe('highlightMentions', () => { + beforeEach(() => { + const mockFind = { + select () { + return this; + }, + lean () { + return this; + }, + exec () { + return Promise.resolve([{ + auth: { local: { username: 'user' } }, _id: '111', + }, { auth: { local: { username: 'user2' } }, _id: '222', + }, { auth: { local: { username: 'user3' } }, _id: '333', + }, { auth: { local: { username: 'user-dash' } }, _id: '444', + }, { auth: { local: { username: 'user_underscore' } }, _id: '555', + }, + ]); + }, + }; + + sinon.stub(mongoose.Model, 'find').returns(mockFind); + }); + + afterEach(() => { + sinon.restore(); + }); + + it('doesn\'t change text without mentions', async () => { + let text = 'some chat text'; + let result = await highlightMentions(text); + expect(result[0]).to.equal(text); + }); + it('highlights existing users', async () => { + let text = '@user: message'; + let result = await highlightMentions(text); + expect(result[0]).to.equal('[@user](/profile/111): message'); + }); + it('highlights special characters', async () => { + let text = '@user-dash: message @user_underscore'; + let result = await highlightMentions(text); + expect(result[0]).to.equal('[@user-dash](/profile/444): message [@user_underscore](/profile/555)'); + }); + it('doesn\'t highlight nonexisting users', async () => { + let text = '@nouser message'; + let result = await highlightMentions(text); + expect(result[0]).to.equal('@nouser message'); + }); + it('highlights multiple existing users', async () => { + let text = '@user message (@user2) @user3 @user'; + let result = await highlightMentions(text); + expect(result[0]).to.equal('[@user](/profile/111) message ([@user2](/profile/222)) [@user3](/profile/333) [@user](/profile/111)'); + }); + it('doesn\'t highlight more than 5 users', async () => { + let text = '@user @user2 @user3 @user4 @user5 @user6'; + let result = await highlightMentions(text); + expect(result[0]).to.equal(text); + }); +}); diff --git a/website/client/components/chat/chatCard.vue b/website/client/components/chat/chatCard.vue index b4daaf2ef7..3224f653e2 100644 --- a/website/client/components/chat/chatCard.vue +++ b/website/client/components/chat/chatCard.vue @@ -9,7 +9,7 @@ div span.mr-1(v-if="msg.username") • span(v-b-tooltip="", :title="msg.timestamp | date") {{ msg.timestamp | timeAgo }}  span(v-if="msg.client && user.contributor.level >= 4") ({{ msg.client }}) - .text(v-html='atHighlight(parseMarkdown(msg.text))') + .text(v-html='atHighlight(parseMarkdown(msg.text))', ref='markdownContainer') .reported(v-if="isMessageReported && (inbox === true)") span(v-once) {{ $t('reportedMessage')}} br @@ -47,7 +47,6 @@ div