Edited at

Node.js で絵文字を使う時の注意点

More than 3 years have passed since last update.

Node.js で絵文字を使った時に少し躓いたので


環境

$ node -v

v5.7.1


ダメな例

文字列に対して一文字ごとに操作したい場合、 charAtstr[i] で文字を取得したり、split("") で分離させたりすると思います。

しかし、絵文字が含まれていると結果がおかしくなります。


kuso.js

"use strict";

const emojiStr = "unko💩 うんこ";

// 一文字ごとに色を付けたい
const rainbow = [31, 32, 33, 34, 35, 36];
let rainbowPos = 0;

// 一文字ごとに切って色をつける
const colored = emojiStr.split("").map((c) => {
let n = rainbow[
(rainbow.length <= ++rainbowPos) ? (rainbowPos = 0) : rainbowPos
];
return `\x1b[${n}m${c}\x1b[39m`;
}).join("");

console.log(colored);


実行結果がこちら



最悪ですね。


punycode.ucs2.decode / encode を用いる

そこで、標準モジュールである punycode の punycode.ucs2.decode, punycode.ucs2.encode 関数を使用すると、絵文字を含む文字列をいい感じに操作することが可能になります。


iikannji.js

"use strict";

const punycode = require("punycode");

const emojiStr = "star🌠 星";

// 一文字ごとに色を付けたい
const rainbow = [31, 32, 33, 34, 35, 36];
let rainbowPos = 0;

// decode で文字列をコード化
const colored = punycode.ucs2.decode(emojiStr).map((code) => {

// コードから文字へ戻す
let c = punycode.ucs2.encode([code]);

let n = rainbow[
(rainbow.length <= ++rainbowPos) ? (rainbowPos = 0) : rainbowPos
];

return `\x1b[${n}m${c}\x1b[39m`;
}).join("");

console.log(colored);


実行結果がこちら



最高です。


まとめ

絵文字が含まれる文字列を操作する場合は punycode.ucs2.encode/decode を使用しましょう。

Array.from 使おう!(コメントより)