Issue 12033 - Use version of habitica-markdown that includes mentions (#12089)

* Issue 12033 - Use version of habitica-markdown that includes mention plugin

Also fixes frontend parts of 11504 and 10924

* Issue 12033 - Reduce duplication in chatCard & messageCard

* Issue 12033 - Use habitica-markdown version 2.0.0

* Issue 12033 - Use new entry point and fix tests

* Issue 12033 - Rename renderMarkdown to renderWithMentions
This commit is contained in:
Bart Enkelaar
2020-05-09 20:04:14 +02:00
committed by GitHub
parent ef99943646
commit c218b8d56c
9 changed files with 44 additions and 67 deletions

6
package-lock.json generated
View File

@@ -7379,9 +7379,9 @@
}
},
"habitica-markdown": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/habitica-markdown/-/habitica-markdown-1.4.0.tgz",
"integrity": "sha512-hklG3eBILNbx/VxGeRxuk+/RiWWllcd5QLNv7Kvm2wGBRTeK9c3my2eusGuHXkwStEFGxjJD5e0iMO47cGPxYw==",
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/habitica-markdown/-/habitica-markdown-2.0.0.tgz",
"integrity": "sha512-70Kl/d7v1d2Rz6TFkQQ9hYcBYGAHnIPbRgS3PrW/dD/GGpN42q6gT3sCLsIpLqEXbN0EWjVscGs2qKWYLc6BMQ==",
"requires": {
"habitica-markdown-emoji": "1.2.4",
"markdown-it": "10.0.0",

View File

@@ -36,7 +36,7 @@
"gulp-imagemin": "^6.2.0",
"gulp-nodemon": "^2.5.0",
"gulp.spritesmith": "^6.9.0",
"habitica-markdown": "^1.4.0",
"habitica-markdown": "^2.0.0",
"helmet": "^3.22.0",
"image-size": "^0.8.3",
"in-app-purchase": "^1.11.3",

View File

@@ -11676,9 +11676,9 @@
}
},
"habitica-markdown": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/habitica-markdown/-/habitica-markdown-1.4.0.tgz",
"integrity": "sha512-hklG3eBILNbx/VxGeRxuk+/RiWWllcd5QLNv7Kvm2wGBRTeK9c3my2eusGuHXkwStEFGxjJD5e0iMO47cGPxYw==",
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/habitica-markdown/-/habitica-markdown-2.0.0.tgz",
"integrity": "sha512-70Kl/d7v1d2Rz6TFkQQ9hYcBYGAHnIPbRgS3PrW/dD/GGpN42q6gT3sCLsIpLqEXbN0EWjVscGs2qKWYLc6BMQ==",
"requires": {
"habitica-markdown-emoji": "1.2.4",
"markdown-it": "10.0.0",

View File

@@ -36,7 +36,7 @@
"eslint-config-habitrpg": "^6.2.0",
"eslint-plugin-mocha": "^5.3.0",
"eslint-plugin-vue": "^6.2.2",
"habitica-markdown": "^1.4.0",
"habitica-markdown": "^2.0.0",
"hellojs": "^1.18.4",
"inspectpack": "^4.4.0",
"intro.js": "^2.9.3",

View File

@@ -34,7 +34,7 @@
<div
ref="markdownContainer"
class="text"
v-html="atHighlight(parseMarkdown(msg.text))"
v-html="parseMarkdown(msg.text)"
></div>
<hr>
<div
@@ -201,7 +201,7 @@ import moment from 'moment';
import cloneDeep from 'lodash/cloneDeep';
import escapeRegExp from 'lodash/escapeRegExp';
import habiticaMarkdown from 'habitica-markdown';
import renderWithMentions from '@/libs/renderWithMentions';
import { mapState } from '@/libs/store';
import userLink from '../userLink';
@@ -210,7 +210,6 @@ import copyIcon from '@/assets/svg/copy.svg';
import likeIcon from '@/assets/svg/like.svg';
import likedIcon from '@/assets/svg/liked.svg';
import reportIcon from '@/assets/svg/report.svg';
import { highlightUsers } from '../../libs/highlightUsers';
import { CHAT_FLAG_LIMIT_FOR_HIDING, CHAT_FLAG_FROM_SHADOW_MUTE } from '@/../../common/script/constants';
export default {
@@ -341,12 +340,8 @@ export default {
chatId: message.id,
});
},
atHighlight (text) {
return highlightUsers(text, this.user.auth.local.username, this.user.profile.name);
},
parseMarkdown (text) {
if (!text) return null;
return habiticaMarkdown.render(String(text));
return renderWithMentions(text, this.user);
},
},
};

View File

@@ -21,7 +21,7 @@
</p>
<div
class="text"
v-html="atHighlight(parseMarkdown(msg.text))"
v-html="parseMarkdown(msg.text)"
></div>
<div
v-if="isMessageReported"
@@ -139,13 +139,12 @@
import axios from 'axios';
import moment from 'moment';
import habiticaMarkdown from 'habitica-markdown';
import renderWithMentions from '@/libs/renderWithMentions';
import { mapState } from '@/libs/store';
import userLink from '../userLink';
import deleteIcon from '@/assets/svg/delete.svg';
import reportIcon from '@/assets/svg/report.svg';
import { highlightUsers } from '../../libs/highlightUsers';
export default {
components: {
@@ -204,12 +203,8 @@ export default {
await axios.delete(`/api/v4/inbox/messages/${message.id}`);
},
atHighlight (text) {
return highlightUsers(text, this.user.auth.local.username, this.user.profile.name);
},
parseMarkdown (text) {
if (!text) return null;
return habiticaMarkdown.render(String(text));
return renderWithMentions(text, this.user);
},
},
};

