※この記事は1年以上前の記事です。
現在は状況が異なる可能性がありますのでご注意ください。
どうも。
気づけば、一年以上記事書いてなかった。
普通に死ぬほど忙しかった。
さて、表記の件だ。
面白いよね、絵文字って。
エンジニアにとっては、56したい存在だけどね。
DBに保存する情報や、印刷に回すデザイン情報などは特に、絵文字が入っていると、まず間違いなくバグるので、
非常に厄介な存在だ。
そして、その性質が故に、除去がとんでもなく難しいのでことさら56したくなる。
こればっかりはやってみた人間にしかわからない。
ってわけで、御託ここまで。
絵文字の完璧な除去になったのでは?
ってコードができたので、公開しようかと。
const ranges = [ '[\ud800-\ud8ff][\ud000-\udfff]', // 基本的な絵文字除去 '[\ud000-\udfff]{2,}', // サロゲートペアの二回以上の繰り返しがあった場合 '\ud7c9[\udc00-\udfff]', // 特定のシリーズ除去 '[0-9|*|#][\uFE0E-\uFE0F]\u20E3', // 数字系絵文字 '[0-9|*|#]\u20E3', // 数字系絵文字 '[©|®|\u2010-\u3fff][\uFE0E-\uFE0F]', // 環境依存文字や日本語との組み合わせによる絵文字 '[\u2010-\u2FFF]', // 指や手、物など、単体で絵文字となるもの '\uA4B3', // 数学記号の環境依存文字の除去 ]; const surrogatePairCode = [ 65038, 65039, 8205, 11093, 11035 ]; const removeEmoji = in_value => { const reg = new RegExp(ranges.join('|'), 'g'); let retValue = in_value.replace(reg, ''); // パターンにマッチする限り、除去を繰り返す(一回の正規表現除去では除去しきないパターンがあるため) while (retValue.match(reg)) { retValue = retValue.replace(reg, ''); } // 二重で絵文字チェック(4バイト、サロゲートペアの残りカス除外) return retValue.split('').reduce((p, c) => { const code = c.charCodeAt(0); if ( encodeURIComponent(v).replace(/%../g, 'x').length < 4 && !surrogatePairCode.some(codoNum => code == codeNum) ) { return p += c; } else { return p; } }, ''); } const target = document.getElementsByClassName('removeEmoji'); const bindFunc = function(){ this.value = removeEmoji(this.value); }; Array.prototype.forEach.call(target, el => { el.addEventListener('change', bindFunc); el.addEventListener('blur', bindFunc); });
ポイントは、
正規表現の部分と、サロゲートペアの残りカスの除去だ。
多くの絵文字除去の方法記事で採用されている、正規表現を簡潔にし、アップデートしている。
これにより、9割がたの除去がされる。
また、マッチする限り、繰り返し除去を行うことによって、さらに除去を進める。
そして、次に大事なのは、
サロゲートペアの残りカスの除去だ。
上記正規表現による除去では、除去しきれないのが、絵文字の厄介なところ。
4バイト以上の文字や、サロゲートペアの片割れが残る可能性がある。
(サロゲートペアとは、絵文字は二つ以上の文字コードを、一つの文字とすることによって表現されているものが大半。
そのペアのことを指す)
なので、4バイト以上の文字と、その片割れを含めない文字列を返すようにしている。
以上だ。
今回は、ブラウザ動作のJavaScriptでの実行だが、
他の言語・環境においても、応用が効くだろう。
さて、仕事戻ろうか・・・。
コメントする