よんどころなき事情により、新年早々に Chrome拡張機能を作成してみました。
(Chrome拡張機能) Create Link の挙動が不安定の記事に書いた通り、 Chrome拡張機能 の Create Link - Chromeウェブストア が挙動不安定になってしまいました。
ブログを書く際に参考記事をリストアップしたり、自分の活動にはこの機能はなくてはならないのでそれがままならないというのは不便極まりない。
そこで、代替となる Chrome拡張機能 を自作してみることにしました。
Create Link の代替を想定したため、機能はこれに準じます。
ただし、貼り付けるコードのカスタマイズの必要はない (プレーン、HTML、Markdown の3種があれば充分) ので設定画面等の自前でカスタマイズできる機能は全てオミット。
ページを開いている状態で右クリックして、コンテキストメニューから上述3種の形式でリンクをクリップボードに貼り付けられれば良いです。
{
"manifest_version": 2,
"name": "emerald-isle",
"description": "Make link text of open page.",
"version": "0.0.1",
"background": {
"scripts": [
"dist/chain.js"
],
"persistent": false
},
"content_scripts": [
{
"matches": [
"*://*/*"
],
"js": [
"dist/smith.js"
]
}
],
"permissions": [
"tabs",
"activeTab",
"clipboardWrite",
"contextMenus"
],
"content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'",
"icons": {
"48": "assets/icon_48.png",
"128": "assets/icon_128.png"
}
}
特筆すべき事項はあまりないですが
2
を選択permissions
はタブ、クリップボードへの書き込み、右クリックメニュー(コンテキストメニュー)等background
, content_scripts
の2つのフィールドが存在)
content_scripts
を実行させるURLは全てのURLで良いので *://*/*
指定 (matches
フィールド)といったところでしょうか。
import { mdLink } from "markdown-function"
/**
* grace_O_Malley : Grace O'Malley / titleタグ 文字列のエスケープ
*
* @param {string} text : 開いているタブの titleタグ の中身の文字列
* @param {string} url : 開いているタブの URL の文字列
*
* @returns {string} : Markdown 記法をエスケープした Markdown 形式のリンク
*/
const grace_O_Malley = (text, url) => {
return mdLink({
text: text,
url: url,
});
};
/**
* brianBoru_s_March : Brian Boru's March / メイン処理
*
* @returns {void}
*/
const brianBoru_s_March = () => {
chrome.runtime.onInstalled.addListener(() => {
chrome.contextMenus.create({
type: 'normal',
id: 'CahirCastle',
title: 'Emerald Isle',
contexts: [
'all'
],
});
chrome.contextMenus.create({
type: 'normal',
id: 'plain',
parentId: 'CahirCastle',
title: 'Plain Text',
contexts: [
'all'
],
});
chrome.contextMenus.create({
type: 'normal',
id: 'html',
parentId: 'CahirCastle',
title: 'HTML',
contexts: [
'all'
],
});
chrome.contextMenus.create({
type: 'normal',
id: 'md',
parentId: 'CahirCastle',
title: 'Markdown',
contexts: [
'all'
],
});
});
chrome.contextMenus.onClicked.addListener(function(item){
chrome.tabs.getSelected((tab) => {
// 現在のタブ
let clipText = '';
// クリックされたメニューに応じてテキストを組み立て
switch (item.menuItemId) {
case 'plain':
clipText = `${tab.title} - ${tab.url}`;
break;
case 'html':
clipText = `<a href="${tab.url}" target="_blank" rel="noopener noreferrer">${tab.title}</a>`;
break;
case 'md':
clipText = grace_O_Malley(tab.title, tab.url);
break;
default:
break;
}
chrome.tabs.sendMessage(tab.id, clipText, function(response) {
console.log(response.value);
});
});
});
};
document.addEventListener('DOMContentLoaded', brianBoru_s_March());
chrome.contextMenus.create()
でコンテキストメニューの中身を作成chrome.contextMenus.onClicked.addListener()
にコンテキストメニューがクリックされた場合の処理を記述
id
の値で条件分岐してプレーン,HTML,Markdownの3種のリンクのテキストを生成navigator.clipboard.writeText()
を発動させようとしても失敗してしまいます (Uncaught (in promise) DOMException: Document is not focused.
というエラー文が出力される)
Document.execCommand
はDOMの指定が必要でこれも Content Scripts 側の動作と思われる上、Document.execCommand() - Web API | MDNに 非推奨: この機能は非推奨になりました。
と記載されているため、今からこの方法を採用するのは得策ではないと判断しました
document.querySelector('document').focus();
等としても Background Scripts からDOM指定をすると Background Scripts に紐付けられた Background Page を拾ってしまうので実際に開いているタブのDOMは拾えずにエラーとなるchrome.tabs.sendMessage()
でクリップボードへ貼り付けたいテキストを request
としてメッセージ送信で投げることにしましたちなみに markdown-function 使用のため Webpack を使用しました。
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
// メッセージとして送信されたクリップボードに貼り付けたいテキストをそのままレスポンスに設定して返却
navigator.clipboard.writeText(request);
sendResponse({
value: request,
});
});
ということで、上述した通り Background Scripts (Event Scripts) から投げられたメッセージを受け取って navigator.clipboard.writeText()
でクリップボードに貼り付ける側のコード。こちらは述べた通りの役割のみなのでシンプルです。
お作法として元の Background Scripts (Event Scripts) にレスポンスを返す形になるので、 request
で投げられたものをそのまま返しています (返却後も console.log()
しているだけですが)。
これで望む動作の Chrome拡張機能 を作ることができました。
一度 Background Scripts (Event Scripts) と Content Scripts の違いや権限周りを履修していたのでそこそこスムーズに進めることができたと思います。
毎度恒例の名前について。
今回はリンクを生成するということで鎖を連想しました。
で、色々調べたところ
鎖を楽器として使用する吹奏楽の楽曲があることを知りました。冒頭部で本当に鎖を落として音を出していますね……。
この楽曲に着想を得てアイルランドの俗称である「エメラルドの島 (Emerald Isle)」としました。
各種関数やファイル名もこれに関連したものからチョイス。
Crieitは誰でも投稿できるサービスです。 是非記事の投稿をお願いします。どんな軽い内容でも投稿できます。
また、「こんな記事が読みたいけど見つからない!」という方は是非記事投稿リクエストボードへ!
こじんまりと作業ログやメモ、進捗を書き残しておきたい方はボード機能をご利用ください。
ボードとは?
コメント