LoginSignup
6
2

More than 5 years have passed since last update.

GitHubのIssueコメントをGitHub上にストックするためのChrome拡張作りました!

Last updated at Posted at 2019-03-18

github-stocked-comments

作ったもの

ナビバーに追加した Stocked Comments というリンクを押すとストックしたIssueコメントが以下のように表示されるものを作りました。

これGitHubの標準に備わっている画面じゃないんですよ(笑)

Kobito.vE4vBQ.png

ストックはIssueに表示されている Stocked ボタンからできるようになってます。

gsc_screen1.png

作った経緯

普段プログラミングをしていてgemとかnpmパッケージとか使用していてエラーに遭遇した時、問題解決につながる事はIssueに書いてあることが多いですよね。これを作る前は見つけたIssueのリンクをSlackとかに貼って次困った時に思い出せるように管理していたんですが、Slackは検索性能が悪いし、ログはどんどん流れていきあまり効率の良い方法ではないんですよね。そこでGitHubのIssueをストックするSlackに変わる何かいい方法はないだろうか?と考えたところ、「 GitHubのものはGitHub上で管理すればいいのでは? 」となってこのChrome拡張を作ろうとなったわけです。

インストール

Chrome Web Storeからダウンロード

GitHubからダウンロード

機能紹介

実際に使ってもらうと分かっていただけると思うが機能はざっくりこんな感じです。

機能 説明
クライアントサイド検索機能 検索したい文字(大小の区別なし)にマッチしたIssueコメントだけ残るようになってます。
マッチした文字列は黄色のマーカー表示されます。
ソート機能 ・最も最近ストックしたIssueコメント順
・最も投稿が古いIssueコメント順
・最も内容が長いIssueコメント順
ページネート機能 ストックしたIssueコメントの数が多くなると1ページあたり5個の表示になるようになってます。
フィルタリング機能(一般) 現在は、自分のIssueか他の人のIssueかをフィルタリングするようになってます。
フィルタリング機能(メイン言語別) Issueコメントのリポジトリに使われているメイン言語でフィルタリングするようになってます。
Jump to a Friend機能 自分がフォローしているユーザーのページに飛ぶことができます。
30人まで写真付きで表示されます。

使用しているライブラリとか(主要なものだけ)

使っているライブラリなどに関して簡単な説明をするとこんな感じです。

項目 説明
vue Stocked Comments をクリックした後にレンダリングされる画面を作成するのに使用してます。
vuex 機能紹介 で挙げた機能を実現するために使ってます。
ページネート機能に関してはvuexのpluginを自分で作ってそれを使って実現してます。
(まだパッケージ化してないですが近々パッケージ化してnpmで公開しようかと思います。)
mark.js クライアントサイド検索機能で検索結果にマッチした文字を黄色マーカー表示する際に使用してます。
rest.js issueコメントIDからIssueの詳細を取ってくるためのGitHubのAPIのラッパーライブラリです。
jquery Stocked Comments というリンクやIssueコメント上の Stoked ボタンを追加するために使用してます。
chrome.storage.local chrome拡張で使えるローカルストレージです。5MB までデータを保存できます。

知れてよかったライブラリ

このchrome拡張を作る上で使用してよかった・見つけれてよかったと思ったライブラリに関してです。

項目 説明
ALiangLiang/vue-webpack-chrome-extension-template vueでchrome拡張を作る時に便利なboilerplateです。
ソースコードに変更が生じたら自動で再ビルド・chrome拡張の再読み込みが走り開発効率を上げてくれます。
バンドルする時に node_modules 以下も一緒にまとめてバンドルするのではなく、node_modules 以下はそれだけでバンドルして読み込むように設定されていて、ビルド時間の短縮につながるような工夫もされてます。
chrome公開時のzipファイルの生成も自動でやってくれます。
github-injection 有名なChrome拡張である OctoLinker の中で使用されていたGitHubにインジェクションする時に便利な小さなライブラリです。 pjax:end のイベントをラップしてあります。GitHubではページ遷移を軽くするためにpjaxでの遷移になっている箇所が多数あるらしく、Issueページもpjaxで表示されているのでIssueページが表示されたのをこのライブラリを使って検知して Stocked というボタンを付与するようにしました。(Issueページの表示がpjaxで行われていることをこのライブラリのおかげで知ることができたというのも使用した理由です。)

やってよかったこと

