Mis disculpas si esto ya ha sido respondido aquí. No pude encontrar un hilo relevante.
Soy nuevo en JavaScript. Necesito poder truncar una cadena de una manera compatible con UTF8. Actualmente, al usar slice() y métodos similares, los caracteres multibyte al final de la cadena se cortan por la mitad y obtengo caracteres no válidos.
//Slicing Emojis var emojitext = "😊😊😊"; var chopped_emoji = emojitext.slice(0, 1); document.getElementById("slice").innerHTML = chopped_emoji + " is broken"; <p id="slice"></p> El código anterior da como resultado un carácter no válido almacenado en chopped_emoji . ¿Cómo me aseguro de que esto no suceda?
JS tiene una nueva API de segmentación para trabajar con caracteres de cadena. Dependiendo de la compatibilidad del navegador que necesite, podría ser una buena opción (también puede polillenarlo). Puede usarlo para crear una matriz de grafemas (es decir, las letras/unidades percibidas visualmente en la pantalla). Luego puede usar .slice() en esa matriz y luego .join() de nuevo en una cadena:
const str = "😊😊😊"; const segmenter = new Intl.Segmenter("en", {granularity: 'grapheme'}); const segItr = segmenter.segment(str); const segArr = Array.from(segItr, ({segment}) => segment); const choppedEmoji = segArr.slice(0, 1).join(''); // Examples console.log("With segmentation", choppedEmoji); console.log("Without segmentation", str.slice(0, 1)); Lo anterior se ocupa de muchos casos extremos, como pares sustitutos (emojis como 😊), caracteres con elementos de unión de ancho cero (para emojis como 👨👩👦), caracteres con selectores de variación (como ❤️) y pares compuestos caracteres (como ñ ).
Para caracteres más simples, puede usar Array.from() o la sintaxis extendida ( ... ) para convertir su cadena en una matriz agrupada por los puntos de código de su cadena (un emoji puede constar de múltiples unidades de código que codifican un solo código punto), de esta manera cuando se divide, puede evitar dividir en una de las unidades de código (lo que provoca el carácter de error):
const emojitext = "😊😊😊"; const choppedEmoji = [...emojitext].slice(0, 1).join(''); console.log(choppedEmoji + " is not broken :)"); Pero si arrojas algo como 👨👩👦 en el ejemplo anterior, encontrarás que no funciona como se esperaba, ya que 👨👩👦 es un grafema que consta de varios puntos de código unidos por un ancho cero caracteres de unión, por lo que el enfoque anterior no funcionará con él, pero la opción del segmentador sí lo hará (lo mismo con los caracteres que consisten en selectores de variación y caracteres compuestos).