![Backlogで「リンク付きの課題キーと件名」を取得するボタンを追加するChrome拡張機能を作ってみた](https://devio2023-media.developers.io/wp-content/uploads/2019/07/google-chrome-eyecatch.jpg)
Backlogで「リンク付きの課題キーと件名」を取得するボタンを追加するChrome拡張機能を作ってみた
データアナリティクス事業本部のueharaです。
今回はBacklogで「リンク付きの課題キーと件名」を取得するボタンを追加するChrome拡張機能を作ってみたいと思います。
何がしたいのか?
Backlogには標準機能として課題キーと件名をコピーするボタンがあります。
しかし、少なくともMac Bookではこのボタンでコピーを行ったあと、Google Docsに貼り付けると次のようになります。
うーむ、、、
私としては、以下のようなプレーンなリンク付きテキストで貼り付けられるのが希望です。
今までは「①一旦書式無しテキストで貼り付け ⇒ ②課題チケットに戻りURLをコピー ⇒ ③テキストにリンクを紐付け」という手順を踏んでこの形にしていたのですが、流石に面倒になってきたので、今回Chromeの拡張機能を作ってみました。
どう対応したのか?
標準ボタンの隣に1つボタンを追加し、1クリックで上記の「プレーンなリンク付きテキスト」を取得することができるChromeの拡張機能を作成しました。
これにより今までのストレスが無くなり、快適にGoogle Docsに課題チケットを転記することができるようになりました。
実装
ファイル構成
今回作成した拡張機能のファイル構成は次の通りです。
my_extension ├ css | └ style.css ├ icons | ├ icon16.png | ├ icon48.png | └ icon128.png ├ js | └ content.js └ manifest.json
manifest.json
詳しい説明は省略しますが、Chromeの拡張機能を作る際にはまず manifest.json
が必要になります。
現状使われているものとしてはmanifest V2とmanifest V3がありますが、V2の方は2023年6月に例外なく動作しなくなります。
今から作成する場合はV3にしておく方が無難です。
ということで、以下のように書いてみました。
{ "name": "BacklogLinkCopy", "version": "0.1.0", "manifest_version": 3, "description": "For Backlog Link Copy", "icons": { "16": "icons/icon16.png", "48": "icons/icon48.png", "128": "icons/icon128.png" }, "host_permissions": [ "https://<クラメソのサブドメイン>.backlog.jp/*" ], "permissions": [ "clipboardWrite", "activeTab" ], "content_scripts": [{ "matches": [ "https://<クラメソのサブドメイン>.backlog.jp/*" ], "css": [ "css/style.css" ], "js": [ "js/content.js" ], "run_at": "document_end", "all_frames": true }] }
今回、ターゲットのURLとして特定ドメインのBacklogに限定していますが、他のBacklogでも使いたい場合はURLを追加するであったり、*
を使うなどで対応することができます。
それぞれの記載についてはなんとなく文字からイメージがつくかと思いますが、より詳しく知りたい方は公式のドキュメントをご確認ください。
style.css
追加するボタンのスタイルを決めます。
今回はできるだけ標準のボタンと近い形となるよう、以下のように設定しました。
.new-button { position: absolute; margin-left: 7px; background-color: #3ea8ff; color: white; line-height: 1; height: 32px; width: 32px; text-align: center; border: none; border-radius: 50%; font-size: 18px; cursor: pointer; } .new-button:active{ background-color: #0f83fd; color: white; }
content.js
こちらが今回のメインとなる部分です。
console.log("[DEBUG] load extension"); window.addEventListener('load', main, false); window.addEventListener('popstate', main); window.addEventListener('pushstate', main); window.addEventListener('replacestate', main); const loadFontAwesome = () => { let link = document.createElement('link'); link.rel = 'stylesheet'; link.href = 'https://use.fontawesome.com/releases/v5.13.1/css/all.css'; document.head.insertAdjacentElement('beforeEnd', link); }; function main(event) { const jsInitCheckTimer = setInterval(jsLoaded, 100); // fontawesomeのロード loadFontAwesome(); function jsLoaded() { if (document.querySelector('#copyKey-help') != null) { clearInterval(jsInitCheckTimer); // ボタンを追加する場所を選択 let existingButton = document.querySelector('#copyKey-help'); // ボタン要素を作成 let newButton = document.createElement('button'); // ボタンのテキストを設定 newButton.innerHTML = '<i class="far fa-copy"></i>'; newButton.classList.add('new-button'); // ボタンを追加 existingButton.appendChild(newButton); // ボタンが押された時の処理 newButton.addEventListener('click', function() { let currentUrl = window.location.href; let ticket_key = document.querySelector(".ticket__key-number").innerText; let subject = document.querySelector(".markdown-body").innerText; let title = ticket_key + " " + subject; let htmlLink = '<a href="' + currentUrl + '">' + title + '</a>'; const blob = new Blob([htmlLink], { type: 'text/html' }); const blobPlain = new Blob([htmlLink], { type: 'text/plain' }); const data = [new window.ClipboardItem({ 'text/html': blob, 'text/plain': blobPlain })]; navigator.clipboard.write(data) .then(function() { console.log('Title copied to clipboard'); }) .catch(function(error) { console.error('Failed to copy title: ', error); }); }); } } }
そこまで難しい処理は無いですが、1点だけ注意したい部分があります。
今回標準機能のボタン #copyKey-help
の隣に新しいボタンを追加したいのですが、標準ボタンは動的に生成される要素のため、単純に.appendChild(newButton)
をしようとすると高確率でエラーとなります(標準ボタンの生成前にappend処理が動いてしまう)。
したがって、動的なページの読み込みが完了してからChrome拡張機能を実行するようにしています。
また、今回ボタンのアイコンにFontAwesomeを利用したかったので、ヘッダにスタイルシートを追加する処理も記載しています。
冒頭で示した「プレーンなリンク付きテキスト」は以下のような形で作成することができます。
let htmlLink = '<a href="' + currentUrl + '">' + title + '</a>'; const blob = new Blob([htmlLink], { type: 'text/html' }); const blobPlain = new Blob([htmlLink], { type: 'text/plain' }); const data = [new window.ClipboardItem({ 'text/html': blob, 'text/plain': blobPlain })];
作成した拡張機能の読み込み
作成したオレオレ拡張機能の読み込みは、Chromeの拡張機能のページにあるデベロッパーモードをONにし、「パッケージ化されていない拡張機能を読み込む」ボタンから実施することができます。
その後、my_extension
フォルダを選択すれば拡張機能の読み込みは完了です。
※私はアイコンをBacklogのロゴに設定したので、上記のような表示となっています。(my_extensionフォルダ配下のiconsに配置している.png
ファイルが表示されるアイコンになります)
最後に
今回は、Backlogで「リンク付きの課題キーと件名」を取得するボタンを追加するChrome拡張機能を作ってみました。
本記事がどなたかの参考になりましたら幸いです。
参考文献
- Welcome to Manifest V3
- google chrome extension - How to get a content script to load AFTER a page's Javascript has executed? - Stack Overflow
- Chrome 拡張機能で FontAwesome を使う
- javascript - TypeError: Failed to construct 'ClipboardItem': Failed to convert value to 'Blob' - Stack Overflow
- JavaScriptのClipboard APIでリッチテキスト(書式付きテキスト)をコピーする