このブログは更新を終了しました。移転先はこちらです。

2023-02-19

NTA-DIY:1ヶ月目⑥~実作:簡単なブックマークレット~

 基礎の基礎を一通り勉強したところで、次はブックマークレットの作成に挑みました。Scrapboxのページに書き込むものです。

 というのも、Scrapboxの特定のページに追記する(またはページを新規作成する)にはURLに文字列をくっつけて開けばいいと知ったので、それなら「ブックマークレットの書き方」さえ解ればすぐ実用的なプログラムができるだろうと思ったからです。


 それがどのくらい簡単なことかというと、最終的にwindow.open('https://scrapbox.io/<project>/<page>?body=<text>')の形の一文を実行できればいいのです。そのために必要なのは<text>の部分の文字列を用意することだけです。書き込みたい文字列を作って、この一文に入れて実行させる。それだけなら全然難しいことはないわけです。

 なおブックマークレットは、JavaScriptで即時関数(読み込むと同時に実行する関数)を作って頭に「javascript:」をつけ、ブックマークのURL欄に設定することでクリック時に実行できるようになります。

 例えば以下の一文を登録して実行すれば動作の確認はできます。「<project>」の部分には書き込みたいプロジェクトのURLを入れてください。「test」というページに「abc」と書き込まれます。「test」というページが既にあって編集日時が更新されると困るというような場合は、適当な英数字に変えて試してください。

javascript:(function(){window.open("https://scrapbox.io/<project>/test?body=abc")})()

 ブラウザによってはポップアップのブロックで動かない場合があります。その場合は「https://scrapbox.io」のポップアップとリダイレクトを許可すれば動くと思います。(Chromeの場合→Chrome でポップアップをブロックまたは許可する - パソコン - Google Chrome ヘルプ

 これは、「window.open(<url>)」というメソッドを「(function(){ })()」で囲って即時関数にし、頭に「javascript:」をつけてブックマークレットにしているわけです。

 なおこの例では半角英数のみなので単純にURLを入れていますが、日本語や記号などはそのまま入れることができず、エンコードが必要です。エンコードは「encodeURIComponent()」というメソッドを使います。基本的に常にこのメソッドを通して設定することになります。

javascript:(function(){window.open("https://scrapbox.io/<project>/"+encodeURIComponent("テスト")+"?body="+encodeURIComponent("本文"))})()

 これをブックマークに登録すると(<project>の部分は変えてください)、クリックするたびに「テスト」というページに「本文」が追記されます。


 実用的なブックマークレットを作成するにあたっては、ページタイトルと本文部分について、window.open()の手前に処理を加えて希望の内容を作ることになります。その処理によってブックマークレット実行時に自動で文字列を生成し、複雑な内容のページをScrapboxにワンクリックで作ったり、または既存ページに追記したりできるようになるわけです。

 例えば、今日の日付のページにダイアログボックスを通じて文字列を追記するとすればこんなふうになります。

