Chrome拡張でショートカットキーをつくってみた

# はじまり

この記事はディップ株式会社 [Advent Calendar 2022](https://qiita.com/advent-calendar/2022/dip-dev)の投稿です！

GitHub Enterpirseでプルリクエストを出す際にApproveをするためのショートカットキーがほしいなと思ったので、Chrome拡張でショートカットキーを作ってみました。

# ディレクトリ構成

下記のディレクトリ構成でChromeに読み込ませます。

```
$ tree
├── background.js
├── manifest.json
└── scripts //ショートカットキー押下後の処理が書かれたスクリプト
    ├── approve.js
    ├── conversation.js
    ├── files_changed.js
    └── openReview.js
```

# manifest.jsonの設定

manifest.jsonのcommandsに追加したいショートカットキーを追加します。
ショートカットキーは4つまでしか設定できないので注意が必要です。

```manifest.json
{
  "manifest_version": 3,
  "name": "GitHub Shortcut",
  "version": "2.0.1",
  "description": "Github Shortcut",
  "background": {
    "service_worker": "background.js"
  },
  "permissions": [
    "tabs",
    "webNavigation",
    "scripting"
  ],
  "host_permissions": [
    "https://GitHub Enterpriseホストドメイン/*"
  ],
  "commands": {
    "files_changed": {
      "suggested_key": {
        "default": "Alt+F",
        "mac": "MacCtrl+Shift+F"
       },
      "description": "Open files changed tab"
    },
    "conversation": {
      "suggested_key": {
        "default": "Alt+C",
        "mac": "MacCtrl+Shift+C"
       },
      "description": "Open Conversation tab"
    },
    "openReview": {
      "suggested_key": {
        "default": "Alt+C",
        "mac": "MacCtrl+Shift+R"
       },
      "description": "open Reivew Window"
    },
    "approve": {
      "suggested_key": {
        "default": "Alt+C",
        "mac": "MacCtrl+Shift+A"
       },
      "description": "Approve"
    }
  }
}
```
commandsキーにショートカットキーの情報を追加していきます。
本記事を参考にChrome拡張を作成する場合はショートカットキー名は実行するスクリプトのファイル名になるようにします。
suggested_keyにの中にそのショートカットキーに割り当てるキーボード配列の情報を追加していきます。
キーボードの配列の情報は[こちら](https://developer.chrome.com/docs/extensions/reference/commands/#supported-keys)を参照してください。
suggested_keyの中に`default`と`mac`というパラメータがありますが、ここでOSごとのキー情報を設定できます。
`mac`には`MacCtrl`というmacでのCtrlキーが用意されていたり、それぞれのOS限定のキー配列もあったりします。
注意点としては英数字キー1つだけの設定はできないので、複数のショートカットキーを使った配列にしなければなりません。


```json
"commands": {
    "ショートカットキー名": {
      "suggested_key": {
        "default": "ショートカットキー配列",
        "mac": "ショートカットキー配列"
       },
      "description": "コマンドの説明"
    },
}
```

# background.jsを設定

background.jsにコマンドのリスナーを設定します。
ショートカットキーが押されたら、現在開いているタブに対して事前に用意しておいたスクリプトを起動するようにします。

```background.js
chrome.commands.onCommand.addListener(function (command) {
  getCurrentTab().then((tab) => {
    chrome.scripting.executeScript({ target: { tabId: tab.id }, files: [`./scripts/${command}.js`] });
  })
});

async function getCurrentTab() {
	let queryOptions = { active: true, currentWindow: true };
	let [tab] = await chrome.tabs.query(queryOptions);
	return tab;
}
```

# 起動するスクリプトを用意する

ショートカットキーを押下後に実行するスクリプトを用意します。
このスクリプトは現在開いているページ内にJavascriptを埋め込んでいるような形になるので、
現在開いているページのDOM情報を取得することができます。
例として、プルリクエストの画面を開いて、`Ctrl + Shift + A`を押下したら、Approveをするようにします。
処理としては下記のようなことを行っています。
1. プルリクエストのFiles Changedを開く
1. `Review Changes`ボタンのDOM情報を取得
1. ラジオボタンをApproveに変更
1. `Submit review`ボタンを押下


```approve.js
function main() {
  const radio = document.getElementsByName('pull_request_review[event]');

  radio[1].checked = true;

  const submitButtons = document.getElementsByTagName('button');
  for (let i of submitButtons) {
    if (i.innerHTML.includes('Submit review')) {
      i.click();
      break;
    }
  }
}

main()
```

# 終わり

今回はGitHub EnterpriseでのPR画面でショートカットキーを作成しました。
このショートカットキーはChrome拡張で作成しているのでGitHub Enterprise以外のWebサイトで拡張することができるので、よく使うサイトなどでマウスでの操作が多い操作に対してショートカットキーを作成できます。

ただし、ショートカットキーが4つしか設定できないので、いろいろなショートカットキーを作成したい場合などではこの方法は作成できないので注意が必要です。