正则表达式匹配可以与肤色修饰符有效结合的表情符号?

Regex to match emojis that can be validly combined with skin tone modifiers?

检测表情符号(通常意义上的“表情符号”)的 JS 代码很简单:

let str = "...";
if(/\p{Extended_Pictographic}/u.test(str)) {
  // do something
}

是否有一些等效的简单方法来检测可以有效添加肤色修饰符的表情符号?

一个 关键要求 是我不必多年来随着更多表情符号的添加或现有表情符号的更新而更新正则表达式 skin-tone-able。基本上我想知道是否有类似 Skin Unicode 属性 转义,或其他一些优雅的 future-proof 解决方案。


备注:

您可以使用 Fitzpatrick scale 来检测 skin-toned 表情符号。具有肤色的表情符号将包含六个 Fitzpatrick 比例 unicode 中的任何一个。

编辑:

此解决方案使用 Element.getBoundingClientRect() 来确定表情符号在连接 Fitzpatrick 肤色表情符号后是否具有相同的宽度和高度。

function isEmojiSkinToneAdaptable(emoji) {
  const SKIN_TONES = [
    '\u{1f3fb}', // skin tone 1 & 2
    '\u{1f3fc}', // skin tone 3
    '\u{1f3fd}', // skin tone 4
    '\u{1f3fe}', // skin tone 5
    '\u{1f3ff}', // skin tone 6
  ];
  
  function getRemovedSkinToneEmoji(emoji) {
    let emojiCopy = ' '.concat(emoji).slice(1);
    SKIN_TONES.forEach(skinTone => {
      emojiCopy = emojiCopy.replace(skinTone, '');
    })
    return emojiCopy;
  }
  
  function getEmojiRects(emoji) {
    let span = document.createElement('span');
    span.style.position = 'fixed';
    span.style.top = '-99999px';
    span.textContent = emoji;
    document.body.append(span);
    let emojiRects = span.getBoundingClientRect();
    span.remove();
    return emojiRects;
  }

  let baseEmoji = getRemovedSkinToneEmoji(emoji);
  let skinToneEmoji = baseEmoji + SKIN_TONES[1];
  
  let baseEmojiRects = getEmojiRects(baseEmoji);
  let skinToneEmojiRects = getEmojiRects(skinToneEmoji);

  return baseEmojiRects.width === skinToneEmojiRects.width 
    && baseEmojiRects.height === skinToneEmojiRects.height;
}

console.log(`Human with skin tone: ${isEmojiSkinToneAdaptable('')}`); // true
console.log(`Thumbs up without skin tone: ${isEmojiSkinToneAdaptable('')}`); // true
console.log(`Animal: ${isEmojiSkinToneAdaptable('')}`); // false

相关的 Unicode 字符 属性 称为 Emoji_Modifier_Base/\p{Emoji_Modifier_Base}/u.test() 将 return 对于每个可以使用肤色修饰符的表情符号字符。