RocketChat/Rocket.Chat

View on GitHub
apps/meteor/app/emoji/client/emojiParser.js

Summary

Maintainability
A
2 hrs
Test Coverage
import { isIE11 } from '../../../client/lib/utils/isIE11';
import { emoji } from './lib';

/**
 * emojiParser is a function that will replace emojis
 * @param {{ html: string }} message - The message object
 * @return {{ html: string }}
 */
export const emojiParser = ({ html }) => {
    html = html.trim();

    // ' to apostrophe (') for emojis such as :')
    html = html.replace(/'/g, "'");

    // '<br>' to ' <br> ' for emojis such at line breaks
    html = html.replace(/<br>/g, ' <br> ');

    html = Object.entries(emoji.packages)
        .reverse()
        .reduce((value, [, emojiPackage]) => emojiPackage.render(value), html);

    const checkEmojiOnly = document.createElement('div');

    checkEmojiOnly.innerHTML = html;

    const emojis = Array.from(checkEmojiOnly.querySelectorAll('.emoji:not(:empty), .emojione:not(:empty)'));

    let hasText = false;

    if (!isIE11) {
        const filter = (node) => {
            if (node.nodeType === Node.ELEMENT_NODE && (node.classList.contains('emojione') || node.classList.contains('emoji'))) {
                return NodeFilter.FILTER_REJECT;
            }
            return NodeFilter.FILTER_ACCEPT;
        };

        const walker = document.createTreeWalker(checkEmojiOnly, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_TEXT, filter);

        while (walker.nextNode()) {
            if (walker.currentNode.nodeType === Node.TEXT_NODE && walker.currentNode.nodeValue.trim() !== '') {
                hasText = true;
                break;
            }
        }
        const emojiOnly = emojis.length && !hasText;

        if (emojiOnly) {
            for (let i = 0, len = emojis.length; i < len; i++) {
                const { classList } = emojis[i];
                classList.add('big');
            }
            html = checkEmojiOnly.innerHTML;
        }
    }

    // apostrophe (') back to &#39;
    html = html.replace(/\'/g, '&#39;');

    // line breaks ' <br> ' back to '<br>'
    html = html.replace(/ <br> /g, '<br>');

    return { html };
};