Node.js で絵文字を使った時に少し躓いたので
環境
$ node -v
v5.7.1
ダメな例
文字列に対して一文字ごとに操作したい場合、 charAt
や str[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
使おう!(コメントより)