このchrome拡張を作る上でやってよかったことは以下のような感じです。

  • 本格的に作る前に既にある比較的簡単なChrome拡張をリファクタしながら作ってみたこと。

    • ES6・babel・webpack・jestを使ったモダンな開発の練習になった。
    • chrome.storage.localをPromise化する方法が学べた。
    • manifestの書き方のイメージがついた。
    • 「chrome拡張、俺でも作れるんじゃね?」って自信がついた。
  • vuexのソースコードを読んだこと。

    • mapAction とか mapGetter とかの仕組みが理解できた。
      • vuexのプラグインを作る時に役に立った。
    • store の実装は難しくて分からなかった....。
      • 高階関数?になっていて難しい...。

得られた知識

このchrome拡張ベースで説明すると

GitHubに追加したリンク Stocked Comments をクリックした後に画面をレンダリングする方法

chrome拡張では現在のタブでスクリプトを実行したい時は、manifestのbackgroudに設定したスクリプトファイル(background/index.js)で行う必要があるということ。こんな感じで。

これは現在のタブで inject/index.js を実行するというコードです。
inject/index.js はメインコンテンツとフッターをレンダーするというコードです。

[background/index.js]

chrome.tabs.query({ active: true, currentWindow: true }, function (tabs) {
  chrome.tabs.executeScript(tabs[0].id, {
        file: 'inject/index.js'
  })
})

[inject/index.js]

import Vue from 'vue'
import App from './App.vue'
import Footer from './Footer.vue'
import store from '@/inject/store'

Vue.config.productionTip = false

new Vue({ // eslint-disable-line no-new
  el: '#github-stocked-comments',
  store,
  render: h => h(App)
})

new Vue({ // eslint-disable-line no-new
  el: '#github-stocked-comments-footer',
  render: h => h(Footer)
})

簡単に書いたらこんな感じなのですが、実際は background/index.js からcontent_script側 (content/event.js) ni js/inject.js を呼び出すように命令を出して実現してます。

  1. background => 2. content_script => 3. background => js/inject.js の実行

になってます。

1. background/index.js#18-L34

2. content/event.js#L28-L50

3. background/index.js#L2-L15

GitHubのIssueに Stocked というボタンを追加する方法

追加する方法はjqueryで一般的なやり方で追加しているだけなので簡単ですが、追加するタイミングが意外と難しかったです。

Issueのページがpjaxで表示されている事が分かったので以下のような感じでできます。

document.addEventListener('pjax:end', () => {
    # Issueに「Stocked」というボタンを追加する処理
});

github-injectionを使うともっといい感じ(エラー処理とかあり)にかけます。

import githubInjection from 'github-injection'

gitHubInjection(() => {
   # Issueに「Stocked」というボタンを追加する処理
})

node_modules以下のファイルだけでバンドルする方法

optimize.CommonsChunkPlugin を使って以下のように書くとできるそうです。
webpack4で optimization.splitChunks というものに変わったそうです。

こちらの記事がめちゃくちゃ詳しくて勉強になりました。
webpack 4 の optimization.splitChunks の使い方、使い所 〜廃止された CommonsChunkPlugin から移行する〜

new webpack.optimize.CommonsChunkPlugin({
      name: 'vendor',
      minChunks: function (module) {
        return (
          module.resource &&
          /\.js$/.test(module.resource) &&
          module.resource.indexOf(
            path.join(__dirname, '../node_modules')
          ) === 0
        )
      }
    })

今後の課題

使用していて必要と感じたらですが、機能的には以下の機能を実装したいかなって思ってます。

項目 内容
PR(discussion)保存 PR自体やdisscussionも保存できるようにする
フィルタリング機能(種類) 表示したいものを
・Issue
・Issueコメント
・PR
・PRのdiscussion
の種類でフィルターできるようにする
お気に入り機能 フィルタリング機能(一般)にお気に入りにしたリストを表示して絞れるようにする
メモ追加機能 保存したIssueコメントなどにメモを追加できるようにする

その他

  • Googleアナリティクスを導入して利用頻度を調べる
  • jestでテストを書く
  • CIを導入する

まとめ

普段よく使っている物を便利にするChrome拡張を作るのは楽しいです。
Webサービスを個人開発するより簡単で割と使えるものになりやすい気がします。
是非、何か作ってみたらいかがでしょうか。

6
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
2