mirror of
https://github.com/HabitRPG/habitica.git
synced 2025-12-16 06:07:21 +01:00
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:
6
package-lock.json
generated
6
package-lock.json
generated
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
6
website/client/package-lock.json
generated
6
website/client/package-lock.json
generated
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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);
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
7
website/client/src/libs/renderWithMentions.js
Normal file
7
website/client/src/libs/renderWithMentions.js
Normal 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);
|
||||
}
|
||||
@@ -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');
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user