diff --git a/src/utils/emojify-text.js b/src/utils/emojify-text.js
index 99977fc1..f6552e53 100644
--- a/src/utils/emojify-text.js
+++ b/src/utils/emojify-text.js
@@ -1,18 +1,55 @@
+const ESCAPE_REGEX = /[.*+?^${}()|[\]\\]/g;
+const HTML_ESCAPE_MAP = {
+ '&': '&',
+ '"': '"',
+ '<': '<',
+ '>': '>',
+};
+const HTML_ESCAPE_REGEX = /[&"<>]/g;
+
+function escapeRegex(str) {
+ return str.replace(ESCAPE_REGEX, '\\$&');
+}
+
+function escapeHTML(str) {
+ return str.replace(HTML_ESCAPE_REGEX, (char) => HTML_ESCAPE_MAP[char]);
+}
+
function emojifyText(text, emojis = []) {
if (!text) return '';
if (!emojis.length) return text;
- if (text.indexOf(':') === -1) return text;
- // Replace shortcodes in text with emoji
- // emojis = [{ shortcode: 'smile', url: 'https://example.com/emoji.png' }]
- emojis.forEach((emoji) => {
- const { shortcode, staticUrl, url } = emoji;
- text = text.replace(
- new RegExp(`:${shortcode}:`, 'g'),
- `
`,
- );
+ if (!text.includes(':')) return text;
+
+ // Deduplicate emojis by shortcode and filter out invalid entries
+ const emojiMap = new Map();
+ for (let i = 0; i < emojis.length; i++) {
+ const emoji = emojis[i];
+ if (emoji?.shortcode && emoji?.url) {
+ emojiMap.set(emoji.shortcode, emoji);
+ }
+ }
+
+ if (emojiMap.size === 0) return text;
+
+ const shortcodes = Array.from(emojiMap.keys());
+ const pattern = shortcodes.map((sc) => `:${escapeRegex(sc)}:`).join('|');
+ const regex = new RegExp(pattern, 'g');
+
+ return text.replace(regex, (match) => {
+ const shortcode = match.slice(1, -1);
+ const emoji = emojiMap.get(shortcode);
+
+ if (!emoji) return match;
+
+ const { staticUrl, url } = emoji;
+ const escapedShortcode = escapeHTML(match);
+
+ const sourceTag = staticUrl
+ ? ``
+ : '';
+
+ return `${sourceTag}
`;
});
- // console.log(text, emojis);
- return text;
}
export default emojifyText;