日々のこと

まいにちの暮らしをつれづれ書きます

GitHubに貼る画像のサイズ調整を楽にするChrome拡張をつくった / Markdown to ImageTag

Chrome拡張機能をつくった話を書きます。

つくったもの

GitHubに貼る画像のサイズ調整を楽にするChrome拡張機能です。
Markdown to ImageTag という名前にしました。
アイコンは Chat-GPT に生成してもらいました。

chromewebstore.google.com

https://github.com/nobu09/image-tagify-extensions

やりたかったこと

GitHubで画像をアップロードすると、マークダウン形式になることがあります。
マークダウン形式の画像の場合、大きなサイズで表示されてしまい、画像サイズが調整できなくて不便でした。
画像を見やすくするために、手作業でimgタグに置き換えてwidth指定のサイズ調整を行うことがありとても煩わしかったので、自動で置き換えるようにしたかったことが動機でした。

 ![icon](https://github.com/nobu09/assets/xxxxxxxxxx)
   ↓
 <img width=500 src='https://github.com/nobu09/assets/xxxxxxxx' />

Chrome拡張を自作してみたかったので、勉強がてら取り組みました。

使い方

マークダウン形式の画像があるテキストエリアを右クリックし、imgタグに変換 を選択します。

img タグの画像に自動変換されます。デフォルトで width が 500px に指定されるので、お好みのサイズに調整してください。

コード

manifest.json

拡張機能の設定をする manifest.json はこのような内容です。

{
  "manifest_version": 3,
  "name": "Markdown to ImageTag",
  "description": "Replace markdown format images pasted into text areas (such as GitHub) with image tags",
  "version": "1.0",
  "icons": {
    "16": "images/icon-16.png",
    "32": "images/icon-32.png",
    "48": "images/icon-48.png",
    "128": "images/icon-128.png"
  },
  "permissions": ["activeTab", "contextMenus", "scripting"],
  "background": {
    "service_worker": "background.js"
  }
}

activeTab権限

現在アクティブにしているタブでスクリプトを実行するために、activeTab権限を許可しました。
この拡張機能では、ユーザーがGitHubのIssueやPull Requestなどのテキストエリア内で右クリックした際に、マークダウン形式の画像リンクをimgタグに変換するスクリプトを実行します。activeTab権限によって、ユーザーが操作しているタブに対し、必要なスクリプトを注入して動作させることができるようになりました。

contextMenus権限

contextMenus 権限は、拡張機能にブラウザのコンテキストメニュー(右クリックメニュー)にカスタムメニュー項目を追加する機能を提供します。
右クリックで imgタグに変換というコンテキストメニューを追加するためにこの権限を追加しました。

scripting権限

scripting 権限は、ページに対してプログラム的にコードを実行したり、ページのコンテンツを動的に変更するために必要でした。
この拡張機能では、選択されたマークダウンの画像リンクを動的に img タグに置き換えるために利用しています。

background.js

Chrome拡張のバックグラウンド処理を担当する、処理の中核となる部分はこのようになりました。

chrome.runtime.onInstalled.addListener(() => {
  chrome.contextMenus.create({
    id: 'replaceImage',
    title: 'imgタグに変換',
    contexts: ['editable'] // 編集可能なテキストフィールド上で右クリックしたときに表示
  });
})

function replaceImage() {
  let textarea = document.activeElement;
  if (textarea.tagName !== 'TEXTAREA') return;
  let textAreaText = textarea.value;
  let regex = /!\[.*\]\((.*?)\)/;
  let match = textAreaText.match(regex);
  if (match) {
    let url = match[1];
    let imgTagText = `<img width="500" src="${url}" />`;
    textarea.value = textarea.value.replace(regex, imgTagText);
  }
}

chrome.contextMenus.onClicked.addListener((info, tab) => {
  if (info.menuItemId === 'replaceImage') {
    chrome.scripting.executeScript({
      target: { tabId: tab.id },
      function: replaceImage,
    })
  }
});

拡張機能がインストールされたら、コンテキストメニューimgタグを変換 というメニューを追加するようにしました。これは、編集可能なテキストフィールド上で右クリックしたときのみ表示するようにしています。
そして、コンテキストメニューがクリックされたときに指定したスクリプトを実行するようにしています。
そのスクリプト(replaceImage function)では、正規表現でマークダウン形式の画像にマッチしたら img タグに変換させる処理をさせています。

公開までの流れ

せっかく作ったので公開することにしました。
審査に出して公開まで1日半ほどかかりました。
公開までの流れの詳細は、こちらのscrapboxの記事に書いています。

scrapbox.io

感想

取り組んでみて Chrome拡張のつくりかたをざっくり理解できたので、似たような拡張ならすぐ作れそうです。拡張機能を作るハードルが低くなりました。
自分で困っていたことを自分で解決できたことがうれしかったです。 また、拡張機能が公開されたのちに使ってくれる人が増えたり、便利と言っていただけるととてもうれしく、作ってよかったと思いました。
よかったら使ってみていただけたらうれしいです。

2024年も残りあとほんの少し。みなさん、良いお年を!