diff --git a/res/css/views/rooms/_EventTile.scss b/res/css/views/rooms/_EventTile.scss
index b077dc8bbc..51e7f16927 100644
--- a/res/css/views/rooms/_EventTile.scss
+++ b/res/css/views/rooms/_EventTile.scss
@@ -391,10 +391,9 @@ $left-gutter: 64px;
position: absolute;
}
-/* HACK to override line-height which is already marked important elsewhere */
-.mx_EventTile_bigEmoji.mx_EventTile_bigEmoji {
+.mx_EventTile_bigEmoji .mx_EventTile_Emoji {
font-size: 48px !important;
- line-height: 57px !important;
+ line-height: 57px;
}
.mx_EventTile_content .mx_EventTile_edited {
diff --git a/src/HtmlUtils.tsx b/src/HtmlUtils.tsx
index e50d868ef9..ca391fc300 100644
--- a/src/HtmlUtils.tsx
+++ b/src/HtmlUtils.tsx
@@ -22,6 +22,7 @@ import sanitizeHtml from 'sanitize-html';
import cheerio from 'cheerio';
import classNames from 'classnames';
import EMOJIBASE_REGEX from 'emojibase-regex';
+import { split } from 'lodash';
import katex from 'katex';
import { AllHtmlEntities } from 'html-entities';
import { IContent } from 'matrix-js-sdk/src/models/event';
@@ -402,6 +403,11 @@ export interface IOptsReturnString extends IOpts {
returnString: true;
}
+const emojiToHtmlSpan = (emoji: string) =>
+ `${emoji}`;
+const emojiToJsxSpan = (emoji: string, key: number) =>
+ { emoji };
+
/**
* Wraps emojis in to style them separately from the rest of message. Consecutive emojis (and modifiers) are wrapped
* in the same .
@@ -411,34 +417,27 @@ export interface IOptsReturnString extends IOpts {
* and plain text for everything else
*/
function formatEmojis(message: string, isHtmlMessage: boolean): (JSX.Element | string)[] {
- const emojiToSpan = isHtmlMessage ? (emoji: string) => `${emoji}` :
- (emoji: string, key: number) => { emoji };
+ const emojiToSpan = isHtmlMessage ? emojiToHtmlSpan : emojiToJsxSpan;
const result: (JSX.Element | string)[] = [];
let text = '';
- let emojis = '';
let key = 0;
- for (const char of message) {
- if (mightContainEmoji(char) || ZWJ_REGEX.test(char) || char === '\ufe0f') {
+
+ // We use lodash's grapheme splitter to avoid breaking apart compound emojis
+ for (const char of split(message, '')) {
+ if (mightContainEmoji(char)) {
if (text) {
result.push(text);
text = '';
}
- emojis += char;
+ result.push(emojiToSpan(char, key));
+ key++;
} else {
- if (emojis) {
- result.push(emojiToSpan(emojis, key));
- key++;
- emojis = '';
- }
text += char;
}
}
if (text) {
result.push(text);
}
- if (emojis) {
- result.push(emojiToSpan(emojis, key));
- }
return result;
}
@@ -574,7 +573,7 @@ export function bodyToHtml(content: IContent, highlights: string[], opts: IOpts
});
let emojiBodyElements: JSX.Element[];
- if (!isDisplayedWithHtml && bodyHasEmoji && !emojiBody) {
+ if (!isDisplayedWithHtml && bodyHasEmoji) {
emojiBodyElements = formatEmojis(strippedBody, false) as JSX.Element[];
}