如何在 JS 中解析表情符号?
How to parse emojis in JS?
我在数据库中存储了一些纯字符串,其中包含一些表情符号,例如:
hello world
我需要这些表情符号更大一些。
所以结果应该是这样的:function parseEmoji(string)
hello <span class="emoji></span> world <span class="emoji></span>
知道如何检测和替换字符串中的表情符号吗?
The following EBNF can be used to quickly scan for possible emoji. Those possible emoji can then be verified where necessary by performing validity tests according to the definitions, or checking against the RGI emoji set. It is much simpler than the expressions currently in the definitions. It includes a superset of emoji as a by-product of that simplicity, but the extras can be weeded out by validity tests.
EBNF
Notes
possible_emoji :=
flag_sequence
| zwj_element (\x{200D} zwj_element)*
\x{200D} = zero-width joiner
flag_sequence :=
\p{RI} \p{RI}
\p{RI} = Regional_Indicator
zwj_element :=
\p{Emoji} emoji_modification?
emoji_modification :=
\p{EMod}
| \x{FE0F} \x{20E3}?
\p{EMod} = Emoji_Modifier
\x{FE0F} = emoji VS
\x{20E3} = enclosing keycap
tag_modifier :=
[\x{E0020}-\x{E007E}]+ \x{E007F}
\x{E00xx} are tags
\x{E007F} = TERM tag
From these EBNF rules a regex can be generated, as below. While this regex may seem complex, it is far simpler than what would result from the definitions. Direct use of the definitions would result in regex expressions which are many times more complicated, and yet still require verification with validity tests.
Regex
\p{RI} \p{RI}
| \p{Emoji}
( \p{EMod}
| \x{FE0F} \x{20E3}?
| [\x{E0020}-\x{E007E}]+ \x{E007F} )?
(\x{200D} \p{Emoji}
( \p{EMod}
| \x{FE0F} \x{20E3}?
| [\x{E0020}-\x{E007E}]+ \x{E007F} )?
)*
– Unicode® Technical Standard #51, Unicode Emoji, Section 1.4.9 EBNF and Regex
鉴于以上内容,可以推导出以下JavaScript兼容的正则表达式:
/\p{RI}\p{RI}|\p{Emoji}(\p{EMod}+|\u{FE0F}\u{20E3}?|[\u{E0020}-\u{E007E}]+\u{E007F})?(\u{200D}\p{Emoji}(\p{EMod}+|\u{FE0F}\u{20E3}?|[\u{E0020}-\u{E007E}]+\u{E007F})?)+|\p{EPres}(\p{EMod}+|\u{FE0F}\u{20E3}?|[\u{E0020}-\u{E007E}]+\u{E007F})?|\p{Emoji}(\p{EMod}+|\u{FE0F}\u{20E3}?|[\u{E0020}-\u{E007E}]+\u{E007F})/gu
上面的正则表达式与 string replace will allow us to replace the emoji with span tags wrapping the emoji. $&
配对插入匹配的子字符串(表情符号)。
'hello world '.replace(/\p{RI}\p{RI}|\p{Emoji}(\p{EMod}+|\u{FE0F}\u{20E3}?|[\u{E0020}-\u{E007E}]+\u{E007F})?(\u{200D}\p{Emoji}(\p{EMod}+|\u{FE0F}\u{20E3}?|[\u{E0020}-\u{E007E}]+\u{E007F})?)+|\p{EPres}(\p{EMod}+|\u{FE0F}\u{20E3}?|[\u{E0020}-\u{E007E}]+\u{E007F})?|\p{Emoji}(\p{EMod}+|\u{FE0F}\u{20E3}?|[\u{E0020}-\u{E007E}]+\u{E007F})/gu, '<span></span>')
如链接的技术标准中所述,此解决方案确实会匹配非表情符号的内容。我目前还没有弄清楚如何根据规范编写有效性测试,所以没有尝试过。您可能希望这样做或平衡误报的风险与弄清楚这一点所需的努力。
下面是一个演示,其中(很多)表情符号被一个 span 包裹着,该 span 的样式使其具有 1px 实心红色边框。
document.body.innerHTML = `☺️️☹️☠️❣️❤️❤️❤️️️️️️️✋✋✋✋✋✋✌️✌✌✌✌✌☝️☝☝☝☝☝✊✊✊✊✊✊✍️✍✍✍✍✍️♂️♂♂️♂♂️♂♂️♂♂️♂♂️♂♀️♀♀️♀♀️♀♀️♀♀️♀♀️♀♀️♀♀️♀♀️♀♀️♀♀️♀♀️♀♂️♂♂️♂♂️♂♂️♂♂️♂♂️♂♂️♂♂️♂♂️♂♂️♂♂️♂♂️♂♀️♀♀️♀♀️♀♀️♀♀️♀♀️♀♂️♂♂️♂♂️♂♂️♂♂️♂♂️♂♀️♀♀️♀♀️♀♀️♀♀️♀♀️♀♂️♂♂️♂♂️♂♂️♂♂️♂♂️♂♀️♀♀️♀♀️♀♀️♀♀️♀♀️♀♂️♂♂️♂♂️♂♂️♂♂️♂♂️♂♀️♀♀️♀♀️♀♀️♀♀️♀♀️♀♂️♂♂️♂♂️♂♂️♂♂️♂♂️♂♀️♀♀️♀♀️♀♀️♀♀️♀♀️♀♂️♂♂️♂♂️♂♂️♂♂️♂♂️♂♀️♀♀️♀♀️♀♀️♀♀️♀♀️♀♂️♂♂️♂♂️♂♂️♂♂️♂♂️♂♀️♀♀️♀♀️♀♀️♀♀️♀♀️♀♂️♂♂️♂♂️♂♂️♂♂️♂♂️♂♀️♀♀️♀♀️♀♀️♀♀️♀♀️♀♂️♂♂️♂♂️♂♂️♂♂️♂♂️♂♀️♀♀️♀♀️♀♀️♀♀️♀♀️♀♂️♂♂️♂♂️♂♂️♂♂️♂♂️♂♀️♀♀️♀♀️♀♀️♀♀️♀♀️♀⚕️⚕⚕️⚕⚕️⚕⚕️⚕⚕️⚕⚕️⚕⚕️⚕⚕️⚕⚕️⚕⚕️⚕⚕️⚕⚕️⚕⚕️⚕⚕️⚕⚕️⚕⚕️⚕⚕️⚕⚕️⚕⚖️⚖⚖️⚖⚖️⚖⚖️⚖⚖️⚖⚖️⚖⚖️⚖⚖️⚖⚖️⚖⚖️⚖⚖️⚖⚖️⚖⚖️⚖⚖️⚖⚖️⚖⚖️⚖⚖️⚖⚖️⚖✈️✈✈️✈✈️✈✈️✈✈️✈✈️✈✈️✈✈️✈✈️✈✈️✈✈️✈✈️✈✈️✈✈️✈✈️✈✈️✈✈️✈✈️✈♂️♂♂️♂♂️♂♂️♂♂️♂♂️♂♀️♀♀️♀♀️♀♀️♀♀️♀♀️♀️️♂️♂️♂♂️♂♂️♂♂️♂♂️♂️♀️♀️♀♀️♀♀️♀♀️♀♀️♀♂️♂♂️♂♂️♂♂️♂♂️♂♂️♂♀️♀♀️♀♀️♀♀️♀♀️♀♀️♀♂️♂♂️♂♂️♂♂️♂♂️♂♂️♂♀️♀♀️♀♀️♀♀️♀♀️♀♀️♀♂️♂♂️♂♂️♂♂️♂♂️♂♂️♂♀️♀♀️♀♀️♀♀️♀♀️♀♀️♀♂️♂♂️♂♂️♂♂️♂♂️♂♂️♂♀️♀♀️♀♀️♀♀️♀♀️♀♀️♀♂️♂♂️♂♂️♂♂️♂♂️♂♂️♂♀️♀♀️♀♀️♀♀️♀♀️♀♀️♀♂️♂♂️♂♂️♂♂️♂♂️♂♂️♂♀️♀♀️♀♀️♀♀️♀♀️♀♀️♀♂️♂♂️♂♂️♂♂️♂♂️♂♂️♂♀️♀♀️♀♀️♀♀️♀♀️♀♀️♀♂️♂♂️♂♂️♂♂️♂♂️♂♂️♂♀️♀♀️♀♀️♀♀️♀♀️♀♀️♀♂️♂♂️♂♂️♂♂️♂♂️♂♂️♂♀️♀♀️♀♀️♀♀️♀♀️♀♀️♀♂️♂♂️♂♂️♂♂️♂♂️♂♂️♂♀️♀♀️♀♀️♀♀️♀♀️♀♀️♀♂️♂♂️♂♂️♂♂️♂♂️♂♂️♂♀️♀♀️♀♀️♀♀️♀♀️♀♀️♀♂️♂♂️♂♂️♂♂️♂♂️♂♂️♂♀️♀♀️♀♀️♀♀️♀♀️♀♀️♀♂️♂♀️♀♂️♂♀️♀♂️♂♂️♂♂️♂♂️♂♂️♂♂️♂♀️♀♀️♀♀️♀♀️♀♀️♀♀️♀♂️♂♂️♂♂️♂♂️♂♂️♂♂️♂♀️♀♀️♀♀️♀♀️♀♀️♀♀️♀♂️♂♂️♂♂️♂♂️♂♂️♂♂️♂♀️♀♀️♀♀️♀♀️♀♀️♀♀️♀♂️♂♂️♂♂️♂♂️♂♂️♂♂️♂♀️♀♀️♀♀️♀♀️♀♀️♀♀️♀♂️♂♂️♂♂️♂♂️♂♂️♂♂️♂♀️♀♀️♀♀️♀♀️♀♀️♀♀️♀♂️♂♂️♂♂️♂♂️♂♂️♂♂️♂♀️♀♀️♀♀️♀♀️♀♀️♀♀️♀️♂️♂♀️♀♂️♂♂️♂♂️♂♂️♂♂️♂♂️♂♀️♀♀️♀♀️♀♀️♀♀️♀♀️♀♂️♂♂️♂♂️♂♂️♂♂️♂♂️♂♀️♀♀️♀♀️♀♀️♀♀️♀♀️♀⛷️️️♂️♂️♂♂️♂♂️♂♂️♂♂️♂️♀️♀️♀♀️♀♀️♀♀️♀♀️♀♂️♂♂️♂♂️♂♂️♂♂️♂♂️♂♀️♀♀️♀♀️♀♀️♀♀️♀♀️♀♂️♂♂️♂♂️♂♂️♂♂️♂♂️♂♀️♀♀️♀♀️♀♀️♀♀️♀♀️♀♂️♂♂️♂♂️♂♂️♂♂️♂♂️♂♀️♀♀️♀♀️♀♀️♀♀️♀♀️♀⛹️⛹⛹⛹⛹⛹⛹️♂️⛹♂️⛹♂⛹♂️⛹♂⛹♂️⛹♂⛹♂️⛹♂⛹♂️⛹♂⛹️♀️⛹♀️⛹♀⛹♀️⛹♀⛹♀️⛹♀⛹♀️⛹♀⛹♀️⛹♀️️♂️♂️♂♂️♂♂️♂♂️♂♂️♂️♀️♀️♀♀️♀♀️♀♀️♀♀️♀♂️♂♂️♂♂️♂♂️♂♂️♂♂️♂♀️♀♀️♀♀️♀♀️♀♀️♀♀️♀♂️♂♂️♂♂️♂♂️♂♂️♂♂️♂♀️♀♀️♀♀️♀♀️♀♀️♀♀️♀♂️♂♂️♂♂️♂♂️♂♂️♂♂️♂♀️♀♀️♀♀️♀♀️♀♀️♀♀️♀♂️♂♀️♀♂️♂♂️♂♂️♂♂️♂♂️♂♂️♂♀️♀♀️♀♀️♀♀️♀♀️♀♀️♀♂️♂♂️♂♂️♂♂️♂♂️♂♂️♂♀️♀♀️♀♀️♀♀️♀♀️♀♀️♀♂️♂♂️♂♂️♂♂️♂♂️♂♂️♂♀️♀♀️♀♀️♀♀️♀♀️♀♀️♀♂️♂♂️♂♂️♂♂️♂♂️♂♂️♂♀️♀♀️♀♀️♀♀️♀♀️♀♀️♀❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤️⬛️❄️❄️️️️☘️️☕️️️⛰️️️️️️️️️️️⛪⛩️⛲⛺️♨️️️️️️⛽⚓⛵️⛴️️✈️️️️⌛⏳⌚⏰⏱️⏲️️️☀️⭐☁️⛅⛈️️️️️️️️️️☂️☔⛱️⚡❄️☃️⛄☄️✨️️️⚽⚾⛳⛸️️♠️♥️♦️♣️♟️️️️⛑️️️️☎️️️⌨️️️️️️️️✉️️✏️✒️️️️️️️️️✂️️️️️⛏️⚒️️️⚔️️⚙️️⚖️⛓️⚗️️️⚰️⚱️♿⚠️⛔☢️☣️⬆️↗️➡️↘️⬇️↙️⬅️↖️↕️↔️↩️↪️⤴️⤵️⚛️️✡️☸️☯️✝️☦️☪️☮️♈♉♊♋♌♍♎♏♐♑♒♓⛎▶️⏩⏭️⏯️◀️⏪⏮️⏫⏬⏸️⏹️⏺️⏏️♀️♂️⚧️✖️➕➖➗♾️‼️⁉️❓❔❕❗〰️⚕️♻️⚜️⭕✅☑️✔️❌❎➰➿〽️✳️✴️❇️©️®️™️#️⃣*️⃣0️⃣1️⃣2️⃣3️⃣4️⃣5️⃣6️⃣7️⃣8️⃣9️⃣️️ℹ️Ⓜ️️️️️㊗️㊙️⚫⚪⬛⬜◼️◻️◾◽▪️▫️️️️⚧️☠️☠`.replace(/\p{RI}\p{RI}|\p{Emoji}(\p{EMod}+|\u{FE0F}\u{20E3}?|[\u{E0020}-\u{E007E}]+\u{E007F})?(\u{200D}\p{Emoji}(\p{EMod}+|\u{FE0F}\u{20E3}?|[\u{E0020}-\u{E007E}]+\u{E007F})?)+|\p{EPres}(\p{EMod}+|\u{FE0F}\u{20E3}?|[\u{E0020}-\u{E007E}]+\u{E007F})?|\p{Emoji}(\p{EMod}+|\u{FE0F}\u{20E3}?|[\u{E0020}-\u{E007E}]+\u{E007F})/gu, '<span>$&</span>');
span {
border: 1px solid red;
}
我在数据库中存储了一些纯字符串,其中包含一些表情符号,例如:
hello world
我需要这些表情符号更大一些。
所以结果应该是这样的:function parseEmoji(string)
hello <span class="emoji></span> world <span class="emoji></span>
知道如何检测和替换字符串中的表情符号吗?
The following EBNF can be used to quickly scan for possible emoji. Those possible emoji can then be verified where necessary by performing validity tests according to the definitions, or checking against the RGI emoji set. It is much simpler than the expressions currently in the definitions. It includes a superset of emoji as a by-product of that simplicity, but the extras can be weeded out by validity tests.
EBNF | Notes |
---|---|
possible_emoji := |
\x{200D} = zero-width joiner |
flag_sequence := |
\p{RI} = Regional_Indicator |
zwj_element := |
|
emoji_modification := |
\p{EMod} = Emoji_Modifier \x{FE0F} = emoji VS \x{20E3} = enclosing keycap |
tag_modifier := |
\x{E00xx} are tags \x{E007F} = TERM tag |
From these EBNF rules a regex can be generated, as below. While this regex may seem complex, it is far simpler than what would result from the definitions. Direct use of the definitions would result in regex expressions which are many times more complicated, and yet still require verification with validity tests.
Regex |
---|
\p{RI} \p{RI} |
– Unicode® Technical Standard #51, Unicode Emoji, Section 1.4.9 EBNF and Regex
鉴于以上内容,可以推导出以下JavaScript兼容的正则表达式:
/\p{RI}\p{RI}|\p{Emoji}(\p{EMod}+|\u{FE0F}\u{20E3}?|[\u{E0020}-\u{E007E}]+\u{E007F})?(\u{200D}\p{Emoji}(\p{EMod}+|\u{FE0F}\u{20E3}?|[\u{E0020}-\u{E007E}]+\u{E007F})?)+|\p{EPres}(\p{EMod}+|\u{FE0F}\u{20E3}?|[\u{E0020}-\u{E007E}]+\u{E007F})?|\p{Emoji}(\p{EMod}+|\u{FE0F}\u{20E3}?|[\u{E0020}-\u{E007E}]+\u{E007F})/gu
上面的正则表达式与 string replace will allow us to replace the emoji with span tags wrapping the emoji. $&
配对插入匹配的子字符串(表情符号)。
'hello world '.replace(/\p{RI}\p{RI}|\p{Emoji}(\p{EMod}+|\u{FE0F}\u{20E3}?|[\u{E0020}-\u{E007E}]+\u{E007F})?(\u{200D}\p{Emoji}(\p{EMod}+|\u{FE0F}\u{20E3}?|[\u{E0020}-\u{E007E}]+\u{E007F})?)+|\p{EPres}(\p{EMod}+|\u{FE0F}\u{20E3}?|[\u{E0020}-\u{E007E}]+\u{E007F})?|\p{Emoji}(\p{EMod}+|\u{FE0F}\u{20E3}?|[\u{E0020}-\u{E007E}]+\u{E007F})/gu, '<span></span>')
如链接的技术标准中所述,此解决方案确实会匹配非表情符号的内容。我目前还没有弄清楚如何根据规范编写有效性测试,所以没有尝试过。您可能希望这样做或平衡误报的风险与弄清楚这一点所需的努力。
下面是一个演示,其中(很多)表情符号被一个 span 包裹着,该 span 的样式使其具有 1px 实心红色边框。
document.body.innerHTML = `☺️️☹️☠️❣️❤️❤️❤️️️️️️️✋✋✋✋✋✋✌️✌✌✌✌✌☝️☝☝☝☝☝✊✊✊✊✊✊✍️✍✍✍✍✍️♂️♂♂️♂♂️♂♂️♂♂️♂♂️♂♀️♀♀️♀♀️♀♀️♀♀️♀♀️♀♀️♀♀️♀♀️♀♀️♀♀️♀♀️♀♂️♂♂️♂♂️♂♂️♂♂️♂♂️♂♂️♂♂️♂♂️♂♂️♂♂️♂♂️♂♀️♀♀️♀♀️♀♀️♀♀️♀♀️♀♂️♂♂️♂♂️♂♂️♂♂️♂♂️♂♀️♀♀️♀♀️♀♀️♀♀️♀♀️♀♂️♂♂️♂♂️♂♂️♂♂️♂♂️♂♀️♀♀️♀♀️♀♀️♀♀️♀♀️♀♂️♂♂️♂♂️♂♂️♂♂️♂♂️♂♀️♀♀️♀♀️♀♀️♀♀️♀♀️♀♂️♂♂️♂♂️♂♂️♂♂️♂♂️♂♀️♀♀️♀♀️♀♀️♀♀️♀♀️♀♂️♂♂️♂♂️♂♂️♂♂️♂♂️♂♀️♀♀️♀♀️♀♀️♀♀️♀♀️♀♂️♂♂️♂♂️♂♂️♂♂️♂♂️♂♀️♀♀️♀♀️♀♀️♀♀️♀♀️♀♂️♂♂️♂♂️♂♂️♂♂️♂♂️♂♀️♀♀️♀♀️♀♀️♀♀️♀♀️♀♂️♂♂️♂♂️♂♂️♂♂️♂♂️♂♀️♀♀️♀♀️♀♀️♀♀️♀♀️♀♂️♂♂️♂♂️♂♂️♂♂️♂♂️♂♀️♀♀️♀♀️♀♀️♀♀️♀♀️♀⚕️⚕⚕️⚕⚕️⚕⚕️⚕⚕️⚕⚕️⚕⚕️⚕⚕️⚕⚕️⚕⚕️⚕⚕️⚕⚕️⚕⚕️⚕⚕️⚕⚕️⚕⚕️⚕⚕️⚕⚕️⚕⚖️⚖⚖️⚖⚖️⚖⚖️⚖⚖️⚖⚖️⚖⚖️⚖⚖️⚖⚖️⚖⚖️⚖⚖️⚖⚖️⚖⚖️⚖⚖️⚖⚖️⚖⚖️⚖⚖️⚖⚖️⚖✈️✈✈️✈✈️✈✈️✈✈️✈✈️✈✈️✈✈️✈✈️✈✈️✈✈️✈✈️✈✈️✈✈️✈✈️✈✈️✈✈️✈✈️✈♂️♂♂️♂♂️♂♂️♂♂️♂♂️♂♀️♀♀️♀♀️♀♀️♀♀️♀♀️♀️️♂️♂️♂♂️♂♂️♂♂️♂♂️♂️♀️♀️♀♀️♀♀️♀♀️♀♀️♀♂️♂♂️♂♂️♂♂️♂♂️♂♂️♂♀️♀♀️♀♀️♀♀️♀♀️♀♀️♀♂️♂♂️♂♂️♂♂️♂♂️♂♂️♂♀️♀♀️♀♀️♀♀️♀♀️♀♀️♀♂️♂♂️♂♂️♂♂️♂♂️♂♂️♂♀️♀♀️♀♀️♀♀️♀♀️♀♀️♀♂️♂♂️♂♂️♂♂️♂♂️♂♂️♂♀️♀♀️♀♀️♀♀️♀♀️♀♀️♀♂️♂♂️♂♂️♂♂️♂♂️♂♂️♂♀️♀♀️♀♀️♀♀️♀♀️♀♀️♀♂️♂♂️♂♂️♂♂️♂♂️♂♂️♂♀️♀♀️♀♀️♀♀️♀♀️♀♀️♀♂️♂♂️♂♂️♂♂️♂♂️♂♂️♂♀️♀♀️♀♀️♀♀️♀♀️♀♀️♀♂️♂♂️♂♂️♂♂️♂♂️♂♂️♂♀️♀♀️♀♀️♀♀️♀♀️♀♀️♀♂️♂♂️♂♂️♂♂️♂♂️♂♂️♂♀️♀♀️♀♀️♀♀️♀♀️♀♀️♀♂️♂♂️♂♂️♂♂️♂♂️♂♂️♂♀️♀♀️♀♀️♀♀️♀♀️♀♀️♀♂️♂♂️♂♂️♂♂️♂♂️♂♂️♂♀️♀♀️♀♀️♀♀️♀♀️♀♀️♀♂️♂♂️♂♂️♂♂️♂♂️♂♂️♂♀️♀♀️♀♀️♀♀️♀♀️♀♀️♀♂️♂♀️♀♂️♂♀️♀♂️♂♂️♂♂️♂♂️♂♂️♂♂️♂♀️♀♀️♀♀️♀♀️♀♀️♀♀️♀♂️♂♂️♂♂️♂♂️♂♂️♂♂️♂♀️♀♀️♀♀️♀♀️♀♀️♀♀️♀♂️♂♂️♂♂️♂♂️♂♂️♂♂️♂♀️♀♀️♀♀️♀♀️♀♀️♀♀️♀♂️♂♂️♂♂️♂♂️♂♂️♂♂️♂♀️♀♀️♀♀️♀♀️♀♀️♀♀️♀♂️♂♂️♂♂️♂♂️♂♂️♂♂️♂♀️♀♀️♀♀️♀♀️♀♀️♀♀️♀♂️♂♂️♂♂️♂♂️♂♂️♂♂️♂♀️♀♀️♀♀️♀♀️♀♀️♀♀️♀️♂️♂♀️♀♂️♂♂️♂♂️♂♂️♂♂️♂♂️♂♀️♀♀️♀♀️♀♀️♀♀️♀♀️♀♂️♂♂️♂♂️♂♂️♂♂️♂♂️♂♀️♀♀️♀♀️♀♀️♀♀️♀♀️♀⛷️️️♂️♂️♂♂️♂♂️♂♂️♂♂️♂️♀️♀️♀♀️♀♀️♀♀️♀♀️♀♂️♂♂️♂♂️♂♂️♂♂️♂♂️♂♀️♀♀️♀♀️♀♀️♀♀️♀♀️♀♂️♂♂️♂♂️♂♂️♂♂️♂♂️♂♀️♀♀️♀♀️♀♀️♀♀️♀♀️♀♂️♂♂️♂♂️♂♂️♂♂️♂♂️♂♀️♀♀️♀♀️♀♀️♀♀️♀♀️♀⛹️⛹⛹⛹⛹⛹⛹️♂️⛹♂️⛹♂⛹♂️⛹♂⛹♂️⛹♂⛹♂️⛹♂⛹♂️⛹♂⛹️♀️⛹♀️⛹♀⛹♀️⛹♀⛹♀️⛹♀⛹♀️⛹♀⛹♀️⛹♀️️♂️♂️♂♂️♂♂️♂♂️♂♂️♂️♀️♀️♀♀️♀♀️♀♀️♀♀️♀♂️♂♂️♂♂️♂♂️♂♂️♂♂️♂♀️♀♀️♀♀️♀♀️♀♀️♀♀️♀♂️♂♂️♂♂️♂♂️♂♂️♂♂️♂♀️♀♀️♀♀️♀♀️♀♀️♀♀️♀♂️♂♂️♂♂️♂♂️♂♂️♂♂️♂♀️♀♀️♀♀️♀♀️♀♀️♀♀️♀♂️♂♀️♀♂️♂♂️♂♂️♂♂️♂♂️♂♂️♂♀️♀♀️♀♀️♀♀️♀♀️♀♀️♀♂️♂♂️♂♂️♂♂️♂♂️♂♂️♂♀️♀♀️♀♀️♀♀️♀♀️♀♀️♀♂️♂♂️♂♂️♂♂️♂♂️♂♂️♂♀️♀♀️♀♀️♀♀️♀♀️♀♀️♀♂️♂♂️♂♂️♂♂️♂♂️♂♂️♂♀️♀♀️♀♀️♀♀️♀♀️♀♀️♀❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤❤️❤️⬛️❄️❄️️️️☘️️☕️️️⛰️️️️️️️️️️️⛪⛩️⛲⛺️♨️️️️️️⛽⚓⛵️⛴️️✈️️️️⌛⏳⌚⏰⏱️⏲️️️☀️⭐☁️⛅⛈️️️️️️️️️️☂️☔⛱️⚡❄️☃️⛄☄️✨️️️⚽⚾⛳⛸️️♠️♥️♦️♣️♟️️️️⛑️️️️☎️️️⌨️️️️️️️️✉️️✏️✒️️️️️️️️️✂️️️️️⛏️⚒️️️⚔️️⚙️️⚖️⛓️⚗️️️⚰️⚱️♿⚠️⛔☢️☣️⬆️↗️➡️↘️⬇️↙️⬅️↖️↕️↔️↩️↪️⤴️⤵️⚛️️✡️☸️☯️✝️☦️☪️☮️♈♉♊♋♌♍♎♏♐♑♒♓⛎▶️⏩⏭️⏯️◀️⏪⏮️⏫⏬⏸️⏹️⏺️⏏️♀️♂️⚧️✖️➕➖➗♾️‼️⁉️❓❔❕❗〰️⚕️♻️⚜️⭕✅☑️✔️❌❎➰➿〽️✳️✴️❇️©️®️™️#️⃣*️⃣0️⃣1️⃣2️⃣3️⃣4️⃣5️⃣6️⃣7️⃣8️⃣9️⃣️️ℹ️Ⓜ️️️️️㊗️㊙️⚫⚪⬛⬜◼️◻️◾◽▪️▫️️️️⚧️☠️☠`.replace(/\p{RI}\p{RI}|\p{Emoji}(\p{EMod}+|\u{FE0F}\u{20E3}?|[\u{E0020}-\u{E007E}]+\u{E007F})?(\u{200D}\p{Emoji}(\p{EMod}+|\u{FE0F}\u{20E3}?|[\u{E0020}-\u{E007E}]+\u{E007F})?)+|\p{EPres}(\p{EMod}+|\u{FE0F}\u{20E3}?|[\u{E0020}-\u{E007E}]+\u{E007F})?|\p{Emoji}(\p{EMod}+|\u{FE0F}\u{20E3}?|[\u{E0020}-\u{E007E}]+\u{E007F})/gu, '<span>$&</span>');
span {
border: 1px solid red;
}