View File

@@ -1,26 +0,0 @@
import escapeRegExp from 'lodash/escapeRegExp';
const optionalAnchorTagRegExStr = '(<\\w[^>]*)?'; // everything including the anchor tag is recognized
const mentionRegExStr = '(@(?:<(?:em|strong)>)?[\\w-]+(?:<\\/(?:em|strong)>)?)';
const optionalPostMentionRegExStr = '(\\.\\w+)?'; // like dot-TLD
const finalMentionRegEx = new RegExp(`${optionalAnchorTagRegExStr}${mentionRegExStr}${optionalPostMentionRegExStr}`, 'gi');
export function highlightUsers (text, userName, displayName) { // eslint-disable-line import/prefer-default-export, max-len
const currentUser = [`@${userName}`, `@${displayName}`].map(escapeRegExp);
text = text.replace(finalMentionRegEx, (fullMatched, preMention, mentionStr, postMention) => { // eslint-disable-line no-param-reassign, max-len
if ((preMention && preMention.includes('<a')) || Boolean(postMention)) {
return fullMatched;
}
let fixedStr = mentionStr.replace(/<\/?em>/g, '_');
fixedStr = fixedStr.replace(/<\/?strong>/g, '__');
const isUserMention = currentUser.includes(fixedStr) ? 'at-highlight' : '';
return fullMatched.replace(mentionStr, `<span class="at-text ${isUserMention}">${fixedStr}</span>`);
});
return text;
}

View File

@@ -0,0 +1,7 @@
import habiticaMarkdown from 'habitica-markdown/withMentions';
export default function renderWithMentions (text, user) {
if (!text) return null;
const env = { userName: user.auth.local.username, displayName: user.profile.name };
return habiticaMarkdown.render(String(text), env);
}

View File

@@ -1,11 +1,20 @@
import habiticaMarkdown from 'habitica-markdown';
import { highlightUsers } from '@/libs/highlightUsers';
import renderMarkdown from '@/libs/renderWithMentions';
describe('renderWithMentions', () => {
function user (name, displayName) {
return { auth: { local: { username: name } }, profile: { name: displayName } };
}
it('returns null if no text supplied', () => {
const result = renderMarkdown('', user('a', 'b'));
expect(result).to.be.null;
});
describe('highlightUserAndEmail', () => {
it('highlights displayname', () => {
const text = 'hello @displayedUser with text after';
const result = highlightUsers(text, 'user', 'displayedUser');
const result = renderMarkdown(text, user('user', 'displayedUser'));
expect(result).to.contain('<span class="at-text at-highlight">@displayedUser</span>');
});
@@ -13,45 +22,42 @@ describe('highlightUserAndEmail', () => {
it('highlights username', () => {
const text = 'hello @user';
const result = highlightUsers(text, 'user', 'displayedUser');
const result = renderMarkdown(text, user('user', 'displayedUser'));
expect(result).to.contain('<span class="at-text at-highlight">@user</span>');
});
it('highlights username sandwiched with underscores', () => {
const text = 'hello @<em>user</em>';
const text = 'hello @_user_';
const result = highlightUsers(text, '_user_', 'displayedUser');
const result = renderMarkdown(text, user('_user_', 'displayedUser'));
expect(result).to.contain('<span class="at-text at-highlight">@_user_</span>');
expect(result).to.not.contain('<em>');
expect(result).to.not.contain('</em>');
});
it('highlights username sandwiched with double underscores', () => {
const text = 'hello @<strong>user</strong>';
const text = 'hello @__user__';
const result = highlightUsers(text, 'diffUser', 'displayDiffUser');
const result = renderMarkdown(text, user('diffUser', 'displayDiffUser'));
expect(result).to.contain('<span class="at-text">@__user__</span>');
expect(result).to.not.contain('<strong>');
expect(result).to.not.contain('</strong>');
});
it('not highlights any email', () => {
const text = habiticaMarkdown.render('hello@example.com');
const result = renderMarkdown('hello@example.com', user('example', 'displayedUser'));
const result = highlightUsers(text, 'example', 'displayedUser');
expect(result).to.not.contain('<span class="at-highlight">@example</span>');
});
it('complex highlight', () => {
const plainText = 'a bit more @mentions to @use my@mentions.com broken.@mail.com';
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');
const result = renderMarkdown(plainText, user('use', 'mentions'));
expect(result).to.contain('<span class="at-text at-highlight">@mentions</span>');
expect(result).to.contain('<span class="at-text at-highlight">@use</span>');
expect(result).to.contain('<span class="at-text">@mail</span>');
expect(result).to.not.contain('<span class="at-text at-highlight">@mentions</span>.com');
});
});