From 522caba420a837796b3190ee66ffc8f8f551515c Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Thu, 26 Feb 2026 17:20:04 +0200 Subject: [PATCH] Fix standard emoji not rendering as Discord-style images (#1488) Co-authored-by: Tyrrrz <1935960+Tyrrrz@users.noreply.github.com> Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> --- .../Discord/Data/EmojiIndex.cs | 2 + .../Markdown/Parsing/MarkdownParser.cs | 59 ++++--------------- 2 files changed, 14 insertions(+), 47 deletions(-) diff --git a/DiscordChatExporter.Core/Discord/Data/EmojiIndex.cs b/DiscordChatExporter.Core/Discord/Data/EmojiIndex.cs index 64be1efb..9fa229d8 100644 --- a/DiscordChatExporter.Core/Discord/Data/EmojiIndex.cs +++ b/DiscordChatExporter.Core/Discord/Data/EmojiIndex.cs @@ -8855,6 +8855,8 @@ internal static class EmojiIndex ["united_nations"] = "πŸ‡ΊπŸ‡³", }; + public static IReadOnlyCollection GetAllNames() => _toCodes.Keys; + public static string? TryGetCode(string name) => _toCodes.GetValueOrDefault(name); public static string? TryGetName(string code) => _fromCodes.GetValueOrDefault(code); diff --git a/DiscordChatExporter.Core/Markdown/Parsing/MarkdownParser.cs b/DiscordChatExporter.Core/Markdown/Parsing/MarkdownParser.cs index 9ff09469..c25c6395 100644 --- a/DiscordChatExporter.Core/Markdown/Parsing/MarkdownParser.cs +++ b/DiscordChatExporter.Core/Markdown/Parsing/MarkdownParser.cs @@ -208,53 +208,18 @@ internal static partial class MarkdownParser private static readonly IMatcher StandardEmojiNodeMatcher = new RegexMatcher( new Regex( - @"(" - + - // Country flag emoji (two regional indicator surrogate pairs) - @"(?:\uD83C[\uDDE6-\uDDFF]){2}|" - + - // Digit emoji (digit followed by enclosing mark) - @"\d\p{Me}|" - + - // Surrogate pair - @"\p{Cs}{2}|" - + - // Miscellaneous characters - @"[" - + @"\u2600-\u2604" - + @"\u260E\u2611" - + @"\u2614-\u2615" - + @"\u2618\u261D\u2620" - + @"\u2622-\u2623" - + @"\u2626\u262A" - + @"\u262E-\u262F" - + @"\u2638-\u263A" - + @"\u2640\u2642" - + @"\u2648-\u2653" - + @"\u265F-\u2660" - + @"\u2663" - + @"\u2665-\u2666" - + @"\u2668\u267B" - + @"\u267E-\u267F" - + @"\u2692-\u2697" - + @"\u2699" - + @"\u269B-\u269C" - + @"\u26A0-\u26A1" - + @"\u26A7" - + @"\u26AA-\u26AB" - + @"\u26B0-\u26B1" - + @"\u26BD-\u26BE" - + @"\u26C4-\u26C5" - + @"\u26C8" - + @"\u26CE-\u26CF" - + @"\u26D1" - + @"\u26D3-\u26D4" - + @"\u26E9-\u26EA" - + @"\u26F0-\u26F5" - + @"\u26F7-\u26FA" - + @"\u26FD" - + @"]" - + @")", + // Build a pattern from all known emoji, sorted longest-first so that compound + // emoji (e.g. sequences with ZWJ or skin-tone modifiers) are matched before + // their individual components. + "(" + + string.Join( + "|", + EmojiIndex + .GetAllNames() + .OrderByDescending(e => e.Length) + .Select(Regex.Escape) + ) + + ")", DefaultRegexOptions ), (_, _, m) => new EmojiNode(m.Groups[1].Value)