(function (){
const projectName = prompt('プロジェクトURLを入力してください。');
if(!projectName) return; // 未記入ならreturn
const today = new Date(); // 現在日時のDateオブジェクト
const year = today.getFullYear(); // 年(四桁)
const month = ('00' + (today.getMonth() + 1)).slice(-2); // 月(常に二桁表示になるように加工)
const date = ('00' + today.getDate()).slice(-2); // 日(常に二桁表示になるように加工)
const pageTitle = encodeURIComponent(`${year}/${month}/${date}`); // タイトルを作ってエンコードする
let url = `https://scrapbox.io/${projectName}/${pageTitle}`; // プロジェクトURLとページタイトルからURLを作る
const text = prompt('ページに追記する文字列を入力してください。');
if(text) url += `?body=${encodeURIComponent(text)}`; // 追記する文字列があればURLに加える(なければただページを開く)
window.open(url); // Scrapboxを開く
})();
/*
javascript:(function(){const projectName=prompt('プロジェクトURLを入力してください。');if(!projectName)return;const today=new Date();const year=today.getFullYear();const month=('00'+(today.getMonth()+1)).slice(-2);const date=('00'+today.getDate()).slice(-2);const pageTitle=encodeURIComponent(`${year}/${month}/${date}`);let url=`https://scrapbox.io/${projectName}/${pageTitle}`;const text=prompt('ページに追記する文字列を入力してください。');if(text)url+=`?body=${encodeURIComponent(text)}`;window.open(url)})()
*/

 一番下のコメントアウトされている部分がブックマーク登録用のものです。登録して実行すると、まずプロジェクトURLの入力を求められ、次に文字列の入力をすることになります。(自分で使うにはプロジェクトURLの入力は煩わしいですが、例として誰でも使えるようにするために入力する形にしています。)

 同様に今日の日付のページに、今度は現在開いているページを追記するなら以下のようになります。選択範囲があれば引用記法で追記されます。

(function (){
const projectName = prompt('今開いているページをScrapboxに記録します。\nプロジェクトURLを入力してください。');
if(!projectName) return; // 未記入ならreturn
const today = new Date(); // 現在日時のDateオブジェクト
const year = today.getFullYear(); // 年(四桁)
const month = ('00' + (today.getMonth() + 1)).slice(-2); // 月(常に二桁表示になるように加工)
const date = ('00' + today.getDate()).slice(-2); // 日(常に二桁表示になるように加工)
const pageTitle = encodeURIComponent(`${year}/${month}/${date}`); // 文字列を作ってエンコードする
let url = `https://scrapbox.io/${projectName}/${pageTitle}`; // プロジェクトURLとページタイトルからURLを作る
const link = `[${document.title} ${window.location.href}]`; // 開いているページのタイトルとURLを取得してリンク記法にする
let selection = window.getSelection().toString(); // 選択範囲の文字列を取得する
if(selection.trim()) selection = '\n> ' + selection.replace(/\n/g, '\n> ').replace(/\>\s$/,''); // 選択範囲があれば各行を引用記法にする
url += `?body=${encodeURIComponent(link + selection)}`; // urlに加える
window.open(url); // Scrapboxを開く
})();
/*
javascript:(function(){const projectName=prompt('今開いているページをScrapboxに記録します。\nプロジェクトURLを入力してください。');if(!projectName)return;const today=new Date();const year=today.getFullYear();const month=('00'+(today.getMonth()+1)).slice(-2);const date=('00'+today.getDate()).slice(-2);const pageTitle=encodeURIComponent(`${year}/${month}/${date}`);let url=`https://scrapbox.io/${projectName}/${pageTitle}`;const link=`[${document.title} ${window.location.href}]`;let selection=window.getSelection().toString();if(selection.trim())selection='\n> '+selection.replace(/\n/g,'\n> ').replace(/\>\s$/,'');url+=`?body=${encodeURIComponent(link + selection)}`;window.open(url)})()
*/


 JavaScriptに詳しくなればブックマークレットによって相当複雑なことができるようになりますが、最初のうちはそんな高度なことはできません。(私は現時点でも大したことはできません。)

 Scrapboxへのページ追加は、最低限ブックマークレットとして動かすために必要なことが非常に少ないので、練習にはうってつけでした。本文部分の文字列を作るコードを少しずつ複雑にしていくことで、データの扱いや各種メソッドを覚えていったのです。

 そして、Scrapboxの特定のページの作成・追記だけでも色々可能性は広がると思います。何より、UIに沿って手動で行うアナログな入力に縛られずに「プログラムで動かす」という経験をすることは、少し大袈裟に言えば世界の色が変わるような体験です。それ以上のことを実際にするかどうかは別として、「やろうと思えば色々できそう」と感じることは心を豊かにすると感じています。



このシリーズ記事の概要はこちら→ノートテイキングアプリDIY体験記