Как выводить emoji на консоль в Node.js (в Windows)?
В Windows есть некоторые основные поддержки emoji в консоли, так что я могу получить монохромный глиф, если я ☕
, например, ☕
или 📜
. Я могу вывести строку из PowerShell или консольного приложения С# или Python, и все они достаточно хорошо отображают эти символы.
Однако, из Node.js, я могу получить только пару emoji для отображения (например, ☕
), но не другие (вместо 📜
я вижу
). Однако, если я throw
строку с этими символами, они отображаются правильно.
console.log(' 📜 ☕ ');
throw ' 📜 ☕ ';
Если я запустил вышеприведенный скрипт, вывод будет
� ☕
C:\Code\emojitest\emojitest.js:2
throw ' 📜 ☕ ';
^
📜 ☕
Есть ли в любом случае, что я могу правильно выводить эти emojis, не выдавая ошибки? Или это исключение происходит за пределами того, что доступно мне через стандартные API Node.js?
Ответы
Ответ 1
То, что вы хотите, может быть невозможно без изменения libuv. Когда вы (или консоль) записываете в stdout
или stderr
в Windows, а поток - TTY, libuv выполняет собственное преобразование с UTF-8 на UTF-16. При этом он явно отказывается выводить суррогатные пары, вместо этого U+FFFD
символ U+FFFD
для любого U+FFFD
за пределами BMP.
Heres виновник в 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;
}
Сообщение о throw
отображается правильно, потому что Node позволяет Windows выполнять преобразование из UTF-8 в UTF-16 с помощью MultiByteToWideChar()
(который испускает суррогатные пары) перед записью сообщения на консоль. (См. PrintErrorString()
в src/node.cc.)
Ответ 2
(Отказ от ответственности: у меня нет решения, я изучил, что делает специальную обработку исключений применительно к печати emoji, с инструментами, которые у меня есть на Windows 10 - С некоторой удачей, которая может немного рассказать о проблеме, и, возможно, кто-то будет признать что-то и придумать решение)
Похоже, что код отчетов об исключениях для узлов для Windows вызывает другой API Windows, который, оказывается, лучше поддерживает Unicode.
Давайте посмотрим с помощью источников Node 7.10:
ReportException → AppendExceptionLine → PrintErrorString
В PrintErrorString
раздел, PrintErrorString
Windows, определяет тип вывода (tty/console или нет): - для контекста non-tty/console он будет печатать на stderr
(например, если вы перенаправляетесь на файл) - в консоли cmd (без перенаправления), он преобразует текст с помощью MultiByteToWideChar()
а затем передаст это WriteConsoleW()
.
Если я запустил вашу программу с помощью ConEmu (проще, чем получить стандартное cmd
для работы с unicode и emoji - да, я немного здесь ленился), я вижу нечто похожее на то, что вы видели: console.log
не печатает emoji, но emoji в сообщении об исключении печатаются ОК (даже глиф прокрутки).
Если я перенаправляю весь вывод в файл (node test.js > out.txt 2>&1
, да, это тоже работает в Windows cmd), я получаю "чистый" Unicode в обоих случаях.
Так что, когда программа печатает на stdout
или stderr
в консоли Windows, консоль выполняет некоторую (плохую) перекодировку перед печатью. Когда программа напрямую использует консольный API Windows (выполнение самого преобразования с помощью MultiByteToWideChar
затем запись на консоль с помощью WriteConsoleW()
), консоль показывает славные неизмененные эможи.
Когда JS-программа использует console
API для записи материала, возможно, Node может попробовать (в Windows) обнаружить консоль и сделать то же самое, что и для отчетов об исключениях. См. Ответ @BrianNixon, в котором объясняется, что на самом деле происходит в libuv.
Ответ 3
Следующий " Терминал Windows " (от Кайлы Синнамон) и проект Microsoft/Terminal должны отображать смайлики.
Это будет доступно с июня 2019 года. Благодаря использованию шрифта Consolas будет обеспечена частичная поддержка Unicode.
Запрос находится в процессе выполнения в Microsoft/Terminal
387.
А выпуск Microsoft/Terminal 190 формально требует "добавить поддержку emoji в консоль Windows".
Но есть еще проблемы (март 2019):
Я обновил свой Win10 с 1803 до 1809 несколько дней назад, и теперь все символы> = U + 10000 (UTF-8 с 4 байтами или более) больше не отображаются.
Я также попробовал новейшую инсайдерскую версию (Windows 10 Insider Preview 18358.1 (19h1_release)), к сожалению, эта ошибка все еще существует.