Saltar al contenido

¿Cómo enviar emoji a la consola en Node.js (en Windows)?

Luego de de esta prolongada búsqueda de información dimos con la solución este contratiempo que presentan muchos usuarios. Te ofrecemos la solución y deseamos resultarte de gran ayuda.

Solución:

Lo que desea puede no ser posible sin un cambio en libuv. Cuando tú (o la consola) escribes en stdout o stderr en Windows y la transmisión es un TTY,
libuv hace su propia conversión de UTF‑8 a UTF‑16. Al hacerlo, se niega explícitamente a generar pares suplentes, emitiendo en su lugar el carácter de reemplazo
U+FFFD para cualquier punto de código más allá del BMP.

Aquí está el culpable en uv/src/win/tty.c:

  /* We wouldn't mind emitting utf-16 surrogate pairs. Too bad, the */
  /* windows console doesn't really support UTF-16, so just emit the */
  /* replacement character. */
  if (utf8_codepoint > 0xffff) 
    utf8_codepoint = UNICODE_REPLACEMENT_CHARACTER;
  

El throw El mensaje aparece correctamente porque Node permite que Windows realice la conversión de UTF‑8 a UTF‑16 con MultiByteToWideChar() (que emite pares sustitutos) antes de escribir el mensaje en la consola. (Ver
PrintErrorString() en src/node.cc.)

Nota: Se envió una solicitud de extracción para resolver este problema.

(Descargo de responsabilidad: no tengo una solución, exploré qué hace que el manejo de excepciones sea especial con respecto a la impresión de emoji, con las herramientas que tengo en Windows 10: con un poco de suerte, eso podría arrojar algo de luz sobre el problema, y ​​​​quizás alguien reconozca algo y encuentre una solución)

Parece que el código de informe de excepción de Node para llamadas de Windows a una API de Windows diferente, que resulta ser compatible con Unicode mejor.

Veamos con las fuentes de Node 7.10:

ReportException → AppendExceptionLine → PrintErrorString

En PrintErrorString, la sección específica de Windows detecta el tipo de salida (tty/consola o no): – Para el contexto que no es tty/consola, se imprimirá en stderr (por ejemplo, si redirige a un archivo): en una consola cmd (sin redirección), convertirá el texto con MultiByteToWideChar() y luego pasar eso a WriteConsoleW().

Si ejecuto su programa usando ConEmu (más fácil que obtener estándar cmd para trabajar con Unicode y emoji, sí, me dio un poco de pereza aquí), veo algo similar a lo que viste: console.log no puede imprimir emoji, pero los emoji en el mensaje de excepción se imprimen correctamente (incluso el glifo de desplazamiento).

Si redirijo toda la salida a un archivo (node test.js > out.txt 2>&1, sí, eso también funciona en Windows cmd), obtengo Unicode “limpio” en ambos casos.

Entonces parece que cuando un programa se imprime en stdout o stderr en una consola de Windows, la consola realiza algún (mal) trabajo de recodificación antes de imprimir. Cuando el programa usa la API de la consola de Windows directamente (haciendo la conversión en sí mismo con MultiByteToWideChar luego escribe en la consola con WriteConsoleW()), la consola muestra el glorioso emoji inalterado.

Cuando un programa JS usa console API para registrar cosas, tal vez Node podría intentar (en Windows) detectar la consola y hacer lo mismo que hace para informar excepciones. Vea la respuesta de @BrianNixon que explica lo que realmente está sucediendo en libuv.

Reseñas y puntuaciones

Recuerda dar visibilidad a esta sección si te ayudó.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *