36
Help us understand the problem. What are the problem?

posted at

updated at

WebページのタイトルとURLをワンクリックでコピーするBookmarklet

やりたいこと

タイトル+URLをリンクの形式でコピーしたい。
各サービスでフォーマットがバラバラなのでいちいち覚えたくない。
あと、Ctrl+Cもめんどくさいので、bookmarkletを押すだけでClipboardにコピーしたい。

※2017-09-01: 実装、タイトル、説明内容を見直して修正しました。
※2021-03-27: 実装修正しました
※2022-02-21: Twitterのページで動作しない問題に対応しました

参考にさせてもらったページ

やったこと

こんな感じにしました。以下がベースとなるコードです。

(() => {

  /**
   * メイン処理
   */
  const main = () => {

    // div要素用意
    const divElement = document.createElement("div");
    const escapeHtml = (unsafe) =>  {
      return unsafe
        .replace(/&/g, "&")
        .replace(/</g, "&lt;")
        .replace(/>/g, "&gt;")
        .replace(/"/g, "&quot;")
        .replace(/'/g, "&#039;")
        .replace(/ /g, "&nbsp;")
        .replace(/\n/g, "<br>")
      ;
    }
    // div要素にタイトルとURLを設定
    divElement.innerHTML = escapeHtml(getTitleAndUrlText())
    // さらにBodyの子要素にする
    const bodyElement = document.getElementsByTagName("body")[0];
    bodyElement.appendChild(divElement);

    // div要素内の文字を選択する
    // javascript - Select all DIV text with single mouse click - Stack Overflow  
    // https://stackoverflow.com/questions/1173194/select-all-div-text-with-single-mouse-click
    const range = document.createRange();
    range.selectNode(divElement);
    window.getSelection().removeAllRanges();
    window.getSelection().addRange(range);

    const isSuccessCopy = document.execCommand('copy');
    bodyElement.removeChild(divElement);
    console.log("Copy successful? = " + isSuccessCopy)
  };

  /**
   * URLとタイトル取得
   * @returns {string}
   */
  const getTitleAndUrlText = () => {
    let title = document.title;
    let url = document.URL

    // 各フォーマット向けにエスケープしたい文字列を定義して置換
    const replacedStrings = {
      ':': '',
      '\\[': '',
      '\\]': '',
      '\\|': ''
    };
    for (let key in replacedStrings) {
      title = title.replace(new RegExp(key, 'g'), replacedStrings[key]);
    }

    // コピー後のフォーマットに加工した文字列を返す
    return title + '\n' + url + '\n\n';
  };

  main();
})()


このコードの

    // コピー後のフォーマットに加工した文字列を返す
    return title + '\n' + url + '\n\n';

の部分を各サービスやマークアップ言語などのフォーマットに変更することで、ワンクリックでそのフォーマットの文字列をクリップボードにコピーできます。

作ったBookmarklet

各サービスやマークアップ言語のリンク形式の表現で、タイトルとURLをクリップボードにコピーするBookmarkletを作ってみました。
使い方は

  1. 適当なページ(例えばGoogleとかでも良いです)のBookmarkを作る
  2. そのBookmarkを編集し、URLの部分に以下の「コード」をそのままコピペする。タイトルは分かりやすいように、「Markdown形式でコピー」とかつけておくと良いかもです。

です。

Normal

フォーマット

ページタイトル
http://example.com

コード

javascript:(()=>{const e=()=>{const e=document.createElement("div"),c=e=>e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#039;").replace(/ /g,"&nbsp;").replace(/\n/g,"<br>");e.innerHTML=c(n());const t=document.getElementsByTagName("body")[0];t.appendChild(e);const o=document.createRange();o.selectNode(e),window.getSelection().removeAllRanges(),window.getSelection().addRange(o);const l=document.execCommand("copy");t.removeChild(e),console.log("Copy successful? = "+l)},n=()=>{let e=document.title,n=document.URL;const c={":":"","\\[":"","\\]":"","\\|":""};for(let n in c)e=e.replace(new RegExp(n,"g"),c[n]);return e+"\n"+n+"\n\n"};e()})();

Markdown(引用形式)

フォーマット

> ページタイトル  
> http://example.com  
return '> ' + title + '  \n> ' + url + '  \n\n';

コード

javascript:(()=>{const e=()=>{const e=document.createElement("div"),c=e=>e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#039;").replace(/ /g,"&nbsp;").replace(/\n/g,"<br>");e.innerHTML=c(n());const t=document.getElementsByTagName("body")[0];t.appendChild(e);const o=document.createRange();o.selectNode(e),window.getSelection().removeAllRanges(),window.getSelection().addRange(o);const l=document.execCommand("copy");t.removeChild(e),console.log("Copy successful? = "+l)},n=()=>{let e=document.title,n=document.URL;const c={":":"","\\[":"","\\]":"","\\|":""};for(let n in c)e=e.replace(new RegExp(n,"g"),c[n]);return"> "+e+"  \n> "+n+"  \n\n"};e()})();

Markdown(リンク形式)

フォーマット

- [ページタイトル](http://example.com)
return '- [' + title + '](' + url + ')\n\n';

コード

javascript:(()=>{const e=()=>{const e=document.createElement("div"),c=e=>e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#039;").replace(/ /g,"&nbsp;").replace(/\n/g,"<br>");e.innerHTML=c(n());const t=document.getElementsByTagName("body")[0];t.appendChild(e);const o=document.createRange();o.selectNode(e),window.getSelection().removeAllRanges(),window.getSelection().addRange(o);const l=document.execCommand("copy");t.removeChild(e),console.log("Copy successful? = "+l)},n=()=>{let e=document.title,n=document.URL;const c={":":"","\\[":"","\\]":"","\\(":"","\\)":"","\\|":""};for(let n in c)e=e.replace(new RegExp(n,"g"),c[n]);return"- ["+e+"]("+n+")\n\n"};e()})();

Redmine

フォーマット

"タイトル":http://example.com
return '"' + title + '":' + url + '\n\n';

コード

javascript:(()=>{const e=()=>{const e=document.createElement("div"),c=e=>e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#039;").replace(/ /g,"&nbsp;").replace(/\n/g,"<br>");e.innerHTML=c(n());const t=document.getElementsByTagName("body")[0];t.appendChild(e);const o=document.createRange();o.selectNode(e),window.getSelection().removeAllRanges(),window.getSelection().addRange(o);const l=document.execCommand("copy");t.removeChild(e),console.log("Copy successful? = "+l)},n=()=>{let e=document.title,n=document.URL;const c={":":"","\\[":"","\\]":"","\\|":"",'"':""};for(let n in c)e=e.replace(new RegExp(n,"g"),c[n]);return'"'+e+'":'+n+"\n\n"};e()})();

Backlog

フォーマット

[[タイトル:http://example.com]]
return '[[' + title + ':' + url + ']]\n\n';

コード

javascript:(()=>{const e=()=>{const e=document.createElement("div"),c=e=>e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#039;").replace(/ /g,"&nbsp;").replace(/\n/g,"<br>");e.innerHTML=c(n());const t=document.getElementsByTagName("body")[0];t.appendChild(e);const o=document.createRange();o.selectNode(e),window.getSelection().removeAllRanges(),window.getSelection().addRange(o);const l=document.execCommand("copy");t.removeChild(e),console.log("Copy successful? = "+l)},n=()=>{let e=document.title;document.URL;const n={":":"","\\[":"","\\]":"","\\|":"",'"':""};for(let c in n)e=e.replace(new RegExp(c,"g"),n[c]);return"[["+e+":"+document.URL+"]]\n\n"};e()})();

DocComment

フォーマット

# @see タイトル http://example.com
return '# @see ' + title + ' ' + url + '\n\n';

コード

javascript:(()=>{const e=()=>{const e=document.createElement("div"),c=e=>e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#039;").replace(/ /g,"&nbsp;").replace(/\n/g,"<br>");e.innerHTML=c(n());const t=document.getElementsByTagName("body")[0];t.appendChild(e);const o=document.createRange();o.selectNode(e),window.getSelection().removeAllRanges(),window.getSelection().addRange(o);const l=document.execCommand("copy");t.removeChild(e),console.log("Copy successful? = "+l)},n=()=>{let e=document.title;document.URL;return"# @see "+e+" "+document.URL+"\n\n"};e()})();
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Sign upLogin
36
Help us understand the problem. What are the problem?