Markdown形式のリンクを作成するChrome拡張機能を作ってみた(メモ)


Chromeの拡張機能を作ってみた 〜Markdown形式のリンクを作成する拡張機能〜

勉強メモ程度に書きました
ソースはこちら

構成

Chromeの拡張機能はHTML、CSS、JavaScriptで出来ている。
こいつらと、Manifest fileをひとまとめにして、zip圧縮することでストアに公開することが出来る。また、chrome://extensions/ にドラッグドロップすると、インストールできる。

オプションのページや、ボタンなどの見た目の部分はHTMLとCSSで、処理はJSで実装する。
拡張機能内では、chrome.APIと呼ばれるAPIを使うことが出来る。
https://developer.chrome.com/extensions/api_index
具体的に何が出来るかは以下
https://developer.chrome.com/extensions/samples
サンプルソースもあるよ

Manifest file

JSON形式で書く拡張機能の情報を記したファイルです。

具体的には拡張機能の名前、説明、使用するスクリプトのパス、APIのパーミッションなどを書く。
公式ドキュメント - https://developer.chrome.com/extensions/manifest

参考にした記事

めちゃ分かりやすかったですありがとうございました。

いざ実装

こんな形式でコピーしてクリップボードに記録してくれるやつを作る。

[表示名](https://hoogehoge.com "title")

manifestの作成

manifest.jsonを見よう見まねで作成

manifest.json

manifest.json
{
    "manifest_version": 2,
    "name": "Markdown Link Maker",
    "version": "1.0",

    "description": "Copy text the Link text written in Markdown",
    "icons": {
        "48": "icon/icon48.png"
    },
    "browser_action": {
        "default_icon": {
            "48": "icon/icon48.png"
        },
        "default_title": "Make Markdown Link",
        "default_popup": "popup.html"
    }
}

browser_actionとは、Chromeの右上に表示される拡張機能のアイコンをクリックした際に、行われるアクションのことです。この記述だと、クリックした際にpopup.htmlがポップアップ表示される事になります。

manifestの注意点

  • jsonで次の項目がないのにカンマを付けないこと
  • default_localeは_localesフォルダが存在しない場合は記述しちゃだめ

popup.htmlを書く

テキトーに書いた。
とにかくクリックされたときに表示する内容と、処理を実行するJSの読み込み、CSSの読み込みを行う。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <link rel="stylesheet" href="icon.css">
    <link rel="stylesheet" href="style.css">
    <script src="js/jquery-3.2.1.min.js"></script>
</head>
<body>
    <div style="width: 200px;">
        <p style="margin: 0 auto; display: block;text-align: center;">
            Markdown Link Copied!
        </p>
    </div>
</body>
    <script src="js/main.js" type="text/javascript"></script>
</html>

注意点

  • 特に無い!!!!本当にただHTMLを書くだけでよい
  • さっきも言ったけどGUIの記述と、CSS,JSの読み込みだけ(今回はボタンとかもないのでメッセージのみ)

main.js の前にHello worldをやっとく

動作確認も込めて、Hello Worldをやってみる
とりあえずmain.jsを雑に作成

main.js

main.js
console.log("Hello Extension!");

Chromeでの動作確認をする

  1. chrome://extensions にアクセス
  2. 「パッケージ化されていない拡張機能を読みこむ」をクリック
  3. 拡張機能のフォルダを選択(ZIPになっている必要はありません)
  4. 問題なければ拡張機能の一つとして追加されます。問題があればエラー内容が出るので、修正すること。(出るとするとmanifestの文法エラー)
  5. 右上に作成した拡張機能が追加されているはずなのでクリック
  6. HTMLが表示されればOK。更にポップアップ表示された部分を右クリック、検証。 ポップアップで表示された部分は処理的には別ページなので、表示されているページを検証してもコンソールには何もでない。
  7. 開発者ツールが別ウィンドウで表示されるはずなので、そこのコンソールに出力されていることを確認して微笑む。

やっとちゃんと実装

ページタイトルとURLを取得して、Markdownに整形したものをconsoleに出力する処理を実装してみる。

var url = $(location).attr('search');
var title = $("title").text();

console.log("["+ title + "](" + url + '"' + title + '")');

結果 [Document]("Document") ( ゚д゚)

main.jsはあくまでもpopup.htmlの上で動いているので、locationで取れるのはpopup.htmlの情報だけなのです。
表示しているページの情報(DOM要素)へアクセスするには、実施のページ上でJSを動かす必要があります。

・・・が!今回はChromeAPIをつかってサクッと実装します。

manifestに以下を追記

"permissions":["clipboardRead","tabs"]

これでTAB関連のAPIと、クリップボードへのアクセスが可能になります。
そしてmain.jsに以下のように記述

//main 
chrome.tabs.query({active:true}, function(tab) {
    chrome.tabs.sendMessage(tab[0].id, {text:''}, function(response) {
        url = tab[0].url;
        title = tab[0].title;
    result = "["+ title + "](" + url + ' "' + title + '")';
    execCopy(result);
    });
});

//copy to clipbored
function execCopy(string){
    var temp = document.createElement('div');
    temp.appendChild(document.createElement('pre')).textContent = string;
    var s = temp.style;
    s.position = 'fixed';
    s.left = '-100%';
    document.body.appendChild(temp);
    document.getSelection().selectAllChildren(temp);
    var result = document.execCommand('copy');
    document.body.removeChild(temp);
    return result;
}

chrome.tabs.sendMessage でタブにリクエストを送信し、タブの情報を受け取っています。
あとは中身を整形して、markdownの形でクリップボードに貼っつけるだけ。

HTMLとか調整して完成です!
ソースはこちら

追記 今わかっているバグ

  • 複数ウィンドウを開いていると、親ウィンドウ(?)で開いているタブしか対象にされない