Au-delà des paires de substitution : les pièges cachés du comptage de caractères JS avec PHP/MySQL

DEV - 22/01
Lors du comptage des caractères en JavaScript, le problème de la paire de substitution (où les emoji et certains CJK...

Lors du comptage des caractères en JavaScript, le problème des paires de substitution (où les emoji et certains caractères CJK comptent pour 2) est assez connu. Vous avez probablement entendu des conseils du type « utilisez simplement[...str].longueur" pour le résoudre.

Cependant, lorsque j'ai implémenté un compteur de caractères pour une zone de texte sur le frontend, j'ai découvert qu'il existe d'autres causes d'inadéquation au-delà des paires de substitution. Cela s’est avéré plus profond que prévu, j’aimerais donc partager ce que j’ai appris. Il se peut que certaines choses se trompent, alors s'il vous plaît, prenez cela comme une référence plutôt que comme une vérité absolue.

Ce qui s'est passé

J'implémentais un compteur de caractères pour un. J'utilisais déjà[...str].longueurcomme contre-mesure de paire de substitution, mais celui de Laravelmaximumla validation rejetait toujours certaines entrées.

Après enquête, j'ai trouvé le coupable : la normalisation des nouvelles lignes.

Causes au-delà des paires de substitution

CauseCôté JSCôté PHP/MySQLDivergence
Emoji (paires de substitution)"🎉".longueur→ 2mb_strlen("🎉")→ 1JS compte plus
Normalisation de nouvelle ligne"a\nb".longueur→ 3Après HTTP :"a\r\nb"→ 4PHP compte plus
Mères porteuses solitairesDénombréErreur ou avertissement MySQLÉchec possible de la sauvegarde
Formulaire NFD (ancien macOS)"é".longueur→ 2mb_strlen("é")→ 2Correspond, mais involontairement 2 caractères

Les paires de substitution peuvent être gérées avec[...str].longueur, mais le problème de la nouvelle ligne n'est pas résolu par cela seul. Plus il y a de nouvelles lignes dans le texte, plus l'écart est important : par exemple, 10 nouvelles lignes signifient une différence de +10 caractères.

À propos de la normalisation des nouvelles lignes

C'est là que je suis resté le plus coincé.

Navigateur → Serveur

Lorsque vous soumettez le contenu d'unvia HTTP, les nouvelles lignes sont normalisées à partir de\nà\r\n.

Selon MDN, pourwrap="doux"(la valeur par défaut) :

le navigateur garantit que tous les sauts de ligne dans la valeur saisie sont une paire CR+LF

Le blog WHATWG explique également cela en détail : les nouvelles lignes sont normalisées au format CRLF lors de la soumission du formulaire, conformément aux spécifications.

// Dans le navigateur textarea.value // "a\nb\nc" → 5 caractères // Reçu par PHP $_POST['field'] // "a\r\nb\r\nc" → 7 caractères
Entrer en mode plein écran Quitter le mode plein écran

de Laravelmaximumutilisations des règlesmb_strlen(), il vérifie donc le nombre de caractères après la normalisation. C'est pourquoi les textes comportant de nombre...
[Courte citation de 8% de l'article original]

Loading...