}
[Fact]
+ public void ReplaceEmojiToImg_EmojiZWJSequenceTest()
+ {
+ // 複数の絵文字を U+200D (ZERO WIDTH JOINER) で繋げて表現する絵文字
+ var origText = "👨\u200D🎨"; // U+1F468 (MAN) + U+200D + U+1F3A8 (ARTIST PALETTE)
+
+ var result = EmojiFormatter.ReplaceEmojiToImg(origText);
+ var expected = "<img class=\"emoji\" src=\"https://twemoji.maxcdn.com/2/72x72/1f468-200d-1f3a8.png\" alt=\"👨\u200D🎨\" />";
+
+ Assert.Equal(expected, result);
+ }
+
+ [Fact]
+ public void ReplaceEmojiToImg_EmojiZWJSequenceWithVariationSelectorTest()
+ {
+ // 複数の絵文字を U+200D (ZERO WIDTH JOINER) で繋げて表現 + 異字体セレクタ U+FE0F を含む絵文字
+ // この場合は URL 生成時に異字体セレクタ U+FE0F を除去しない
+ var origText = "🏃\u200D♀\uFE0F"; // U+1F3C3 (RUNNER) + U+200D + U+2640 (FEMARE SIGN) + U+FE0F
+
+ var result = EmojiFormatter.ReplaceEmojiToImg(origText);
+ var expected = "<img class=\"emoji\" src=\"https://twemoji.maxcdn.com/2/72x72/1f3c3-200d-2640-fe0f.png\" alt=\"🏃\u200D♀\uFE0F\" />";
+
+ Assert.Equal(expected, result);
+ }
+
+ [Fact]
public void ReplaceEmojiToImg_NotEmojiTest()
{
var origText = "123ABC";
string input = m.Value;
string codes = "";
- // 異字体セレクタ U+FE0F (emoji style) は除去する
- input = input.Replace("\uFE0F", "");
+ // 異字体セレクタ U+FE0F (emoji style) は除去する (ZWJ を含まない場合のみ)
+ if (!input.Contains('\u200D'))
+ input = input.Replace("\uFE0F", "");
for (var i = 0; i < input.Length; i += char.IsSurrogatePair(input, i) ? 2 : 1)
{