La question est simple: j'ai une chaîne
str
, comment puis-je vérifier s'ilstr
y a un seul emoji et rien d'autre? De plus, je préférerais ne pas utiliser une autre bibliothèque.Match
"🍎"
,"⛹🏿♂️"
,"3️⃣"
mais pas"🍓a"
,"𝕒"
,"🍌🍀"
J'ai du mal à trouver une solution mais voici certaines choses que j'ai essayées jusqu'à présent:
Solution tentée 1 - Jouez sur les longueurs et l' ...
opérateur
J'ai appris que les emojis occupent plus d'un octet, certains occupent même 4 octets ou plus ... et nous pouvons le mesurer via la length
propriété de la chaîne :
console.log("🍎".length); // 2
console.log("🛡️".length); // 3
console.log("⛹🏿♂️".length); // 6
Ensuite, j'ai découvert que l' ...
opérateur prend cela en compte et sépare correctement les emojis dans le tableau - je pouvais alors voir la length
propriété du tableau résultant et détecter si elles étaient différentes.
str = "⛹🏿♂️";
if (str.length !== [...str].length) {
// is emoji?
} else {
// is not emoji
}
Mais cela ne vérifie pas les autres caractères multi-octets tels que 𝕡
dont la longueur est 2. De plus, certains emojis étaient toujours séparés dans un étrange.
Tentative Solution 2 - Regex, expressions régulières
Bien sûr, l'expression régulière serait une chose à étudier, mais je n'ai pas encore trouvé de solution viable.
Le regex de cette réponse\u00a9|\u00ae|[\u2000-\u3300]|\ud83c[\ud000-\udfff]|\ud83d[\ud000-\udfff]|\ud83e[\ud000-\udfff]
fonctionne parfaitement pour détecter si une chaîne a des emojis, mais appliqué à ma situation, cela produit beaucoup de problèmes. Voici mes tests:
Partie A - Sans début / fin de regex de chaîne ( ^
et $
)
- 2A.1
str.match(regex)
est très incohérent, il décompose certains emojis et certains autres inutilisables. Je ne vois pas de moyen de savoir s'il contient même des caractères non emoji ou s'il contient plus d'un emoji:
let regex = /(\u00a9|\u00ae|[\u2000-\u3300]|\ud83c[\ud000-\udfff]|\ud83d[\ud000-\udfff]|\ud83e[\ud000-\udfff])/;
console.log("5️⃣".match(regex)); // [ '⃣', '⃣', index: 2, input: '5️⃣' ]
console.log("💡".match(regex)); // [ '💡', '💡', index: 0, input: '💡' ]
console.log("🌡️🌡️".match(regex)); // [ '🌡', '🌡', index: 0, input: '🌡️🌡️' ]
console.log("a⛅".match(regex)); // [ '⛅', '⛅', index: 1, input: 'a⛅' ]
- 2A.2
regex.test(str)
renvoie true chaque fois qu'un emoji est inclus dans la chaîne, ce qui n'est pas le comportement que je recherche:
let regex = /(\u00a9|\u00ae|[\u2000-\u3300]|\ud83c[\ud000-\udfff]|\ud83d[\ud000-\udfff]|\ud83e[\ud000-\udfff])/;
console.log(regex.test("5️⃣")); // true - correct
console.log(regex.test("a")); // false - correct
console.log(regex.test("🌡️🌡️")); // true - should be false
console.log(regex.test("hello ⛅!")); // true - should be false
Partie B - Avec début / fin de l'expression rationnelle de chaîne ( ^
et $
)
- 2B.1
str.match(regex)
revientnull
sur certains emojis pour une raison quelconque. Je n'ai aucune idée pourquoi, mais je suppose que cela a une relation avec la raison pour laquellestr.match(regex)
ces émoticônes seraient décomposées dans la partie A:
let regex = /^(\u00a9|\u00ae|[\u2000-\u3300]|\ud83c[\ud000-\udfff]|\ud83d[\ud000-\udfff]|\ud83e[\ud000-\udfff])$/;
console.log("5️⃣".match(regex)); // null
console.log("💡".match(regex)); // [ '💡', '💡', index: 0, input: '💡' ]
console.log("🌡️".match(regex)); // null
console.log("⛅".match(regex)); // [ '⛅', '⛅', index: 1, input: 'a⛅' ]
console.log("🍌🍀".match(regex)); // null
- 2B.2
regex.test(str)
retournerafalse
sur les mêmes emojis où il retourneraitnull
surstr.match(regex)
:
let regex = /^(\u00a9|\u00ae|[\u2000-\u3300]|\ud83c[\ud000-\udfff]|\ud83d[\ud000-\udfff]|\ud83e[\ud000-\udfff])$/;
console.log(regex.test("5️⃣")); // false - should be true
console.log(regex.test("💡")); // true - correct
console.log(regex.test("🌡️")); // false - should be true
console.log(regex.test("⛅")); // true - correct
console.log(regex.test("🍌🍀")); // false - correct
Partie C - Autres expressions régulières
- J'ai trouvé celui-ci mais il donne des incohérences similaires, mais pas les mêmes
/(?:[\u2700-\u27bf]|(?:\ud83c[\udde6-\uddff]){2}|[\ud800-\udbff][\udc00-\udfff]|[\u0023-\u0039]\ufe0f?\u20e3|\u3299|\u3297|\u303d|\u3030|\u24c2|\ud83c[\udd70-\udd71]|\ud83c[\udd7e-\udd7f]|\ud83c\udd8e|\ud83c[\udd91-\udd9a]|\ud83c[\udde6-\uddff]|[\ud83c[\ude01\uddff]|\ud83c[\ude01-\ude02]|\ud83c\ude1a|\ud83c\ude2f|[\ud83c[\ude32\ude02]|\ud83c\ude1a|\ud83c\ude2f|\ud83c[\ude32-\ude3a]|[\ud83c[\ude50\ude3a]|\ud83c[\ude50-\ude51]|\u203c|\u2049|[\u25aa-\u25ab]|\u25b6|\u25c0|[\u25fb-\u25fe]|\u00a9|\u00ae|\u2122|\u2139|\ud83c\udc04|[\u2600-\u26FF]|\u2b05|\u2b06|\u2b07|\u2b1b|\u2b1c|\u2b50|\u2b55|\u231a|\u231b|\u2328|\u23cf|[\u23e9-\u23f3]|[\u23f8-\u23fa]|\ud83c\udccf|\u2934|\u2935|[\u2190-\u21ff])/g
:
let regex = /^(?:[\u2700-\u27bf]|(?:\ud83c[\udde6-\uddff]){2}|[\ud800-\udbff][\udc00-\udfff]|[\u0023-\u0039]\ufe0f?\u20e3|\u3299|\u3297|\u303d|\u3030|\u24c2|\ud83c[\udd70-\udd71]|\ud83c[\udd7e-\udd7f]|\ud83c\udd8e|\ud83c[\udd91-\udd9a]|\ud83c[\udde6-\uddff]|[\ud83c[\ude01\uddff]|\ud83c[\ude01-\ude02]|\ud83c\ude1a|\ud83c\ude2f|[\ud83c[\ude32\ude02]|\ud83c\ude1a|\ud83c\ude2f|\ud83c[\ude32-\ude3a]|[\ud83c[\ude50\ude3a]|\ud83c[\ude50-\ude51]|\u203c|\u2049|[\u25aa-\u25ab]|\u25b6|\u25c0|[\u25fb-\u25fe]|\u00a9|\u00ae|\u2122|\u2139|\ud83c\udc04|[\u2600-\u26FF]|\u2b05|\u2b06|\u2b07|\u2b1b|\u2b1c|\u2b50|\u2b55|\u231a|\u231b|\u2328|\u23cf|[\u23e9-\u23f3]|[\u23f8-\u23fa]|\ud83c\udccf|\u2934|\u2935|[\u2190-\u21ff])$/g
console.log(regex.test("5️⃣")); // true - correct
console.log(regex.test("💡")); // false - should be true
console.log(regex.test("🌡️")); // false - should be true
console.log(regex.test("⛅")); // true - correct
console.log(regex.test("🍌🍀")); // false - correct
- De plus, cela casse horriblement (deuxième changement de test basé sur le premier test?)
let regex = /^(?:[\u2700-\u27bf]|(?:\ud83c[\udde6-\uddff]){2}|[\ud800-\udbff][\udc00-\udfff]|[\u0023-\u0039]\ufe0f?\u20e3|\u3299|\u3297|\u303d|\u3030|\u24c2|\ud83c[\udd70-\udd71]|\ud83c[\udd7e-\udd7f]|\ud83c\udd8e|\ud83c[\udd91-\udd9a]|\ud83c[\udde6-\uddff]|[\ud83c[\ude01\uddff]|\ud83c[\ude01-\ude02]|\ud83c\ude1a|\ud83c\ude2f|[\ud83c[\ude32\ude02]|\ud83c\ude1a|\ud83c\ude2f|\ud83c[\ude32-\ude3a]|[\ud83c[\ude50\ude3a]|\ud83c[\ude50-\ude51]|\u203c|\u2049|[\u25aa-\u25ab]|\u25b6|\u25c0|[\u25fb-\u25fe]|\u00a9|\u00ae|\u2122|\u2139|\ud83c\udc04|[\u2600-\u26FF]|\u2b05|\u2b06|\u2b07|\u2b1b|\u2b1c|\u2b50|\u2b55|\u231a|\u231b|\u2328|\u23cf|[\u23e9-\u23f3]|[\u23f8-\u23fa]|\ud83c\udccf|\u2934|\u2935|[\u2190-\u21ff])$/g
console.log(regex.test("⛹🏿♂️")); // false
console.log(regex.test("⛅")); // true
let regex = /^(?:[\u2700-\u27bf]|(?:\ud83c[\udde6-\uddff]){2}|[\ud800-\udbff][\udc00-\udfff]|[\u0023-\u0039]\ufe0f?\u20e3|\u3299|\u3297|\u303d|\u3030|\u24c2|\ud83c[\udd70-\udd71]|\ud83c[\udd7e-\udd7f]|\ud83c\udd8e|\ud83c[\udd91-\udd9a]|\ud83c[\udde6-\uddff]|[\ud83c[\ude01\uddff]|\ud83c[\ude01-\ude02]|\ud83c\ude1a|\ud83c\ude2f|[\ud83c[\ude32\ude02]|\ud83c\ude1a|\ud83c\ude2f|\ud83c[\ude32-\ude3a]|[\ud83c[\ude50\ude3a]|\ud83c[\ude50-\ude51]|\u203c|\u2049|[\u25aa-\u25ab]|\u25b6|\u25c0|[\u25fb-\u25fe]|\u00a9|\u00ae|\u2122|\u2139|\ud83c\udc04|[\u2600-\u26FF]|\u2b05|\u2b06|\u2b07|\u2b1b|\u2b1c|\u2b50|\u2b55|\u231a|\u231b|\u2328|\u23cf|[\u23e9-\u23f3]|[\u23f8-\u23fa]|\ud83c\udccf|\u2934|\u2935|[\u2190-\u21ff])$/g;
console.log(regex.test("⛹")); // true
console.log(regex.test("⛅")); // false
Existe-t-il un moyen de contourner tout ce désordre emoji / unicode / regex? Les bibliothèques / API sont-elles le seul moyen? Comment font-ils?