【JavaScript】ほぼ完璧(だと思う)絵文字除去

謎のプリン語る。
プログラミングの役立つ情報とか、どうでもいい雑談とか書いてます。
一人書く人増えました。

【JavaScript】ほぼ完璧(だと思う)絵文字除去

みやびプリン 500 316

500 320

【JavaScript】ほぼ完璧(だと思う)絵文字除去 - サムネイル

※この記事は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での実行だが、
他の言語・環境においても、応用が効くだろう。

さて、仕事戻ろうか・・・。

ラグナロクオンライン - メイン

トラックバック(0)

トラックバックURL:

コメント(5)

taka

| 2023年7月10日 13:19 | 返信

質問ですが、encodeURIComponentの引数にvという値があるのですが、これはどこから出てきた値でしょうか

コメントする

ページトップへ戻る