過激なコメントを絵文字に変えちゃうブラウザ拡張機能作ってみた😎👍

## インターネットライフに感じた限界

私は毎日、インターネットで技術調査をしたり、Twitterをしたり、YouTubeを見たり、ブログを読んだり、そんなありふれた日常をオンラインで過ごしています。  
楽しいですね。**しかし突然、次のどれかに遭遇することになります。**

- 誹謗中傷
- 罵詈雑言
- 悪口
- 悪意
- 炎上
- イキリマウンティング
- 突然のネタバレ

普段は何ともないように対処していたとしても、時にはあまりにも非道な言葉を見かけることもあります。とてもつらい  

インターネットが地獄と化したのはいつからでしょうか。最初から地獄だったのでしょうか。  
今日のインターネットは無防備なまま放り出されるにはちょっと酷な空間だなと、そう感じています。

さて、幸いなことに自分はエンジニアです。必要なら作っちゃえばいいじゃない、心無い言葉から身を守る盾を！

## ブラウザ拡張機能『EmoGuard』

というわけで、作りました。

![basic.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2938779/715337ed-7cc9-c947-711c-fb71d7180722.gif)

EmoGuardはChromeとSafariに対応したブラウザ拡張機能です。  
EmoGuardを使うと、Webサイト上の見たくないキーワードをブロックすることができます。

つまりインターネットが存在しなければ出会うはずもなかった非道な言葉から身を守ることができちゃいます。

