Lambdaカクテル

京都在住Webエンジニアの日記です

Invite link for Scalaわいわいランド

Chrome拡張を初めて作成してみた(id属性がある見出しにパーマリンクを自動付加する君)

最近Chrome拡張機能について考える機会が多く、自分も何か作ってみることにした。かねてから「自分もChrome拡張の一つや二つ作れなくてなは~」などと考えていたものの、特にアイデアがあるわけではないので、放置していた。 しかし丁度良くアイデアが舞い降りてきたので、やってみることにした。

heading要素にパーマリンクが欲しい

先日Scala 3.0.2のリリースノートを読んでいたとき、良いなと思った記述があった。具体的には次の箇所。

Scala 3.0.2 released! | The Scala Programming Language

型情報をもとに、メソッドを検索できるようになるらしい。さしずめ、HoogleのScala版といったところ。面白いのでここのリンクを社のSlackに投稿しようとした。

この箇所はh3要素を筆頭に記述されている。h3要素にid属性があるのでフラグメント記法を使ってhttps://www.scala-lang.org/blog/2021/09/07/scala-3.0.2-released.html#method-search-by-type-signatureというURIを構成できるし、この記法でリンクを貼ればブラウザはすぐにこの箇所を表示してくれるだろう。

最近のサイトでは、heading要素にid属性があるようなパターンでは、見出しの右側にリンク🔗の絵文字が表示され、クリックするとリンクをコピーできるのだが、今回のサイトにはそのような仕組みがなかったので、開発者コンソールを開いてid属性の中身をコピーしなければならなかった。

この機能はChrome拡張機能で実現できそうだし、それほど実装に手間がかかることはなさそうだと思ったので、さっそく作ることにした。

できた

最低限の機能を実装して作成したのがこちら。

github.com

f:id:Windymelt:20211110214205p:plain

h2, h3, h4要素にid属性があるときは、自動的にパーマリンクを作成してくれるようになった(図では見出しの末尾に#記号が出現している)。

やったことは以下の通り。

  • 実装となるcontent_script.jsの実装
  • アイコン各種の作成(PNG形式)
  • manifest.jsonの作成

最低限これだけでなんとかなる。実装には以下のサイトを参考にした。

qiita.com

この記事のタイトル通り、この拡張機能は会社の昼休みに作れてしまった。

content_script.js

ページロード時にdocument内のh2[id],h3[id],h4[id]をかき集めてきて、リンクとなるa要素を末尾にくっつけている。

window.onload = function() {
    const elems = [...document.querySelectorAll('h2[id], h3[id], h4[id]')];
    elems.forEach((e) => {
        const link = document.createElement('a');
        link.innerText = '#';
        link.href = location.href + '#' + e.id;
        const small = document.createElement('small');
        small.append(link)
        const sub = document.createElement('sub');
        sub.append(small);
        e.append(sub);
    });
}

これだけ。

アイコン各種

GIMPで適当に作成した。id属性があるところにリンクを追加するので、idを象徴する#記号と、リンクを象徴するアンダーラインを使ったものにした。

f:id:Windymelt:20211110213548p:plain

ちなみにここで反省点がある。知識不足から先に32x32ピクセルのアイコンを作成してしまったので、128x128ピクセルの画像がぼんやりになってしまった。実際は32x32があれば良いっぽい?のだけれど、一番先に128x128や、より大きいサイズでアイコンを作成して、適宜縮小したほうがよいと思う。

manifest.jsonの作成

拡張機能にはmanifest.jsonが必須。最小限nameとmanifest_version、content_scriptsあたりを埋めればよさそうだった。

{
  "name": "ID Heading Autolinker",
  "description": "Insert permalink automatically along h2, h3, h4 elements with ID attribute.",
  "manifest_version": 2,
  "version": "0.1",
  "author": "windymelt",
  "homepage_url": "https://github.com/windymelt/id-heading-autolinker-extension",
  "browser_action": {
    "default_icon": "icon_32.png"
  },
  "icons": {
    "16": "icon_16.png",
    "48": "icon_48.png",
    "128": "icon_128.png"
  },
  "content_scripts": [
    {
      "matches": ["http://*/*", "https://*/*"],
      "js": ["content_scripts.js"]
    }
  ],
  "permissions": ["activeTab"]
}

バージョン番号はいかにも管理漏れしそうで怖い。

この通り記述すると、ブラウザがタブを開くたびにcontent_scripts.jsが実行される。

動作確認

ローカルで動作確認するためには、拡張機能の管理画面から「パッケージ化されていない拡張機能を読み込む」を選択し、manifest.jsonがあるディレクトリを指定すればよい。

f:id:Windymelt:20211110214509p:plain

これで拡張機能が有効化された。

冒頭に登場したScala3.0.2のリリースノートを見ると、ちゃんとリンクが出現していることがわかる。

f:id:Windymelt:20211110214205p:plain

いまのところちゃんと動作しているようで、困ったことは起こっていない。積年の面倒臭さが解消されたのでとてもうれしい。

Chrome Web Storeに登録する

せっかく作ってちゃんと動作したからには他の人にも使ってもらいたいと思ったので、Chrome Web Storeへの登録にもチャレンジしてみた。Chrome Web Storeへの登録に関しては公式のドキュメントを参照した。

support.google.com

不正利用を防ぐためか、初回登録時に5ドルGoogleに御布施しなければならない。ドイツでトイレを借りたときも、このくらい(ユーロで)取られた記憶がある。

基本的にフォームを埋めていくだけなのであまり難しいことはない。気を付けたのは以下の点。

  • パーミッションの範囲が広い(今回は全サイトで有効化する拡張機能な)ので、その理由を1行書く必要がある。
  • ZIPファイルをアップロードする必要がある。今回はGithubのリリース機能を使ってZIPを作り、それをそのままアップロードした。
  • スクショを添付する必要がある。GIMPでちまちま指定のサイズのスクショを作成した。
  • 拡張機能の説明文を英語で書くことになるけれど、拙い英語力がバレるかもしれないので不安になった。

パーミッションの範囲が広いので今回はしばらく審査待ちになるようで、デベロッパーコンソールの画面はこういう状態になっている。

f:id:Windymelt:20211110215613p:plain

感想

意外と簡単だった。もっと機能が複雑になってきたらnpmを使ったりTypeScriptを使いたくなりそう。すると今回使った「雑にGithub Releaseを作成してZIPを得る」方式が通用しなくなるので、別のビルドラインを作ることになるのかなぁ、と思った。この拡張機能で大儲けしたい。

闇でインストールしたい方向け情報

GithubのReleaseからZIPファイルをダウンロードできるので、解凍すると「パッケージ化されていない拡張機能を読み込む」で利用することができます。At Your Own Risk.

★記事をRTしてもらえると喜びます
Webアプリケーション開発関連の記事を投稿しています.読者になってみませんか?