前書き

最近は仕事・プライベートに限らず、PCやスマホでWebブラウザを開かない日はないと言っても過言ではないように思います。

その中でも GitHub は個人的に利用する頻度が高いサービスのひとつです。

自分の関わるプロジェクトでPull RequestやIssueを見るだけでなく、OSSのリポジトリでREADMEを読んで使い方を学んだり、ソースコードを直接読むこともあるでしょう。

そんななかでちょっとした不満というか、ここがこうだったらいいのになと思ったのがリンクを開く時の挙動でした。


やりたいこと

GitHubのWebページで外部リンクを新規タブで開けるようにする、シンプルですがこれがやりたいことです。

どうやって実現しようか考えて、この悩みを解決するChrome拡張機能を作ってみようという結論に至りました。

また、この機能に必要な処理は以下のようになると考えました。

  1. GitHubのWebページを開く
  2. Webページ中からaタグを探す
  3. aタグの中から github.com 以外のドメイン(外部リンクとします)のURLをもつ要素を探す
  4. 外部リンクを持つ要素に target="_blank" を付与する

ということでこれをChrome拡張機能として実装してみます。

余談: target="_blank" は必要か?

リンクを新規タブで開いて欲しい時 target="_blank" を使う事自体は特に珍しいことではありません。

MDN web docsを見ると target について以下のように記載があります。

引用(一部省略)

リンク先の URL を表示する場所を指定します。これは、閲覧コンテキスト (タブ、ウィンドウ、<iframe>) の名前またはキーワードです。以下のキーワードは特別な意味を持ちます:
・_blank: 新しい閲覧コンテキストに URL を読み込みます。通常はタブですが、新しいウィンドウを使用するようにブラウザーを設定できます。

ただしこれに関しては議論もあるようで、とりあえず外部リンクには target="_blank" をつけたいという人もいれば、無闇に target="_blank" を使いたくないと考える人もいるようです。

自分も全ての外部リンクに必須であるとは思いませんが、実装自体は難しくないはずなのでGitHubはあえて target="_blank" 使わない方針をとっていると考えることができるでしょうか。

ちなみにGitLabでは外部リンクに target="_blank" が付与されているようでした、このあたりは作り手の意図が読み取れるようで面白いですね。

またドキュメント中では target="_blank" を使用する際の rel="noreferrer"rel="noopener" の併用についても記載がありますので、セキュリティの観点も忘れないようにしましょう。


やったこと

前置きが長くなりましたが、Chrome拡張機能を追加するのに必要なのは2つのファイルのみです。

manifest.json はChrome拡張機能として必要な情報や権限を記述するファイルです。

最低限だと以下のような内容で足りるかと思います。

{
  "manifest_version": 2,
  "name": "github-external-link",
  "version": "0.1.0",
  "description": "add `target=\"_blank\"` to external links on github",
  "content_scripts": [
    {
      "matches": ["https://github.com/*"],
      "js": ["contentScript.js"]
    }
  ]
}

manifest.json にも記述のある contentScript.js は前述の処理を実現するためのスクリプトで以下のようにしてみました。

window.addEventListener(
  'load',
  () => {
    const links = document.getElementsByTagName('a')
    Array.prototype.forEach.call(links, link => {
      const isExternalLink =
        link.href.match(/^https?:\/\/.+/) && !link.href.includes('github.com')
      if (isExternalLink) {
        link.target = '_blank'
        link.rel = [link.rel, 'noopener', 'noreferrer'].join(' ')
      }
    })
  },
  false,
)

この2つのファイルを同一のディレクトリに置き、Chromeの拡張機能画面で「パッケージ化されていない拡張機能を読み込む」で選択すると使用可能になります。(※拡張機能の追加、使用は自己責任で行ってください)

この拡張機能が機能しているか確認するために以下のリポジトリのページを見てみます。

1枚目が拡張機能がオフの状態、2枚目が拡張機能をオンにした状態です。
ページ上部の外部リンクである https://web.devtarget="_blank" を付与できていることがわかるかと思います。

以上でやりたいことが実現できました 🎉


後書き

「自分で作る」というアイデアで完成まで突っ走りましたが、よく考えたら既にChromeウェブストアで同じようなアイデアの拡張機能はありそうだなと思いました。
探してみると実際ありましたし、ここで作ったものをウェブストア上に公開するまでもないと思ったのでソースコードをそのまま紹介しました。

それでもChrome拡張機能を開発するのが意外と簡単なことがわかったのと、いままで意識したことがない target="_blank" について少し考える機会になったのは良かったと思いました。

これを機に何か別のChrome拡張機能も作ってみようと思います。