tag:crieit.net,2005:https://crieit.net/tags/chrome-extension/feed 「chrome-extension」の記事 - Crieit Crieitでタグ「chrome-extension」に投稿された最近の記事 2022-01-04T23:14:56+09:00 https://crieit.net/tags/chrome-extension/feed tag:crieit.net,2005:PublicArticle/17922 2022-01-04T23:14:56+09:00 2022-01-04T23:14:56+09:00 https://crieit.net/posts/chrome-extension-navigator-clipboard-failed-in-http-site-20220104 (Chrome拡張機能) navigator.clipboard を利用したクリップボードへの貼り付けが httpサイト では失敗する <p>先日作成した Chrome拡張機能 が <code>http</code>サイト では上手く動かないことに気付いたので修正しました。</p> <h2 id="経緯"><a href="#%E7%B5%8C%E7%B7%AF">経緯</a></h2> <p>早速作成した Chrome拡張機能 を運用し始めたのですが、一部のサイトでは次のエラーを出力して上手く動かないことが分かりました。</p> <blockquote> <p>Unchecked runtime.lastError: The message port closed before a response was received.</p> </blockquote> <h2 id="原因"><a href="#%E5%8E%9F%E5%9B%A0">原因</a></h2> <p>いくつかのサイトを試験した結果、 <code>http</code>サイト ではこのエラーが出力されることが分かりました。</p> <p>そこで調べてみると……</p> <blockquote> <p>WebExtension の場合、clipboardRead や clipboardWrite パーミッションを要求することで clipboard.readText() や clipboard.writeText() を使うことができます。HTTPサイトに適用されたコンテンツスクリプトは、Clipboard オブジェクトにアクセスすることはできません。</p> <p><a target="_blank" rel="nofollow noopener" href="https://developer.mozilla.org/ja/docs/Web/API/Clipboard">Clipboard - Web API | MDN</a></p> </blockquote> <p>ビンゴ。 <code>http</code>サイト の Content Script では <code>navigator.clipboard</code> へアクセスできないようです。</p> <h2 id="対処"><a href="#%E5%AF%BE%E5%87%A6">対処</a></h2> <p><code>navigator.clipboard</code> へアクセスできないとなると、手っ取り早いのは <code>document.execCommand('copy')</code> によるクリップぼ度貼り付けです。</p> <p>今回は <code>http</code>サイト という基本レガシーと想定される環境への対処なので、 <code>document.execCommand('copy')</code> で妥協しておきますかね……という感じです。</p> <h3 id="chain.js"><a href="#chain.js">chain.js</a></h3> <pre><code class="js">- chrome.tabs.sendMessage(tab.id, clipText, function(response) { - console.log(response.value); + chrome.tabs.sendMessage( + tab.id, + { + text: clipText, + url: tab.url, + }, + function(response) { + console.log(response.value); </code></pre> <p><code>chrome.tabs.sendMessage()</code> の第二引数は元はシンプルにクリップボードに貼り付けたいテキストを投げていましたが、今回は <code>http://</code> か <code>https://</code> かの判定をしたかったのでURLのみのシンプルなテキストも送ることにしました。そこで、Stringだった引数をObjectに変更。</p> <h3 id="smith.js"><a href="#smith.js">smith.js</a></h3> <pre><code class="js"> chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) { // メッセージとして送信されたクリップボードに貼り付けたいテキストをそのままレスポンスに設定して返却 - navigator.clipboard.writeText(request); + if(request.url.toLowerCase().startsWith('https://')) { + navigator.clipboard.writeText(request.text); + } + else { + const inputID = 'chromeExtension-emeraldIsle-clipText'; + console.log(document.querySelector(`#${inputID}`)) + if(document.querySelector(`#${inputID}`) === null) { + const $input = document.createElement('input'); + $input.setAttribute('type', 'text'); + $input.setAttribute('id', inputID); + $input.setAttribute('style', 'position: absolute; left: -100vw; top: 0'); + document.body.appendChild($input); + } + const $inputDom = document.querySelector(`#${inputID}`); + $inputDom.value = request.text; + $inputDom.select(); + document.execCommand('copy'); + } sendResponse({ - value: request, + value: request.text, }); + return true; }); </code></pre> <p>content Scripts 側を大改造。元々は <code>navigator.clipboard.writeText(request);</code> のみのシンプルな内容でしたが、次のように処理を変更。</p> <ol> <li>URLに <code>https://</code> (大文字小文字区別せず) で始まるかどうかを判定</li> <li>始まるならば今まで通りの <code>navigator.clipboard.writeText(request.text);</code> で貼り付け</li> <li>始まらないならば次の処理を実行 <ul> <li>もし指定したIDの要素が存在しないならば <ul> <li>ID付与、画面外領域に <code>input</code>要素 を追加</li> </ul></li> <li>再度指定したIDの <code>input</code>要素 を取得、値にクリップボードに貼り付けたいリンク文字列をセット</li> <li><code>document.execCommand('copy')</code> でクリップボードにコピー</li> </ul></li> </ol> <p>これで <code>http</code>サイト でもリンク文字列をクリップボードに貼り付けられるようになりました。</p> <h2 id="参考"><a href="#%E5%8F%82%E8%80%83">参考</a></h2> <h3 id="Unchecked runtime.lastError: The message port closed before a response was received."><a href="#Unchecked+runtime.lastError%3A+The+message+port+closed+before+a+response+was+received.">Unchecked runtime.lastError: The message port closed before a response was received.</a></h3> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://onoredekaiketsu.com/unchecked-runtime-lasterror-with-chrome/">Chromeのデベロッパーツールで「Unchecked runtime.lastError:」 | 己で解決!泣かぬなら己で鳴こうホトトギス</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://qiita.com/noenture/items/3978f638f2ffb8ff0995">Unchecked runtime.lastError: The message port closed before a response was received. を回避した一例 - Qiita</a></li> </ul> <h3 id="navigator.clipboard へのアクセス"><a href="#navigator.clipboard+%E3%81%B8%E3%81%AE%E3%82%A2%E3%82%AF%E3%82%BB%E3%82%B9">navigator.clipboard へのアクセス</a></h3> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://developer.mozilla.org/ja/docs/Web/API/Clipboard">Clipboard - Web API | MDN</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://note.affi-sapo-sv.com/js-clipbord-copy.php">【JavaScript】 クリップボードへのコピー</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://propg.ee-mall.info/%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0/javascript/js-http%E7%92%B0%E5%A2%83%E3%81%A7%E3%81%AFnavigator-clipboard-writetext%E3%81%8C%E3%82%A8%E3%83%A9%E3%83%BC%E3%81%AB%E3%81%AA%E3%82%8B/">[JS] http環境ではnavigator.clipboard.writeTextがエラーになる | プロプログラマ -Flex,Air,C#,Oracle,HTML5+JS-</a></li> </ul> <h3 id="document.execCommand"><a href="#document.execCommand">document.execCommand</a></h3> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://developer.mozilla.org/ja/docs/Mozilla/Add-ons/WebExtensions/Interact_with_the_clipboard#reading_from_the_clipboard">クリップボードとのやりとり - Mozilla | MDN</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://developer.mozilla.org/ja/docs/Web/API/Document/execCommand#commands">Document.execCommand() - Web API | MDN</a></li> </ul> <h3 id="JavaScript"><a href="#JavaScript">JavaScript</a></h3> <h4 id="DOM要素の有無"><a href="#DOM%E8%A6%81%E7%B4%A0%E3%81%AE%E6%9C%89%E7%84%A1">DOM要素の有無</a></h4> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://qiita.com/mitsuhiro_K/items/7d5cef1f4316c2080fa7">JavaScriptで要素が存在するかtrue\/falseで知りたい時どうするか? - Qiita</a></li> </ul> <h4 id="テキストボックスに値をセット"><a href="#%E3%83%86%E3%82%AD%E3%82%B9%E3%83%88%E3%83%9C%E3%83%83%E3%82%AF%E3%82%B9%E3%81%AB%E5%80%A4%E3%82%92%E3%82%BB%E3%83%83%E3%83%88">テキストボックスに値をセット</a></h4> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://qiita.com/mitsuhiro_K/items/7d5cef1f4316c2080fa7">JavaScriptで要素が存在するかtrue\/falseで知りたい時どうするか? - Qiita</a></li> </ul> <h4 id="要素に属性をセット"><a href="#%E8%A6%81%E7%B4%A0%E3%81%AB%E5%B1%9E%E6%80%A7%E3%82%92%E3%82%BB%E3%83%83%E3%83%88">要素に属性をセット</a></h4> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://developer.mozilla.org/ja/docs/Web/API/Element/setAttribute">element.setAttribute - Web API | MDN</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://developer.mozilla.org/ja/docs/Web/API/Document_Object_Model/Traversing_an_HTML_table_with_JavaScript_and_DOM_Interfaces">JavaScript と DOM インターフェイスによる HTML の表の操作 - Web API | MDN</a></li> </ul> <h4 id="body の末尾に DOM を挿入"><a href="#body+%E3%81%AE%E6%9C%AB%E5%B0%BE%E3%81%AB+DOM+%E3%82%92%E6%8C%BF%E5%85%A5">body の末尾に DOM を挿入</a></h4> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://www.task-notes.com/entry/20161020/1476974565">【JavaScript】要素を追加するinsertBeforeとappendChildについて - TASK NOTES</a></li> </ul> <h4 id="startWith()"><a href="#startWith%28%29">startWith()</a></h4> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/String/startsWith">String.prototype.startsWith() - JavaScript | MDN</a></li> </ul> <h4 id="toLowerCase()"><a href="#toLowerCase%28%29">toLowerCase()</a></h4> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/String/toLowerCase">String.prototype.toLowerCase() - JavaScript | MDN</a></li> </ul> <h3 id="chrome.tabs.sendMessage, 第二引数 message の型"><a href="#chrome.tabs.sendMessage%2C+%E7%AC%AC%E4%BA%8C%E5%BC%95%E6%95%B0+message+%E3%81%AE%E5%9E%8B">chrome.tabs.sendMessage, 第二引数 message の型</a></h3> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://developer.chrome.com/docs/extensions/reference/tabs/">chrome.tabs - Chrome Developers</a></li> </ul> <p><code>any</code> だった。</p> <h3 id="(未使用) html-loader"><a href="#%28%E6%9C%AA%E4%BD%BF%E7%94%A8%29+html-loader">(未使用) html-loader</a></h3> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://chocolat5.com/tips/webpack-html-template/">Webpackを使用してhtmlの共通部分をテンプレート化 | chocolat | Freelance Frontend Engineer</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://www.memory-lovers.blog/entry/2018/12/10/003219">【小ネタ】webpackでhtmlも扱う - くらげになりたい。</a></li> </ul> <p>一瞬 Background Page を作ってそのテキストボックスにいったん貼り付けて、その値を取得する方法を考えました。</p> <p>今回 Webpack 使用だったので <code>html-loader</code> 案件か、と思いましたが、回避しました。</p> arm-band tag:crieit.net,2005:PublicArticle/17915 2022-01-03T23:28:12+09:00 2022-01-03T23:29:08+09:00 https://crieit.net/posts/chrome-extension-copy-title-and-url-to-clipboard-20220103 (Chrome拡張機能) 右クリックのメニューから現在開いているタブのタイトルとURLをクリップボードに貼り付ける <p>よんどころなき事情により、新年早々に Chrome拡張機能を作成してみました。</p> <h2 id="経緯"><a href="#%E7%B5%8C%E7%B7%AF">経緯</a></h2> <p><a target="_blank" rel="nofollow noopener" href="https://labor.ewigleere.net/2021/12/31/create-link-note/">(Chrome拡張機能) Create Link の挙動が不安定</a>の記事に書いた通り、 Chrome拡張機能 の <a target="_blank" rel="nofollow noopener" href="https://chrome.google.com/webstore/detail/create-link/gcmghdmnkfdbncmnmlkkglmnnhagajbm">Create Link - Chromeウェブストア</a> が挙動不安定になってしまいました。</p> <p>ブログを書く際に参考記事をリストアップしたり、自分の活動にはこの機能はなくてはならないのでそれがままならないというのは不便極まりない。</p> <p>そこで、代替となる Chrome拡張機能 を自作してみることにしました。</p> <h2 id="成果物"><a href="#%E6%88%90%E6%9E%9C%E7%89%A9">成果物</a></h2> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://github.com/arm-band/chrome-extension-emerald-isle">arm-band\/chrome-extension-emerald-isle</a></li> </ul> <p><a href="https://crieit.now.sh/upload_images/f56b0d4a5b2945b8216bad8d6a0cf15e61d306f64f80a.jpg" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/f56b0d4a5b2945b8216bad8d6a0cf15e61d306f64f80a.jpg?mw=700" alt="自作の拡張機能を入れてコンテキストメニューを開いたときのキャプチャ画像" /></a></p> <h2 id="機能"><a href="#%E6%A9%9F%E8%83%BD">機能</a></h2> <p>Create Link の代替を想定したため、機能はこれに準じます。</p> <p>ただし、貼り付けるコードのカスタマイズの必要はない (プレーン、HTML、Markdown の3種があれば充分) ので設定画面等の自前でカスタマイズできる機能は全てオミット。</p> <p>ページを開いている状態で右クリックして、コンテキストメニューから上述3種の形式でリンクをクリップボードに貼り付けられれば良いです。</p> <h2 id="コード(要点)"><a href="#%E3%82%B3%E3%83%BC%E3%83%89%28%E8%A6%81%E7%82%B9%29">コード(要点)</a></h2> <h3 id="manifest.json"><a href="#manifest.json">manifest.json</a></h3> <pre><code class="json">{ "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" } } </code></pre> <p>特筆すべき事項はあまりないですが</p> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://labor.ewigleere.net/2021/04/11/open-ie-from-chrome-extension/">Chrome拡張機能 から IE を開く</a>等の実績から、幾分か触り慣れているバージョンの<code>2</code>を選択</li> <li><code>permissions</code> はタブ、クリップボードへの書き込み、右クリックメニュー(コンテキストメニュー)等</li> <li>後述しますが、クリップボードへの貼り付けは Background Scripts(Event Scripts) からアクセスはできずに Content Scripts に持ち込む必要があったため、2つのスクリプトに分かれています (結果、 <code>background</code>, <code>content_scripts</code> の2つのフィールドが存在) <ul> <li><code>content_scripts</code> を実行させるURLは全てのURLで良いので <code>*://*/*</code> 指定 (<code>matches</code> フィールド)</li> </ul></li> </ul> <p>といったところでしょうか。</p> <h3 id="chain.js (Background / Event Scripts)"><a href="#chain.js+%28Background+%2F+Event+Scripts%29">chain.js (Background / Event Scripts)</a></h3> <pre><code class="js">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()); </code></pre> <ul> <li><code>chrome.contextMenus.create()</code> でコンテキストメニューの中身を作成</li> <li><code>chrome.contextMenus.onClicked.addListener()</code> にコンテキストメニューがクリックされた場合の処理を記述 <ul> <li>コンテキストメニューの各項目に記述した <code>id</code> の値で条件分岐してプレーン,HTML,Markdownの3種のリンクのテキストを生成</li> <li>Markdown 形式に関してはブラケットや括弧をエスケープ処理したかったので、<a target="_blank" rel="nofollow noopener" href="https://www.npmjs.com/package/markdown-function">markdown-function</a>を利用させていただきました</li> </ul></li> <li>軽く先述した通り、 Background Scripts (Event Scripts) からはクリップボードへのアクセス権限がないため、このスクリプトの中で <code>navigator.clipboard.writeText()</code> を発動させようとしても失敗してしまいます (<code>Uncaught (in promise) DOMException: Document is not focused.</code> というエラー文が出力される) <ul> <li>かといってクリップボードへ貼り付ける系の記事で散見された <code>Document.execCommand</code> はDOMの指定が必要でこれも Content Scripts 側の動作と思われる上、<a target="_blank" rel="nofollow noopener" href="https://developer.mozilla.org/ja/docs/Web/API/Document/execCommand">Document.execCommand() - Web API | MDN</a>に <code>非推奨: この機能は非推奨になりました。</code> と記載されているため、今からこの方法を採用するのは得策ではないと判断しました <ul> <li>しかも開いているタブにフォーカスが当たっている必要がありますが、<code>document.querySelector('document').focus();</code> 等としても Background Scripts からDOM指定をすると Background Scripts に紐付けられた Background Page を拾ってしまうので実際に開いているタブのDOMは拾えずにエラーとなる</li> </ul></li> <li>Clipboard.js もインスタンス化の際にDOM指定が必要なのでこれも没</li> <li>色々調べた結果、 Content Scripts へ経由させる必要がありそうなことが分かったため <code>chrome.tabs.sendMessage()</code> でクリップボードへ貼り付けたいテキストを <code>request</code> としてメッセージ送信で投げることにしました</li> </ul></li> </ul> <p>ちなみに markdown-function 使用のため Webpack を使用しました。</p> <h3 id="smith.js"><a href="#smith.js">smith.js</a></h3> <pre><code class="js">chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) { // メッセージとして送信されたクリップボードに貼り付けたいテキストをそのままレスポンスに設定して返却 navigator.clipboard.writeText(request); sendResponse({ value: request, }); }); </code></pre> <p>ということで、上述した通り Background Scripts (Event Scripts) から投げられたメッセージを受け取って <code>navigator.clipboard.writeText()</code> でクリップボードに貼り付ける側のコード。こちらは述べた通りの役割のみなのでシンプルです。</p> <p>お作法として元の Background Scripts (Event Scripts) にレスポンスを返す形になるので、 <code>request</code> で投げられたものをそのまま返しています (返却後も <code>console.log()</code> しているだけですが)。</p> <p>これで望む動作の Chrome拡張機能 を作ることができました。</p> <p>一度 Background Scripts (Event Scripts) と Content Scripts の違いや権限周りを履修していたのでそこそこスムーズに進めることができたと思います。</p> <h2 id="(余談) 名前の由来"><a href="#%28%E4%BD%99%E8%AB%87%29+%E5%90%8D%E5%89%8D%E3%81%AE%E7%94%B1%E6%9D%A5">(余談) 名前の由来</a></h2> <p>毎度恒例の名前について。</p> <p>今回はリンクを生成するということで鎖を連想しました。</p> <p>で、色々調べたところ</p> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://www.youtube.com/watch?v=-GvacwBftIs">伝説のアイルランド : Ireland Of Legend and Lore ~ 陸上自衛隊中央音楽隊 - YouTube</a></li> </ul> <p>鎖を楽器として使用する吹奏楽の楽曲があることを知りました。冒頭部で本当に鎖を落として音を出していますね……。</p> <ul> <li><a target="_blank" rel="nofollow noopener" href="http://www.worldfolksong.com/classical/wind-band/ireland-legend.htm">伝説のアイルランド 吹奏楽曲 - 世界の民謡・童謡</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://en.wikipedia.org/wiki/Siege_of_Cahir_Castle">Siege of Cahir Castle - Wikipedia</a></li> </ul> <p>この楽曲に着想を得てアイルランドの俗称である「エメラルドの島 (Emerald Isle)」としました。</p> <p>各種関数やファイル名もこれに関連したものからチョイス。</p> <h2 id="参考"><a href="#%E5%8F%82%E8%80%83">参考</a></h2> <h3 id="Content Scirpts, Background Script (Event Scripts)"><a href="#Content+Scirpts%2C+Background+Script+%28Event+Scripts%29">Content Scirpts, Background Script (Event Scripts)</a></h3> <ul> <li>過去記事: <a target="_blank" rel="nofollow noopener" href="https://labor.ewigleere.net/2021/04/11/open-ie-from-chrome-extension/">Chrome拡張機能 から IE を開く</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://www.sukerou.com/2020/11/chrome_26.html">Chrome拡張機能!コンテキストメニューでクリックされた要素を取得する方法-スケ郎のお話</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://qiita.com/sakaimo/items/5e41d6b2ad8d7ee04b12">Chrome Extension の作り方 (最終話: メッセージパッシング) - Qiita</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://yaraneba.com/extensions-key-binding/">キー割り当てをカスタマイズする拡張機能を自作してみる - やらねば.com</a></li> </ul> <h3 id="Content Scripts"><a href="#Content+Scripts">Content Scripts</a></h3> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://developer.mozilla.org/ja/docs/Mozilla/Add-ons/WebExtensions/manifest.json/content_scripts">content_scripts - Mozilla | MDN</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://developer.mozilla.org/ja/docs/Mozilla/Add-ons/WebExtensions/Match_patterns">マッチパターン - Mozilla | MDN</a></li> </ul> <h3 id="chrome.tabs"><a href="#chrome.tabs">chrome.tabs</a></h3> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://developer.chrome.com/docs/extensions/reference/tabs/">chrome.tabs - Chrome Developers</a></li> </ul> <h3 id="clipboard API"><a href="#clipboard+API">clipboard API</a></h3> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://developer.mozilla.org/en-US/docs/Web/API/Clipboard">Clipboard - Web APIs | MDN</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://developer.mozilla.org/en-US/docs/Web/API/Clipboard/writeText">Clipboard.writeText() - Web APIs | MDN</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://qiita.com/eyuta/items/859d1e8952eef4d8f061">【Javascript】Markdown形式のウェブページのリンクを、ブックマークレットで取得する - Qiita</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://stackoverflow.com/questions/54386279/how-can-i-use-navigator-clipboard-readtext-in-a-chrome-extension">firefox - How can I use navigator.clipboard.readText() in a Chrome extension? - Stack Overflow</a></li> </ul> <h3 id="権限"><a href="#%E6%A8%A9%E9%99%90">権限</a></h3> <ul> <li>v2: <a target="_blank" rel="nofollow noopener" href="https://developer.chrome.com/docs/extensions/mv2/declare_permissions/">Declare permissions - Chrome Developers</a> <ul> <li>v3: <a target="_blank" rel="nofollow noopener" href="https://developer.chrome.com/docs/extensions/mv3/declare_permissions/">Declare permissions - Chrome Developers</a></li> </ul></li> </ul> <h3 id="右クリックメニュー (Context Menu)"><a href="#%E5%8F%B3%E3%82%AF%E3%83%AA%E3%83%83%E3%82%AF%E3%83%A1%E3%83%8B%E3%83%A5%E3%83%BC+%28Context+Menu%29">右クリックメニュー (Context Menu)</a></h3> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://developer.chrome.com/docs/extensions/reference/contextMenus/">chrome.contextMenus - Chrome Developers</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://qiita.com/plumfield56/items/e98c247888d82a79c7ea">Chrome拡張機能で右クリックメニューを作る方法 - Qiita</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/apps/samples/context-menu">chrome-extensions-samples\/apps\/samples\/context-menu at main · GoogleChrome\/chrome-extensions-samples</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://github.com/GoogleChrome/chrome-extensions-samples/blob/main/apps/samples/context-menu/main.js">chrome-extensions-samples\/main.js at main · GoogleChrome\/chrome-extensions-samples</a></li> </ul> <h3 id="Markdown のリンク生成・エスケープ"><a href="#Markdown+%E3%81%AE%E3%83%AA%E3%83%B3%E3%82%AF%E7%94%9F%E6%88%90%E3%83%BB%E3%82%A8%E3%82%B9%E3%82%B1%E3%83%BC%E3%83%97">Markdown のリンク生成・エスケープ</a></h3> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://www.npmjs.com/package/markdown-function">markdown-function - npm</a></li> </ul> <h3 id="(未使用) Clipboard.js"><a href="#%28%E6%9C%AA%E4%BD%BF%E7%94%A8%29+Clipboard.js">(未使用) Clipboard.js</a></h3> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://qiita.com/eyuta/items/859d1e8952eef4d8f061">【Javascript】Markdown形式のウェブページのリンクを、ブックマークレットで取得する - Qiita</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://www.npmjs.com/package/clipboard">clipboard - npm</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://qiita.com/Cesaroshun/items/776c44ac25f21c37b67e">Clipboard.jsの使い方 - Qiita</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://qiita.com/R_TES_/items/194bc78ad73a29daef5f">Google Chrome 拡張機能の開発 - 2 - 早速自作したものに機能追加していく - Qiita</a></li> </ul> <h3 id="(未使用) chrome.clipboard"><a href="#%28%E6%9C%AA%E4%BD%BF%E7%94%A8%29+chrome.clipboard">(未使用) chrome.clipboard</a></h3> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://developer.chrome.com/docs/extensions/reference/clipboard/">chrome.clipboard - Chrome Developers</a></li> </ul> <h3 id="(未使用) Document.execCommand()"><a href="#%28%E6%9C%AA%E4%BD%BF%E7%94%A8%29+Document.execCommand%28%29">(未使用) Document.execCommand()</a></h3> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://developer.mozilla.org/ja/docs/Web/API/Document/execCommand">Document.execCommand() - Web API | MDN</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://developer.mozilla.org/ja/docs/Mozilla/Add-ons/WebExtensions/Interact_with_the_clipboard#reading_from_the_clipboard">クリップボードとのやりとり - Mozilla | MDN</a></li> </ul> <h3 id="(未使用) その他の clipboard"><a href="#%28%E6%9C%AA%E4%BD%BF%E7%94%A8%29+%E3%81%9D%E3%81%AE%E4%BB%96%E3%81%AE+clipboard">(未使用) その他の clipboard</a></h3> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://github.com/GoogleChrome/chrome-extensions-samples/blob/e716678b67fd30a5876a552b9665e9f847d6d84b/apps/samples/text-editor/lib/ace/keyboard/textinput.js">chrome-extensions-samples\/textinput.js at e716678b67fd30a5876a552b9665e9f847d6d84b · GoogleChrome\/chrome-extensions-samples</a></li> </ul> <h3 id="(未使用) HTMLElement.focus()"><a href="#%28%E6%9C%AA%E4%BD%BF%E7%94%A8%29+HTMLElement.focus%28%29">(未使用) HTMLElement.focus()</a></h3> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://developer.mozilla.org/ja/docs/Web/API/HTMLElement/focus">HTMLElement.focus() - Web API | MDN</a></li> </ul> <h3 id="(未使用) Markdown のエスケープ"><a href="#%28%E6%9C%AA%E4%BD%BF%E7%94%A8%29+Markdown+%E3%81%AE%E3%82%A8%E3%82%B9%E3%82%B1%E3%83%BC%E3%83%97">(未使用) Markdown のエスケープ</a></h3> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://note.crohaco.net/2018/markdown-xss/">Markdownのクロスサイトスクリプティングに気をつけろ! - くろのて</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://qumeru.com/magazine/108">JavaScriptの正規表現でエスケープが必要な文字列の一覧を紹介! | Qumeruマガジン</a></li> </ul> arm-band tag:crieit.net,2005:PublicArticle/17746 2021-11-10T13:33:47+09:00 2022-05-12T19:10:56+09:00 https://crieit.net/posts/Web-Google-Chrome-Notta-Audio-Clipper 入れるとすぐWebページの音声コンテンツをテキスト化?おすすめGoogle Chrome拡張機能「Notta Audio Clipper」の活用方 <p>元記事:<a target="_blank" rel="nofollow noopener" href="https://www.notta.ai/blog/notta-audio-clipper-extension-guide">https://www.notta.ai/blog/notta-audio-clipper-extension-guide</a></p> <p><a href="https://crieit.now.sh/upload_images/9cfa78fc38e210e99b3e292ce59df382618b4b51cf780.png" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/9cfa78fc38e210e99b3e292ce59df382618b4b51cf780.png?mw=700" alt="image" /></a></p> <h1 id="Notta Audio Clipperとは?"><a href="#Notta+Audio+Clipper%E3%81%A8%E3%81%AF%EF%BC%9F">Notta Audio Clipperとは?</a></h1> <p>AI音声認識文字起こしサービス「Notta」の新しいChrome拡張機能は、Webページの音声をリアルタイムで録音し、文字起こしすることができます。文字起こし結果はNottaアカウントに保存し、どの端末でも確認できます。Web会議(Zoom、Google Meetなど)やYouTube動画の字幕起こし、在宅テープ起こし、お気に入りのポッドキャストの保存など、手作業による文字起こしの手間が省け、作業効率が大幅UP!</p> <p>‍</p> <h2 id="前提条件"><a href="#%E5%89%8D%E6%8F%90%E6%9D%A1%E4%BB%B6">前提条件</a></h2> <p>Google Chromeブラウザ<br /> Notta Audio Clipper拡張機能 <a target="_blank" rel="nofollow noopener" href="https://bit.ly/3jvP5O0">Chromeウェブストア>></a><br /> Notta アカウント 新規登録は<a target="_blank" rel="nofollow noopener" href="https://app.notta.ai/signup?language=ja">こちら</a><br /> ‍</p> <h1 id="Notta拡張機能をchromeに追加"><a href="#Notta%E6%8B%A1%E5%BC%B5%E6%A9%9F%E8%83%BD%E3%82%92chrome%E3%81%AB%E8%BF%BD%E5%8A%A0">Notta拡張機能をchromeに追加</a></h1> <p>‍</p> <p>Chromeのウェブストアの画面上部にある検索窓に「Notta」を入力して検索ください。画面の右上にある「Chromeに追加」ボタンをクリックして、拡張機能ブラウザに追加します。</p> <p>‍<a href="https://crieit.now.sh/upload_images/c902ef805427ce6191b927e17ab3e93f618b4b5b803cb.png" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/c902ef805427ce6191b927e17ab3e93f618b4b5b803cb.png?mw=700" alt="image" /></a><br /> <a href="https://crieit.now.sh/upload_images/992bbbcbf1953425eaa50e362f8975d3618b4b61a7b05.png" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/992bbbcbf1953425eaa50e362f8975d3618b4b61a7b05.png?mw=700" alt="image" /></a><br /> ‍</p> <p>追加した後、Chrome アドレスバーの横にある「拡張機能アイコン」をクリックください。「画びょう」アイコンをクリックと、ブラウザのツールバーに拡張機能が固定されます。</p> <p><a href="https://crieit.now.sh/upload_images/88fb27b04be9b95c1e859642aad965eb618b4b69c8abb.png" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/88fb27b04be9b95c1e859642aad965eb618b4b69c8abb.png?mw=700" alt="image" /></a><br /> <a href="https://crieit.now.sh/upload_images/22fb35cf5b0daed269bba45b45a286bc618b4b711e644.png" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/22fb35cf5b0daed269bba45b45a286bc618b4b711e644.png?mw=700" alt="image" /></a></p> <p>シークレットモードでも拡張機能を有効にしたいの場合、設定方法は簡単です。設定メニューを開く、「拡張機能」を選択したら、インストールされている拡張機能の一覧が表示されます。Notta拡張機能の「詳細」をクリックください。</p> <p>‍<a href="https://crieit.now.sh/upload_images/3dcdd87eba7f5d10dc4c09179a6cec4d618b4b77f2c96.png" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/3dcdd87eba7f5d10dc4c09179a6cec4d618b4b77f2c96.png?mw=700" alt="image" /></a><br /> <a href="https://crieit.now.sh/upload_images/b779cdd2eefdbe7c9b161bec4734c447618b4b7d924ad.png" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/b779cdd2eefdbe7c9b161bec4734c447618b4b7d924ad.png?mw=700" alt="image" /></a></p> <p>詳細場面で「シークレットモードでの実行を許可する」をONにします。</p> <p>‍<a href="https://crieit.now.sh/upload_images/15b8eaefd4792214aa4d4fabc52e8ea2618b4b8431724.png" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/15b8eaefd4792214aa4d4fabc52e8ea2618b4b8431724.png?mw=700" alt="image" /></a></p> <p>再び読み込みすると、Notta Audio Clipper拡張機能がシークレットモードでも有効になります。</p> <p><a href="https://crieit.now.sh/upload_images/87134956358479b9a4253a6bcf03dbab618b4b8a0521d.png" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/87134956358479b9a4253a6bcf03dbab618b4b8a0521d.png?mw=700" alt="image" /></a></p> <h1 id="準備完了!YouTube動画を文字起こししましょう"><a href="#%E6%BA%96%E5%82%99%E5%AE%8C%E4%BA%86%EF%BC%81YouTube%E5%8B%95%E7%94%BB%E3%82%92%E6%96%87%E5%AD%97%E8%B5%B7%E3%81%93%E3%81%97%E3%81%97%E3%81%BE%E3%81%97%E3%82%87%E3%81%86">準備完了!YouTube動画を文字起こししましょう</a></h1> <p>‍</p> <p>音声コンテンツを文字変換したいウェブページを開き、Nottaのロゴマークをクリックします。</p> <p>「このページの録音を開始します」ボタンをクリックすれば、流れている音声をレコードしはじめます。<strong>一度に5新規タブ</strong>まで同時に録音することが可能です。</p> <p>‍<a href="https://crieit.now.sh/upload_images/9d4cd53458032a67da75848f99a2cfb9618b4b9177238.png" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/9d4cd53458032a67da75848f99a2cfb9618b4b9177238.png?mw=700" alt="image" /></a><br /> <a href="https://crieit.now.sh/upload_images/cb8d43a804853ea4374032e2da5cbc9b618b4b97b7ad8.png" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/cb8d43a804853ea4374032e2da5cbc9b618b4b97b7ad8.png?mw=700" alt="image" /></a></p> <p>録音が終了後、「終了」ボタンをクリックします。</p> <p><a href="https://crieit.now.sh/upload_images/9998eb3de1bfeb10e90d99dbf1ba636d618b4b9e0c8e8.png" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/9998eb3de1bfeb10e90d99dbf1ba636d618b4b9e0c8e8.png?mw=700" alt="image" /></a></p> <h1 id="Notta Web版で文字起こし結果をチェック・編集"><a href="#Notta+Web%E7%89%88%E3%81%A7%E6%96%87%E5%AD%97%E8%B5%B7%E3%81%93%E3%81%97%E7%B5%90%E6%9E%9C%E3%82%92%E3%83%81%E3%82%A7%E3%83%83%E3%82%AF%E3%83%BB%E7%B7%A8%E9%9B%86">Notta Web版で文字起こし結果をチェック・編集</a></h1> <p>‍</p> <p>データはNottaアカウントに保存されます。 <a target="_blank" rel="nofollow noopener" href="https://app.notta.ai/signup?language=ja">Notta Web版</a>に登録すると、録音を確認したり、文字起こし結果を編集したり、メモ・画像を挿入したりすることができます。</p> <p>音声、テキストデータそれぞれの導出も可能です。また、データは複数デバイスにも同期するため、携帯やほかの端末にて随時振り返れます。</p> <p><a href="https://crieit.now.sh/upload_images/1af77b84f6b95d1c8b6678f778f0aea0618b4ba3cd340.png" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/1af77b84f6b95d1c8b6678f778f0aea0618b4ba3cd340.png?mw=700" alt="image" /></a></p> <hr /> <p>Nottaは無料体験できますので、試してみましょう。<br /> ‍<br /> ‍Web版<br /> ‍Google ChromeやMicrosoft Edgeブラウザから<a target="_blank" rel="nofollow noopener" href="http://www.notta.ai/">Web版</a>をアクセス<br /> ‍<br /> ‍Chrome拡張機能<br /> ‍Chrome web storeから<a target="_blank" rel="nofollow noopener" href="https://chrome.google.com/webstore/detail/notta-speech-to-text-tran/kdelkaogljjcbjffjmahedaobfjineig?hl=ja">Notta拡張機能</a>を追加<br /> ‍<br /> ‍アプリ版‍<br /> iOSアプリは<a target="_blank" rel="nofollow noopener" href="https://apps.apple.com/jp/app/notta-%E9%9F%B3%E5%A3%B0%E3%81%AE%E9%8C%B2%E9%9F%B3%E3%81%A8%E6%96%87%E5%AD%97%E8%B5%B7%E3%81%93%E3%81%97-ai%E9%9F%B3%E5%A3%B0%E8%AA%8D%E8%AD%98%E3%82%A2%E3%83%97%E3%83%AA/id1480649572">App Store</a>からダウンロード<br /> Androidアプリは<a target="_blank" rel="nofollow noopener" href="https://play.google.com/store/apps/details?id=com.langogo.transcribe&hl=ja&gl=US">Google Play</a>からダウンロード</p> Notta | 文字起こしサービス | AI音声認識 tag:crieit.net,2005:PublicArticle/17424 2021-06-21T22:21:42+09:00 2021-06-21T22:23:21+09:00 https://crieit.net/posts/chrome-extension-only-one-window 📝 Chrome 拡張で 1つのウインドウを使い回す方法 <p><a target="_blank" rel="nofollow noopener" href="https://chrome.google.com/webstore/detail/teemo-%F0%9F%92%95/alhdkgcgpmdfbidaapdlnmbhoanoijka">Teemo</a> という Chrome 拡張を開発したのですが、その際 1 つのウインドウを使い回す構成にしたいなと考えていました。</p> <p>例えば何も考えずに <code>chrome.windows.create</code> を Chrome 拡張を開くたびに呼び出すと、呼び出すたびにウインドウが新規作成されてしまいます。そうすると、都度画面に不要なウインドウが出てきて邪魔になるだけでなく、手動で不要なウインドウを消す作業をユーザーに強いることとなってしまいます。。🙃</p> <p>上記のような挙動が望まれるケースもあると思いますが、Teemo ではウインドウ間を頻繁に行き来するため、ショートカットを利用して拡張機能を呼び出すことを見込んでいました。そのため、ショートカットを利用して拡張機能を呼び出すたびにウインドウが新規作成され続ける挙動は望んでいませんでした。</p> <p>1 つのウインドウを使い回すためには、<code>chrome.windows.create</code> 時に作成される <code>window</code> の <code>id</code> を保持しておきます。その後、Chrome 拡張が呼び出されるたびに <code>window</code> が既に存在するかどうかを保持していた <code>id</code> を元にチェックします。既に <code>window</code> が存在していた場合はそれを使いまわします。存在していなかった場合は、<code>chrome.windows.create</code> で <code>window</code> を新規作成します。</p> <pre><code class="javascript">// background.js // window の id を保持しておくための変数 let vid = -1; chrome.browserAction.onClicked.addListener(function () { // vid の値を元に Chrome 拡張で開いた window の取得を試みる chrome.windows.get(vid, function (chromeWindow) { // エラーが無く、既に window が存在している場合は、 // そのステータスを { focused: true } にすることで最前面に呼び出す if (!chrome.runtime.lastError && chromeWindow) { chrome.windows.update(vid, { focused: true }); return; } // 上記以外のパターンでは window を新規作成する chrome.windows.create( { url: "index.html", type: "popup", }, function (window) { // 新規作成した window を使い回せるようにするため、 // vid 変数に window の id を保持しておく vid = window.id; } ); }); }); </code></pre> <p>上記コードで 1 つのウインドウを使い回すことが出来るようになるはずです。✅</p> nikaera tag:crieit.net,2005:PublicArticle/17395 2021-06-13T20:10:47+09:00 2021-06-13T20:10:47+09:00 https://crieit.net/posts/teemo-first-release 📔 チャットの短文作成に便利な Chrome 拡張機能を開発してみた <h1 id="はじめに 📝"><a href="#%E3%81%AF%E3%81%98%E3%82%81%E3%81%AB+%F0%9F%93%9D">はじめに 📝</a></h1> <p>最近とある事情により Twitter の DM を利用しているのですが、Slack などのように絵文字をショートカット入力できないことにフラストレーションが溜まってきていました。そのため、絵文字をショトカで入力可能にしてくれる Chrome 拡張機能を探したのですが見つけられませんでした。</p> <p>そこで、無いなら作ろうということで <a target="_blank" rel="nofollow noopener" href="https://chrome.google.com/webstore/detail/teemo-%F0%9F%92%95/alhdkgcgpmdfbidaapdlnmbhoanoijka?hl=ja&">Teemo</a> を開発しました。</p> <p>ソースコードは <a target="_blank" rel="nofollow noopener" href="https://github.com/nikaera/Teemo">GitHub 上で公開しています。</a> 何かご要望等ございましたら PR や Issue 作成頂けますと喜びます。Teemo の実際の挙動については下記の動画で確認できます 🎥</p> <p><a target="_blank" rel="nofollow noopener" href="https://www.youtube.com/watch?v=bJTHbzw1Ee4">Teemo 💕 - Quickly generate chat message with embedded emoji! 💖😆</a></p> <h1 id="考えていたこと 💭"><a href="#%E8%80%83%E3%81%88%E3%81%A6%E3%81%84%E3%81%9F%E3%81%93%E3%81%A8+%F0%9F%92%AD">考えていたこと 💭</a></h1> <p>今回 Teemo の開発を行うに当たり、考えていた点は下記になります。</p> <ul> <li>よくある <code>:</code> 入力からの絵文字ショートカットを導入する <ul> <li>Slack や GitHub、JIRA などではおなじみの入力方法 ⌨️</li> </ul></li> <li>パレットから選択する際は半角英数字で検索できるようにしたい <ul> <li>Twitter では日本語で検索しないと絵文字が探せない 🔍</li> <li>普段英数字で絵文字検索をするので目的の絵文字が見つけづらい 🕵️</li> </ul></li> <li>拡張機能を利用することで文章入力の煩わしさが増加することは避けたい <ul> <li>コピペや文章クリアの機能等にもショトカ利用できるようにしたい 💨</li> </ul></li> </ul> <p>プロトタイピングしながら友人に進捗をシェアしながら開発は進めていきました。本当は個人で利用する想定で進めていたのですが、割と評判が良かったため Chrome ウェブストアに公開するのを目標に動いていました。そして、Chrome ウェブストアで公開できるクオリティを目指して動いたことで満足のいく拡張機能が作れました。</p> <h1 id="使い方 ⚒️"><a href="#%E4%BD%BF%E3%81%84%E6%96%B9+%E2%9A%92%EF%B8%8F">使い方 ⚒️</a></h1> <p>Teemo の使い方について紹介いたします。</p> <h2 id="Teemo を Chrome 拡張機能として追加する 🛍️"><a href="#Teemo+%E3%82%92+Chrome+%E6%8B%A1%E5%BC%B5%E6%A9%9F%E8%83%BD%E3%81%A8%E3%81%97%E3%81%A6%E8%BF%BD%E5%8A%A0%E3%81%99%E3%82%8B+%F0%9F%9B%8D%EF%B8%8F">Teemo を Chrome 拡張機能として追加する 🛍️</a></h2> <p>まずは <a target="_blank" rel="nofollow noopener" href="https://chrome.google.com/webstore/detail/teemo-%F0%9F%92%95/alhdkgcgpmdfbidaapdlnmbhoanoijka?hl=ja&authuser=0">Chrome ウェブストア</a> にアクセスして、Teemo を Chrome に追加する必要があります。</p> <p><img src="https://i.gyazo.com/3649738203bc1e06da63a48d3c8140c0.png" alt="スクリーンショット 2021-06-13 18.24.31.png" /><br /> <strong>1. <a target="_blank" rel="nofollow noopener" href="https://chrome.google.com/webstore/detail/teemo-%F0%9F%92%95/alhdkgcgpmdfbidaapdlnmbhoanoijka?hl=ja&authuser=0">Chrome ウェブストア</a> にアクセスして右上の <code>Chrome に追加</code> ボタンをクリックする</strong></p> <p><img src="https://i.gyazo.com/ea19a358e038d73af1b73e6413e80420.png" alt="スクリーンショット 2021-06-13 18.27.27.png" /><br /> <strong>2. 拡張機能として Teemo の追加が完了したら、ツールバーのアイコンをクリックするか <code>Ctrl or Cmd + Shift + O</code> を入力して Teemo のエディタが開くことを確認する</strong></p> <p>上記確認できれば Teemo が正常に Chrome 拡張機能として追加できています。</p> <h2>Teemo で絵文字を <code>:</code> でショートカット入力する 💨</h2> <p><strong>Teemo のエディタでは <code>:</code> を利用することで文章入力を止めることなく、シームレスに絵文字入力が行えます。<code>:</code> を入力後、関連ワードを半角英数字で入力することで絵文字候補がウィンドウ下部に表示されます。入力したい絵文字をマウスかキーボードの矢印キーで選択して入力できます。</strong></p> <p><img src="https://i.gyazo.com/5b18b25505d443a14befff21e06ecbe8.png" alt="スクリーンショット 2021-06-13 18.51.19.png" /><br /> <strong><code>:</code> を入力後、関連ワードを半角英数字で入力することで絵文字候補がウィンドウ下部に表示される 💨</strong></p> <h2 id="Teemo で絵文字をパレットから選択して入力する 🎨"><a href="#Teemo+%E3%81%A7%E7%B5%B5%E6%96%87%E5%AD%97%E3%82%92%E3%83%91%E3%83%AC%E3%83%83%E3%83%88%E3%81%8B%E3%82%89%E9%81%B8%E6%8A%9E%E3%81%97%E3%81%A6%E5%85%A5%E5%8A%9B%E3%81%99%E3%82%8B+%F0%9F%8E%A8">Teemo で絵文字をパレットから選択して入力する 🎨</a></h2> <p>絵文字をパレットから選択して入力するには <code>Ctrl or Cmd + E</code> キーを入力するか、ウィンドウ下部の真ん中にある <code>🎨</code> ボタンをクリックしてパレットを表示する必要があります。ちなみに絵文字選択用のパレットには OSS の <a target="_blank" rel="nofollow noopener" href="https://github.com/missive/emoji-mart">Emoji Mart</a> を利用しています。</p> <p><img src="https://i.gyazo.com/2fd8384fa90adc797b2cf643cb1f8652.png" alt="スクリーンショット 2021-06-13 18.48.36.png" /><br /> <strong>パレットで関連ワードを入力することで絵文字検索ができる。絵文字をクリックすることで入力できる 🐱</strong></p> <h2 id="Teemo で入力した文章をクリップボードにコピーする 📋"><a href="#Teemo+%E3%81%A7%E5%85%A5%E5%8A%9B%E3%81%97%E3%81%9F%E6%96%87%E7%AB%A0%E3%82%92%E3%82%AF%E3%83%AA%E3%83%83%E3%83%97%E3%83%9C%E3%83%BC%E3%83%89%E3%81%AB%E3%82%B3%E3%83%94%E3%83%BC%E3%81%99%E3%82%8B+%F0%9F%93%8B">Teemo で入力した文章をクリップボードにコピーする 📋</a></h2> <p><strong>入力した文章は <code>Ctrl or Cmd + C</code> キーを入力するか、ウィンドウ下部の右にある <code>📋</code> ボタンをクリックすることで全文コピーが可能です。わざわざ範囲選択を行わずとも文章を全文コピーすることができます。</strong> コピーが正常にできるとウィンドウ下部の真ん中にある <code>📋</code> ボタンが <code>📋✔️</code> ボタンになります。</p> <p><img src="https://i.gyazo.com/17955efbabe4b849cc095a4db118793a.png" alt="スクリーンショット 2021-06-13 18.57.30.png" /><br /> <strong>Teemo で文章入力後 <code>Ctrl + C</code> で全文コピー後、ツイート編集画面にペーストした時の様子 🐦</strong></p> <h2 id="Teemo で入力した文章をクリアする 🧼"><a href="#Teemo+%E3%81%A7%E5%85%A5%E5%8A%9B%E3%81%97%E3%81%9F%E6%96%87%E7%AB%A0%E3%82%92%E3%82%AF%E3%83%AA%E3%82%A2%E3%81%99%E3%82%8B+%F0%9F%A7%BC">Teemo で入力した文章をクリアする 🧼</a></h2> <p><strong>Teemo では単一のウィンドウを使い回すため、改めて文章を作成する際に一度入力した文章をクリアする必要があります。</strong> そのため、<code>Ctrl or Cmd + R</code> キーを入力するか、ウィンドウ下部の左にある <code>🆕</code> ボタンをクリックすることで文章をクリアできるようにしています。</p> <p><img src="https://i.gyazo.com/5096d26a87ff99ec76f5f9b6c12eaa82.png" alt="スクリーンショット 2021-06-13 19.01.42.png" /><br /> <strong>Teemo の入力欄を <code>🆕</code> ボタンをクリックしてクリアした時の様子 🧼</strong></p> <h1 id="おわりに 🔚"><a href="#%E3%81%8A%E3%82%8F%E3%82%8A%E3%81%AB+%F0%9F%94%9A">おわりに 🔚</a></h1> <p>個人的に Teemo のおかげで、Twitter での絵文字を利用した文章作成についてストレス無く出来るようになったので良かったです。副次的な効果として、どんなサイトでも絵文字を利用した文章作成が簡単に出来るようになったため、他に絵文字をショートカット入力できないサイトがあったとしても同様の困りごとは発生しなくなりました。☺️</p> <p>SNS 上などで文章を作成する際に絵文字を頻繁に利用する方には割とご満足いただける拡張機能になっているはずです多分 🙋</p> nikaera tag:crieit.net,2005:PublicArticle/16550 2021-01-06T23:45:20+09:00 2021-01-06T23:55:33+09:00 https://crieit.net/posts/badge-of-github-actions-with-chrome-extension-20210106 Github Actions のバッジを付ける (+バッジに Github Actions ページへのリンクを付与するChrome拡張機能を作成) <p><a href="https://crieit.net/posts/run-phpunit-on-github-actions-20210105">前回記事</a>の続き。 Github Actions で PHPUnit が走ることが確認できたところで、今度は「そういえば Github Actions のバッジはあるのだろうか?」と気になって調べてみました。</p> <h2 id="バッジの所在"><a href="#%E3%83%90%E3%83%83%E3%82%B8%E3%81%AE%E6%89%80%E5%9C%A8">バッジの所在</a></h2> <p>バッジについては Github Actions のページにありました。</p> <ol> <li>リポジトリの対象アクション ( <code>https://github.com/<user>/<repo>/actions?<workflow></code> ) に遷移</li> <li>上のハンバーガー( <code>…</code> ) からメニューを開く</li> <li><code>Create status badge</code> をクリック</li> </ol> <p>以上の手順で発行できます。</p> <p><a href="https://crieit.now.sh/upload_images/30fd56cee47ae62946d6c90ff72122da5ff5cbafc5560.jpg" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/30fd56cee47ae62946d6c90ff72122da5ff5cbafc5560.jpg?mw=700" alt="バッジ発行のメニューを展開した画面" /></a></p> <p>メニュー展開時。</p> <p><a href="https://crieit.now.sh/upload_images/8ae1b6cc9da667dd3e02d32105a009505ff5cbba9ec66.jpg" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/8ae1b6cc9da667dd3e02d32105a009505ff5cbba9ec66.jpg?mw=700" alt="バッジの Markdownコード をコピペできるダイアログ" /></a></p> <p>ダイアログ表示。</p> <p><a href="https://crieit.now.sh/upload_images/141188e82ee2e92f15b7ec06bc7286ef5ff5cbc8c6e40.jpg" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/141188e82ee2e92f15b7ec06bc7286ef5ff5cbc8c6e40.jpg?mw=700" alt="バッジを readme.md に貼り付け" /></a></p> <p>バッジを readme.md に貼り付けてみました。</p> <h2 id="バッジのリンクを変更する Chrome拡張機能"><a href="#%E3%83%90%E3%83%83%E3%82%B8%E3%81%AE%E3%83%AA%E3%83%B3%E3%82%AF%E3%82%92%E5%A4%89%E6%9B%B4%E3%81%99%E3%82%8B+Chrome%E6%8B%A1%E5%BC%B5%E6%A9%9F%E8%83%BD">バッジのリンクを変更する Chrome拡張機能</a></h2> <p>ところで、</p> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://qiita.com/akameco/items/e474691964703033e18d">GitHub Actionsのバッジをリンク付きでREADMEに追加する - Qiita</a></li> </ul> <p>こちらの記事で「デフォルトのバッジ画像の Markdownコード は画像のみとなっていて対象の Github Actions へのリンクにはなっていないのが不便」とありました。確かに……。</p> <p>上記の記事では UserScript で該当の Markdownコード を書き換える方法を紹介していましたが、個人的には Chrome拡張機能 で充分な気がしたのでざっくり自前で作ってみました。</p> <h3 id="リポジトリ"><a href="#%E3%83%AA%E3%83%9D%E3%82%B8%E3%83%88%E3%83%AA">リポジトリ</a></h3> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://github.com/arm-band/chrome_extensions_cambadge">arm-band/chrome_extensions_cambadge</a></li> </ul> <h3 id="manifest.json"><a href="#manifest.json">manifest.json</a></h3> <pre><code class="json">{ "manifest_version": 2, "name": "cambadge", "description": "Github Actions のバッジのURLを変更する拡張機能です。", "version": "0.0.1", "browser_action": { "default_icon": { "19": "icon_19.png", "38": "icon_38.png" }, "default_title": "cambadge" }, "content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'", "content_scripts": [ { "matches": [ "https://github.com/*" ], "js": [ "main.js" ] } ] } </code></pre> <h3 id="main.js"><a href="#main.js">main.js</a></h3> <pre><code class="javascript">/** * cambadgeCampaign: rewrite markdown code in textarea * * @param {object} DOMBadgeMd */ const cambadgeCampaign = (DOMBadgeMd) => { if (/^\!\[(.*)\]\((.*)\)$/gi.test(DOMBadgeMd.textContent)) { DOMBadgeMd.textContent = `[${DOMBadgeMd.textContent}](${location.href})`; } }; window.addEventListener('load', (e) => { // triggered load if (/https:\/\/github\.com\/(.*)actions(.*)/gi.test(location.href)) { // only github actions page const clickItem = document.querySelector('summary[data-test-selector="badge-builder-button"]'); clickItem.addEventListener('click', (ev) => { // triggered click of element:summary[data-test-selector="badge-builder-button"] let setIntervalId; let DOMBadgeMd; function findTargetElement () { // watch until find element:#badge-markdown DOMBadgeMd = document.querySelector('#badge-markdown'); if (DOMBadgeMd !== null && DOMBadgeMd !== undefined) { // found clearInterval(setIntervalId); // call function cambadgeCampaign(DOMBadgeMd); } }; setIntervalId = setInterval(findTargetElement, 100); }); } }); </code></pre> <p>ダイアログ中の <code>#badge-markdown</code> を含むバッジ生成の要素は <code>Create status badge</code> をクリックした際に生成されるようなので、 <code>Create status badge</code> をクリックした後、 <code>#badge-markdown</code> が見付かるまで書き換えの処理を待つようにしました。</p> <p><a href="https://crieit.now.sh/upload_images/fdaadb5b62dc4f103757d48bb84e12645ff5ccc3a2263.jpg" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/fdaadb5b62dc4f103757d48bb84e12645ff5ccc3a2263.jpg?mw=700" alt="バッジの Markdownコード (Chrome拡張機能 で書き換え実施後の表示)" /></a></p> <p>Chrome拡張機能 で書き換えられたダイアログ。これで該当の Github Actions ページへのリンクに繋がるようになりました。</p> <h2 id="参考"><a href="#%E5%8F%82%E8%80%83">参考</a></h2> <h3 id="バッジ"><a href="#%E3%83%90%E3%83%83%E3%82%B8">バッジ</a></h3> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://qiita.com/SnowCait/items/487d70b342ffbe2f33d8#fn1">GitHub Actions でステータスバッジを表示する - Qiita</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://docs.github.com/ja/free-pro-team@latest/actions/managing-workflow-runs/adding-a-workflow-status-badge">ワークフローステータスバッジを追加する - GitHub Docs</a></li> </ul> <h3 id="バッジのリンクを変更する"><a href="#%E3%83%90%E3%83%83%E3%82%B8%E3%81%AE%E3%83%AA%E3%83%B3%E3%82%AF%E3%82%92%E5%A4%89%E6%9B%B4%E3%81%99%E3%82%8B">バッジのリンクを変更する</a></h3> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://qiita.com/akameco/items/e474691964703033e18d">GitHub Actionsのバッジをリンク付きでREADMEに追加する - Qiita</a></li> </ul> <h3 id="UserScript"><a href="#UserScript">UserScript</a></h3> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://kenchan0130.github.io/post/2018-05-21-1">UserScriptで業務改善</a></li> </ul> arm-band