[Perf] Message: Optimize emoji counting algorithm (#5028)
This commit is contained in:
parent
276a3dc355
commit
74689ba4fb
@ -1,11 +1,10 @@
|
|||||||
import twemojiRegex from '../../lib/twemojiRegex';
|
import EMOJI_REGEX from '../../lib/twemojiRegex';
|
||||||
import fixNonStandardEmoji from './fixNonStandardEmoji';
|
import fixNonStandardEmoji from './fixNonStandardEmoji';
|
||||||
|
|
||||||
const DETECT_UP_TO = 100;
|
const DETECT_UP_TO = 100;
|
||||||
const MAX_LENGTH = DETECT_UP_TO * 8; // Maximum 8 per one emoji.
|
const MAX_LENGTH = DETECT_UP_TO * 8; // Maximum 8 code points per one emoji.
|
||||||
const RE_EMOJI_ONLY = new RegExp(`^(?:${twemojiRegex.source})+$`, '');
|
|
||||||
|
|
||||||
const parseEmojiOnlyString = (text: string): number | false => {
|
export default function parseEmojiOnlyString(text: string): number | false {
|
||||||
const standardizedText = fixNonStandardEmoji(text);
|
const standardizedText = fixNonStandardEmoji(text);
|
||||||
const lines = standardizedText.split('\n');
|
const lines = standardizedText.split('\n');
|
||||||
const textWithoutNewlines = lines.join('');
|
const textWithoutNewlines = lines.join('');
|
||||||
@ -13,35 +12,43 @@ const parseEmojiOnlyString = (text: string): number | false => {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const isEmojiOnly = Boolean(textWithoutNewlines.match(RE_EMOJI_ONLY));
|
const totalCount = countIfEmojiOnly(textWithoutNewlines);
|
||||||
if (!isEmojiOnly) {
|
if (!totalCount || totalCount > DETECT_UP_TO) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const countPerLine = lines.map((line) => {
|
|
||||||
let emojiCount = 0;
|
|
||||||
while (twemojiRegex.exec(line)) {
|
|
||||||
emojiCount++;
|
|
||||||
|
|
||||||
if (emojiCount > DETECT_UP_TO) {
|
|
||||||
twemojiRegex.lastIndex = 0;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return emojiCount;
|
|
||||||
});
|
|
||||||
|
|
||||||
|
// Calculate max emoji count per column or line. Used in UI to determine the size of the emoji.
|
||||||
let max = lines.length;
|
let max = lines.length;
|
||||||
for (let i = 0; i < countPerLine.length; i++) {
|
for (const line of lines) {
|
||||||
if (countPerLine[i] === -1) {
|
const count = countIfEmojiOnly(line);
|
||||||
|
if (count === false) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (countPerLine[i] > max) {
|
if (count > max) {
|
||||||
max = countPerLine[i];
|
max = count;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return max;
|
return max;
|
||||||
};
|
}
|
||||||
|
|
||||||
export default parseEmojiOnlyString;
|
function countIfEmojiOnly(line: string): false | number {
|
||||||
|
const iterator = line.matchAll(EMOJI_REGEX);
|
||||||
|
let count = 0;
|
||||||
|
let currentIndex = 0;
|
||||||
|
|
||||||
|
for (const match of iterator) {
|
||||||
|
if (match.index !== currentIndex) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
count++;
|
||||||
|
currentIndex = match.index + match[0].length;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentIndex !== line.length) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user