From 130ad9c35abc1b7439fd6e673901271365dccf10 Mon Sep 17 00:00:00 2001 From: RoyceDa Date: Wed, 8 Apr 2026 22:58:49 +0200 Subject: [PATCH] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=BF=D0=B0=D1=80=D1=81=D0=B8=D0=BD?= =?UTF-8?q?=D0=B3=D0=B0=20emoji=20=D0=B8=20=D1=81=D0=BE=D1=81=D1=82=D0=B0?= =?UTF-8?q?=D0=B2=D0=BD=D1=8B=D1=85=20emoji=20(skin=20tones)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/components/TextParser/TextParser.tsx | 33 ++++++++++++++++++------ 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/app/components/TextParser/TextParser.tsx b/app/components/TextParser/TextParser.tsx index cf517b6..30fb3ca 100644 --- a/app/components/TextParser/TextParser.tsx +++ b/app/components/TextParser/TextParser.tsx @@ -42,6 +42,20 @@ export function TextParser(props: TextParserProps) { const theme = useMantineTheme(); let entityCount = 0; + const UNICODE_EMOJI_SEQUENCE_REGEX = + /(?:\p{Regional_Indicator}{2}|[0-9#*]\uFE0F?\u20E3|\p{Extended_Pictographic}(?:\uFE0F|\uFE0E)?(?:\p{Emoji_Modifier})?(?:\u200D\p{Extended_Pictographic}(?:\uFE0F|\uFE0E)?(?:\p{Emoji_Modifier})?)*)/u; + + const UNICODE_EMOJI_SEQUENCE_REGEX_GLOBAL = new RegExp( + UNICODE_EMOJI_SEQUENCE_REGEX.source, + "gu" + ); + + const toUnified = (value: string): string => + Array.from(value) + .map((ch) => ch.codePointAt(0)?.toString(16)) + .filter(Boolean) + .join("-"); + const formatRules : FormatRule[] = [ { pattern: [ @@ -120,18 +134,21 @@ export function TextParser(props: TextParserProps) { } }, { - // unicode emojis - pattern: [/\p{Emoji_Presentation}/u], + // unicode emojis (including composite sequences) + pattern: [UNICODE_EMOJI_SEQUENCE_REGEX], render: (match: string) => { - let textWithoutEmojis = props.text.replace(/\p{Emoji_Presentation}/gu, ''); - if(textWithoutEmojis.length <= (props.oversizeIfTextSmallerThan ?? 0)) { - return ; + const textWithoutEmojis = props.text.replace(UNICODE_EMOJI_SEQUENCE_REGEX_GLOBAL, ""); + const unified = toUnified(match); + + if (textWithoutEmojis.length <= (props.oversizeIfTextSmallerThan ?? 0)) { + return ; } - return ; + + return ; }, flush: (match: string) => { - return ; - } + return ; + } }, { // :emoji_code: