※この記事は2年以上前の記事です。
現在は状況が異なる可能性がありますのでご注意ください。
どうも。
気づけば、一年以上記事書いてなかった。
普通に死ぬほど忙しかった。
さて、表記の件だ。
面白いよね、絵文字って。
エンジニアにとっては、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(c).replace(/%../g, 'x').length < 4 && !surrogatePairCode.some(codeNum => 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での実行だが、
他の言語・環境においても、応用が効くだろう。
さて、仕事戻ろうか・・・。
anonymous
| 2023年6月30日 20:25 | 返信
バグだらけで完璧じゃないですね・・・
taka
| 2023年7月10日 13:19 | 返信
質問ですが、encodeURIComponentの引数にvという値があるのですが、これはどこから出てきた値でしょうか
●みやびプリンからtakaへの返信
| 2023年8月 1日 20:06 | 返信
ご指摘ありがとうございます。
確かに、定義されてない変数ですね・・・。
確認して、記事を直します。
●みやびプリンからanonymousへの返信
| 2023年8月 1日 20:08 | 返信
コメントありがとうございます。
恐縮ですが、どこらへんにバグがありましたでしょうか・・・?
記事のコードと、実際動かして確認していたコードに差異があった可能性もありますので、
具体的に箇所をご指摘いただければ幸いです。
もちろん、自身でも再確認しますが。
●みやびプリンからanonymousへの返信
| 2023年8月 1日 23:43 | 返信
ご指摘ありがとうございました。
記載時に慌ててコードが間違ってしまっていたようです・・・。
修正しましたので、どうかよろしければお使いください。