HTML
CSS
JavaScript
Chrome
chrome-extension

ページのタイトルとURLを取得するChrome拡張を作った。


動機

ふとChrome拡張機能を作りたいと思った。

で、何を作るかとなったときに、

Markdown つかうようになってきたけど、タイトルの取得に時間がかかる...!

そこで、タイトルやURLを数クリックで取得&コピーできたらいいなと思い、作ってみました。


作成前


タイトル取得時

タイトルの場合、

1. ブックマークのボタンを使用して名前から取得し、Ctrl+Cする。

2. コンソールを開いて document.title を打って、範囲選択 + Ctrl+Cする。

などが私のタイトル取得方法でした。

Bookmark
Console

Bookmark_TtlGet.jpg
Console_TtlGet.jpg

( ` _ ` ).oO(ブラックテーマっていいよね...)


URL取得時

URLバー(?)クリック + Ctrl+Cが簡単。

コンソールで画像中の2つを打つのもあり。ほかにもありそう。

Bar
Console

bar_URLGet.jpg
Console_URLGet.jpg

いずれにしても、面倒くさい


作成後

ScreenShot.jpg

出力を用途によって変えられる。

例えば、Google ( https://www.google.com ) であれば、

Get Title
Get URL
Get Both with Markdown

Google
https://www.google.com/
[Google](https://www.google.com/)

といった具合にテキストボックスに出力され、横のコピーボタンをクリックすればコピーされる。便利。

ちなみに This Extension is open source です。Please Improve this Extension.


ソースコード

a01sa01to/titleAndURL_Picker

こちらで公開していますが、コメントなしなので、こちらでざっくり解説しようと思います。


ファイル構成


  • manifest.json

  • index.html

  • script.js

  • style.css


manifest.json


manifest.json

{

"name": "Title & URL Picker", // 拡張機能の名前(必要)
"version": "1.0", // バージョン(必要)

"icons": {"128": "icon128.png"}, // アイコン(推奨)

"description": "Get Title And URL of a Page.", // 拡張機能の説明(推奨)

"browser_action": {
"default_title": "Title & URL Picker", // 拡張機能のアイコンをホバーしたときに出るテキスト(任意)
"default_popup": "index.html" // 拡張機能アイコンをクリックしたときに出るページ(任意)
},

"permissions": ["activeTab"], // 許可を求める(任意。この拡張に関しては使わなかったかも...?)

"author": "Asa", // 作成者(任意)

"manifest_version": 2 // マニフェストのバージョン(必須。現在は2が推奨されている。)
}


このファイルは、拡張機能を作るのに必要不可欠なファイルです。

(JSONにコメントは付けられないので赤線が引かれてあると思われます)


Every extension has a JSON-formatted manifest file, named manifest.json, that provides important information.

Manifest File Format - Google Chrome


これを訳すと、「すべての拡張機能はmanifest.jsonというJSONマニフェストファイルがある。それは重要な情報を渡すもの。」

ここがずれると、ほぼすべての動作が変わるといっても過言ではないほど重要だと思います。

ちなみに、拡張機能のページ(chrome://extensions/)では、以下のように表示されます。

extensionPreview.jpg

表示されているのは...

name, version, icon, description のみですかね


index.html


index.html

<!DOCTYPE html>

<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="style.css">
<script src="script.js"></script>
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.2/css/all.css" integrity="sha384-fnmOCqbTlWIlj8LyTjo7mOUStjsKC4pOpQbqyi7RrhN7udi9RwhKkMHpvLbHG9Sr" crossorigin="anonymous">
<script src="clipboard.min.js"></script>
</head>
<body>
<h1>Title & URL Picker</h1>
<button class="ttl">Get Title</button>
<button class="url">Get URL</button>
<button class="bmark">Get Both with Markdown</button>
<input type="text" readonly id="result">
<button class="copy" data-clipboard-target="#result" data-clipboard-action="copy"><i class="far fa-copy"></i></button>
<div class="msg">
<p class="copied">Copied!</p>
<p class="failed">failed...</p>
</div>
<p>This Extension is open source. <a href="https://github.com/a01sa01to/titleAndURL_Picker" target="_blank">Improve this Extension.</a></p>
</body>
</html>

ScreenShot.jpg

見比べたら大体わかるかと思います。

今回、Font Awesomeclipboard.jsを使用しました。

どちらもコピーボタンのデザイン&実装に使用しています。


style.css


style.css

@import url('https://fonts.googleapis.com/css?family=Muli');

*{
font-family: 'Muli', sans-serif;
color: #fff;
box-sizing: border-box;
margin: auto; /* 中央揃え */
}
h1{
text-align: center; /* 中央揃え */
grid-area: header;
}
button{
font-size: 16px;
background: #666;
margin: 8px;
border-radius: 10px;
padding: 10px;
width: 1fr; /* Grid 特有。面白い。 */
cursor: pointer;
}
input{
font-size: 18px;
color: #555;
padding: 8px;
height: 40px;
grid-area: result;
width: 95%; /* 左右に余白を持たせたかった。 */
}
body{
--height: 60px; /* CSSでも変数を使えるらしい。 */
width: max-content; /* 子要素の 最大幅+Margin が bodyの最大幅 */
padding: 8px;
background: #333;
display: grid;
grid-template-rows: var(--height) var(--height) var(--height) var(--height) var(--height) 10px 20px; /* See 変数の使い方 */
grid-template-columns: 1fr 75px 50px;
grid-template-areas:
"header header header"
"ttlBtn ttlBtn ttlBtn"
"urlBtn urlBtn urlBtn"
"markBtn markBtn markBtn"
"result result copyBtn"
"...... msg msg"
"notice notice notice";
}
button.copy{
width: 40px;
height: 40px;
border-radius: 20px; /* 丸にしたかった。楕円にならないようにwidth=heightになっている */
font-size: 24px;
padding: 4px;
grid-area: copyBtn;
}

button.ttl{
grid-area: ttlBtn;
}
button.url{
grid-area: urlBtn;
}
button.bmark{
grid-area: markBtn;
}
p{
width: max-content;
grid-area: notice;
text-align: right;
z-index: 2;
}
div.msg{
z-index: 300; /* 究極に上に表示させている。 */
grid-area: msg;
display: none;
width: 100px;
height: 30px;
margin-right: 0;
border-radius: 15px;
padding: 4px 18px;
font-size: 18px;
background: #eee;
}
p.copied, p.failed{
color: #333;
z-index: 350; /* さらに上に表示 */
display: none;
grid-area: unset;
position: absolute;
}


これは...個人の好みの問題です...

今回、レイアウトに初めてGridを使ってみました。

Gridについてはこちらの方の記事がとても分かりやすかったです!

CSS Grid Layout を極める!(基礎編) - Qiita

あとCSSって変数使えるんですねー。

CSS カスタムプロパティ (変数) の使用 - CSS: カスケーディングスタイルシート | MDN

私は割とMuliというフォントが好きです。というかsans-serif体がいい。

Muli - Google Fonts


script.js


script.js

let Data = {"Title": "", "URL": ""}  // とりま格納する変数

chrome.tabs.getSelected(tab=>{ // 現在のタブを取得
Data.Title = tab.title; // tabに現在のタブが格納されている(?)。
Data.URL = tab.url; // tab.titleには現在開いているタブのページタイトルが、tab.urlにはURLが格納されている。
console.log(`Title: ${Data.Title}`); // 出力は、「ポップアップを検証」で見れる。
console.log(`URL: ${Data.URL}`);
});

window.addEventListener('load',()=>{ // 拡張機能アイコンがクリックされて拡張機能ポップアップページが読み込まれたとき
const txtBox = document.querySelector('input');
document.querySelector('button.ttl').addEventListener('click',()=>{ // クリックされたときにテキストボックスに出力
txtBox.value = Data.Title;
});
document.querySelector('button.url').addEventListener('click',()=>{
txtBox.value = Data.URL;
});
document.querySelector('button.bmark').addEventListener('click',()=>{
txtBox.value = `[${Data.Title}](${Data.URL})`;
});

const cb = new ClipboardJS('button.copy'); // Clipboard.js
const msgContainer = document.querySelector('div.msg');
const msgSuccess = document.querySelector('p.copied');
const msgFailed = document.querySelector('p.failed');
cb.on("success", function(e){ // コピーに成功
console.log('Copied Successfully.', e);
msgContainer.style.display = "block"; // 表示
msgSuccess.style.display = "block";
setTimeout(()=>{
msgSuccess.style.display = "none"; // 3sec後に非表示
msgContainer.style.display = "none";
},3000);
});
cb.on("error", function(e) { // コピーに失敗
console.error('Failed to Copy.', e);
msgContainer.style.display = "block";
msgFailed.style.display = "block";
setTimeout(()=>{
msgFailed.style.display = "none";
msgContainer.style.display = "none";
},3000);
});
})


Clipboard.jsの使い方は、こちらが参考になりました!

JavaScriptでコピーをする方法(clipboard.jsの使い方)

Chrome拡張の作り方は公式をはじめ、様々なサイトを拝見しましたが、DOMを取得しない私の作りたい機能では、SendMessageContent_Script などは必要なかったようです。

今後作る拡張には組み込みたい...


動作チェック

やっぱり(?)Googleで動作チェック。


1. タブのページチェック

chk01.jpg

URLは https://www.google.com/ になっています。

もちろんタイトルは「Google」。

(^^) .oO( W3 誕生日おめでとう!!!) // 撮影日:03/12


2. レイアウトチェック

chk02.jpg

自分好みなデザインになっています。

ダークテーマ、最高!!!


3. Button「Get Title」動作チェック

chk03.jpg

タイトルである「Google」の文字がしっかりとテキストボックスに出力されています。


4. Button「Get URL」動作チェック

chk04.jpg

これもしっかりURLが出力されていますね。


5. Button「Get Both with Markdown」動作チェック

chk05.jpg

しっかりとMarkdownの書式にあったものになっています。

// Markdownでは [タイトル](URL)とすることで以下のリンクが作成されます。

// タイトル


6. Button「Copy」動作チェック

これはClipboard.jsを用いて実装したのですが、果たして...?

chk06.jpg

一応Copiedの文字は表示されました。が、実際にコピーされているのでしょうか...


7. コピーされているかチェック

下に貼り付けました。

Google

その画像がこちら。

chk07.jpg

一応ペーストした部分はハイライトしておきました、

しっかりコピーされていました。Clipboard.js 優秀!


チェック終了。

すべて自分の期待通りに動いてくれました。


拡張機能を公開

...はしなくてもいいかなと。完全に自己満足なので。

ソースコードはGitHubで公開しています。

一応インストール手順も記述しておきましたので、使用したい方はそちらをもとにインストールしてみてください!