開いてるタブの'[title](url)'をclipboardコピーするChrome拡張を書いた

Posted on | 229 words | ~2 mins

Situation

  • 調べ物をしてる際、記事URLのメモを取ることがある
  • メモはmarkdown記法をサポートしているエディタをつかっている
  • 記事URLだけでは後で見返すときに識別しづらいので、[title](url)の形式で貼ることが多い
  • ブラウザ(Chrome)で[title](url)をclipboardにコピーするには以下の手間を伴う
    1. 記事タイトルコピー 👈 キーボードで完結させづらくいちばんつらい
    2. アドレスバーへフォーカス
    3. [title](url)へ整形
    4. 全選択&コピー
  • 億劫になってきた

Motivation

  • もっとラクに[title](url)をcopyしたい
  • 念じるだけでできるのが理想
  • せめてコマンド1発

Solution

  • Shift+Y[title](url)をclipboardにコピーするChrome拡張を書く

Alternative Considered

  • 代替手段はとくにみてない
    • chrome拡張書いたことなかったし、書いてみるよい機会とおもったのが大きい

Action

manifest.jsonを追加

{
  "manifest_version": 2,
  "name": "ymdlink",
  "author": "hrfmmr",
  "version": "0.0.1",
  "description": "yank current tab's title and link as markdown notation"
}

chrome://extensionsでロードする

Load Unpackedでfile explorerを起動

ロードするextension prjディレクトリを選択

extensionsに追加される

permissionsを設定

  • Chrome extensionアプリがchromeのAPIアクセスするには、パーミッションを明示的に設定する必要がある
  • 📖 see Declare permissions
  • 今回は「現在のタブ」のtitleとurlを「clipboardにコピー」するので、以下をmanifest.jsonに追記する
    {
        ...
        "permissions": [
          "activeTab",
          "clipboardWrite"
        ]
    }
    

commandsを定義

  • キーマップ割当の設定をmanifest.jsonに追記する
    {
      ...
      "commands": {
        "yank": {
          "suggested_key": {
            "default": "Alt+Shift+Y"
          },
          "description": "yank current tab's title and link as markdown notation"
        }
      }
    }
    
  • Shift+Yを割り当てたかったが、commandsは「modifier」+ 「secondary modifier」 + 「key」の3つから成るという基本ルールがあり、
  • modifierはAltやCtrl, secondary modifierは(定義するなら)Shiftを割り当てるルール
  • なので、「secondary modifier」+「key」のShift+keyはキーマップ定義できない模様
  • なので、Alt+Shift+Yとすることに
  • 📖 see MDN Web Docs - commandss

background scriptを書く

  • 今回GUIは特に不要なショートカットキー割当に特化した拡張なので、popup.htmlは設置せず、background scriptのみ書いていく
  • manifest.jsonに以下を追記
    {
      ...
      "background": {
        "scripts": [
          "background_scripts/main.js"
        ]
      },
    }
    
  • background_scripts/main.js
    // manifest.jsonのcommandsで定義したキー押下のイベントハンドラを定義
    chrome.commands.onCommand.addListener(function(command) {
      if (command == "yank") {
        console.log("ymdlink: yank command is triggerd👉");
        chrome.tabs.query({
            active: true,
            lastFocusedWindow: true
        }, function(tabs) {
            // 現在のタブ情報を取得
            var tab = tabs[0];
            const yanktxt = `[${tab.title}](${tab.url})`
            // clipboardにコピー
            copy(yanktxt);
            console.log(`ymdlink: yanked ${yanktxt}🔗`);
        });
      }
    });
    
    // copy対象のテキスト選択するためのtextarea要素を生成
    const createTextArea = () => {
      const textArea = document.createElement("textarea");
      textArea.style.position = "absolute";
      textArea.style.left = "-100%";
      textArea.contentEditable = "true";
      return textArea;
    }
    
    // copy用textareaにテキストをセットし、選択状態にした上でclipboardへコピー実行
    const copy = (data) => {
      const textArea = createTextArea();
      textArea.value = data;
      document.body.appendChild(textArea);
      textArea.select();
      document.execCommand('copy');
      document.body.removeChild(textArea);
    }
    

background scriptのデバッグ

  • chrome://extensionsからInspect views backgronud pageをクリックして、デバッガコンソールを開く

  • background script内のconsole.logが出力されるのでこれでprint debugできる

Result

FYI.