- [Chrome Web Store](https://chrome.google.com/webstore/detail/emoguard-keyword-blocker/jgjkefnbeaoejcbpfggcggicconjfldd)
- [Mac App Store](https://apps.apple.com/jp/app/emoguard/id6443750638?mt=12&itsct=apps_box_link&itscg=30200)
- [App Store](https://apps.apple.com/jp/app/emoguard-%E3%82%AD%E3%83%BC%E3%83%AF%E3%83%BC%E3%83%89%E3%83%96%E3%83%AD%E3%83%83%E3%82%AB%E3%83%BC/id6443750571?itsct=apps_box_link&itscg=30200)

なんと[iOS版](https://apps.apple.com/jp/app/emoguard-%E3%82%AD%E3%83%BC%E3%83%AF%E3%83%BC%E3%83%89%E3%83%96%E3%83%AD%E3%83%83%E3%82%AB%E3%83%BC/id6443750571?itsct=apps_box_link&itscg=30200)もあります！

![iPhone.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2938779/edfa2001-2f5a-b275-9509-a1fc8e46c45c.gif)

## 開発の背景

キーワードブロッカーと呼べるようなブラウザ拡張機能はいくつか存在していますが、デザインがシンプルで柔軟にカスタマイズできてついでにクロスプラットフォームで動いてくれる、そんな贅沢三昧セットを備えたシロモノは見つかりませんでした。  

なかったので自分で作ることにしました。

## EmoGuardのデモ

### 1. キーワードをブロック

![basic.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2938779/715337ed-7cc9-c947-711c-fb71d7180722.gif)

基本は超シンプル！EmoGuardを開いて、キーワードを追加。  
たったそれだけでほとんどのWebサイトでキーワードをブロックすることができます。

### 2. ターゲットの隠し方を変える

ツールは自分好みにカスタマイズしたいのがエンジニアの性でしょう。  
「カスタマイズ」モードを有効にすれば、ブロック方法を完全に自由にコントロールすることができます。

#### まずは「カスタマイズ」を有効化

![customize.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2938779/1b8b16e7-9db4-cf8c-d040-bf20af9cc29f.gif)

#### テキストだけをピンポイントで隠すか、指定した要素を丸ごと隠すか選べます

![hiding-mode.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2938779/7788b7a3-57d4-e516-2d97-cff6d67f3dc2.gif)

Web開発者にはおなじみのCSSセレクターを自分で追加することもできるので、
どんなサイトでも自分好みのブロック方法を追求することができます。

### 3. どのCSSセレクターが有効になっているかチェックする

目のアイコンをクリックすると、どのCSSセレクターがテキストや要素を隠しているのかリアルタイムに確認することができます。

![visibility.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2938779/8002cd60-c8dc-3695-2ee5-57c26074aaa1.gif)

また、この表示/非表示の設定はEmoGuardを閉じたりブラウザをリロードしても残るので、追加したCSSセレクターを削除したくはないけど一時的にオフにしたい、といった時にも役立ちます。

### 4. 絵文字も変えちゃおう

デフォルト設定ではWebページ上のキーワードが「😎👍」という絵文字で置き換わります。  
**実はこの絵文字はオプションから自由に変更可能です。**

#### 全部🥺に置き換えたり…

![pien.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2938779/6a833fa0-2cdc-cf25-2fa2-b3d807a3c5f1.gif)

#### ぶっちゃけ絵文字じゃなくてもOKです

![neta.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2938779/392810a4-369f-3f35-fd51-33a7466ba546.gif)

この機能、割と個人的に気に入ってます。

### 5. データを同期できちゃう

例えば、Windows版ChromeとiOS版Safariの間でデータを同期することができます。  
同期は最高ですね…（この機能実装するの死ぬほど苦労した…）

## さらに詳しい使い方

公式サイトの[チュートリアル](https://emoguard.app/ja/docs/tutorial)や[よくある質問](https://emoguard.app/ja/docs/faq)で詳しい使い方を解説しています！  
キーワードを縦横無尽にブロックできるようになりたい方は立ち寄ってみてください🤗

## ちょっと技術的な話

EmoGuardにはイマドキの技術が採用されています。

- [TypeScrypt](https://www.typescriptlang.org/)
- [React](https://ja.reactjs.org/)
- [MUI](https://mui.com/)

キーワードブロック機能はできればブラウザにデフォルトで搭載されていてほしい、と個人的には思っています。（過激派）
だからなるべく「公式っぽい見た目」のアプリにしたくてMUIを採用しました。
欲しいコンポーネントは大抵何でも揃っていますし、開発効率も爆上がりなので非常にオススメできます。
もしTypeScrypt・React・MUI（もしくは他のUIフレームワーク）無しにフルスクラッチで開発していたらと想像するとゾッとしてしまうくらい、これらはパワフルに開発者をバックアップしてくれます…

が、これらをブラウザ拡張機能で動かそうとするとちょっと大変です。

webpackはデフォルトでエントリーポイントを一つしか生成しませんが、ブラウザ拡張機能には「popup」「options」「content scripts」「background」と4つものエントリーポイントが必要です。

そのためwebpackの動作を少々ハックする必要があります。

今回はwebpackの設定を上書きするために[react-app-rewired](https://github.com/timarney/react-app-rewired)と[customize-cra](https://github.com/arackaf/customize-cra)を導入しました。
これらのライブラリを駆使してChrome拡張機能でReactを動作させる方法としては、以下のQiitaの記事が非常に参考になりました。
この場を借りて感謝申し上げます。

- [Create React Appで始めるChrome拡張](https://qiita.com/takakobem/items/64c37a4f35cadd712907)

react-app-rewiredとcustomize-craではwebpackの設定を上書きするために `config-overrides.js` というファイルを作成する必要があり、先程の記事でもその手順が記載されています。

しかしwebpackのバージョンが上がったことで不要となった設定や、より本格的な拡張機能のために追加で必要な設定等があったため、参考情報として私のプロジェクトで使用しているコードをここに残しておきます。

```js:config-overrides.js
const path = require('path');
const { override, disableChunk } = require('customize-cra');
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
  paths: function (paths, env) {
    paths.appIndexJs = path.resolve('src/popup/index.tsx');
    return paths;
  },
  webpack: function (config, env) {
    // エントリーポイントを追加
    config.entry = {
      // `main` エントリーが必須のため popup を main に設定
      main: [path.resolve('src/popup/index')],
      options: [path.resolve('src/options/index')],
      'content-script': [path.resolve('src/content-script/content-script')],
      background: [path.resolve('src/background/background')]
    };

    // ファイル名からハッシュを除外
    config.output.filename = 'static/js/[name].js';
    const defaultMiniCssExtractPlugin = config.plugins.find(plugin => plugin.constructor.name === 'MiniCssExtractPlugin');
    defaultMiniCssExtractPlugin.options.filename = 'static/css/[name].css';

    // 指定した <script> タグのみを `popup.html` に挿入
    const defaultHtmlWebpackPlugin = config.plugins.find(plugin => plugin.constructor.name === 'HtmlWebpackPlugin');
    defaultHtmlWebpackPlugin.userOptions.filename = 'popup.html'
    defaultHtmlWebpackPlugin.userOptions.chunks = ['main'];

    config.plugins = config.plugins.concat([
      // options ページ用の HTML ファイルを生成
      new HtmlWebpackPlugin({
        inject: true,
        filename: 'options.html',
        template: 'public/index.html',
        chunks: ['options'],
        minify: Object.assign({}, defaultHtmlWebpackPlugin.userOptions.minify)
      })
    ]);

    return override(
      disableChunk()
    )(config, env);
  }
};
```

## Happy Internet Life!

最初は個人的な感情から開発を始めた拡張機能でしたが、誰かの役に立てばと思い本格的な開発に移行して気づけばそれなりの時間が経ってしまいました。  
ようやくリリースにたどり着けたのは実は結構感無量だったりします。

私は昔、インターネットが結構好きでした。  
でも今はちょっと違うかも、というのが本音です。

自分がまたインターネットを好きになるために作ったこの拡張機能が、他の人にも楽しいインターネット生活を取り戻してくれたらいいな。

**Happy Internet Life!**

---
Twemoji graphics made by Twitter, Inc and other contributors are licensed under CC-BY 4.0:
https://creativecommons.org/licenses/by/4.0/