okayurisotto.net

私が好きでやったことが他の人のためにもなったらお得かも!

Wikipediaの任意のページの短縮URLを生成するブックマークレットを作った

  1. 📝

はじめに

閲覧中のWikipediaのページの短縮URLを生成(取得)するブックマークレットを作りました。

下に示すURIをブックマークして使ってください。

javascript:void((()%3D%3E%7B%22use%20strict%22%3B(()%3D%3E%7B(async()%3D%3E%7Blet%20r%3Dnew%20URL(%22https%3A%2F%2Fmeta.wikimedia.org%2Fw%2Fapi.php%22)%3Br.searchParams.set(%22origin%22%2Clocation.origin)%3Blet%20t%3Dawait(await%20fetch(r%2C%7Bmethod%3A%22POST%22%2Cmode%3A%22cors%22%2Creferrer%3Alocation.origin%2Ccredentials%3A%22include%22%2Cheaders%3A%7B%22Content-Type%22%3A%22application%2Fx-www-form-urlencoded%3B%20charset%3DUTF-8%22%7D%2Cbody%3Anew%20URLSearchParams(%7Baction%3A%22shortenurl%22%2Cformat%3A%22json%22%2Curl%3Alocation.href%7D).toString()%7D)).json()%3Bprompt(%22%22%2Ct.shortenurl.shorturl)%7D)()%3B%7D)()%3B%0A%7D)())%3B

これだけでは流石に記事として味気ないので、少し技術的な解説をします。

ブックマークレットとは

URI(統一資源識別子)には、URL(統一資源位置指定子)の他にもいくつか種類がありますが、その中に、非公式ながらも広く使われているものとして、JavaScript URIがあります。javascript:から始まるもので、次のような形でよく登場します。

<a href="javascript:void(0)" onclick="register">登録ボタン</a>

aタグをonclick属性を使って無理矢理ボタンとして使うときにhrefとして使うもののことです。これは、押下されたとき、javascript:に続けて書かれたJavaScriptをそのページで実行するURIで、それ以上でもそれ以下でもありません。この例ではvoid(0)が実行されますので、何も起きません。

では次のようなURIだった場合はどうでしょうか。(この例ではわかりやすさのためにURIに適切なエスケープをしていません。)

javascript:void((async () => { alert("Hello, world!") })());

これを実行すると、「Hello, world!」という文字列でWebブラウザのダイアログが表示されます。

そして面白いのが、このURIをブックマークすると、そのブックマークを開いたときにURIに書かれたJavaScriptが実行されるということです。つまり任意のタイミングで、あらかじめ登録しておいたJavaScriptを閲覧中のWebページで実行することができるということです。ある種の拡張機能ですね。

WikipediaのURLについて

Wikipediaの各項目にはそれぞれURLが割り当てられていますが、そのURLはとてつもなく長いものです。どうしてこのようになってしまっているのかというと、そのURLはその項目のタイトルをエンコードしただけのものだからです。そして、日本語によるタイトルをURLに含める都合で行われるエンコード(パーセントエンコーディング)は、非常に冗長なのです。

下に示すのは、Wikipediaの「パーセントエンコーディング」の項目のURLです。パーセント記号を使ってエンコードされている様子がおわかり頂けると思います。

https://ja.wikipedia.org/wiki/%E3%83%91%E3%83%BC%E3%82%BB%E3%83%B3%E3%83%88%E3%82%A8%E3%83%B3%E3%82%B3%E3%83%BC%E3%83%87%E3%82%A3%E3%83%B3%E3%82%B0

Wikipediaの短縮URLについて

そんなWikipediaですが、実は短縮URLを生成する機能が備わっていますので、それを使ってしまえば万事解決だったりします。PC版Wikipediaのページ右上にある「ツール」メニューから「短縮URL」を選択することで短縮URLがモーダルで表示されます。

ではなぜブックマークレットを作ったのか

  • メニューを開いて項目を選ぶ操作が面倒だった
  • モーダルを閉じる操作が面倒だった
  • そもそもなぜかメニューが表示されない項目があって面倒だった

これらの理由から、APIを直接叩くことで短縮URLを得るブックマークレットを作成しました。

APIについて

短縮URLを取得するAPIは内部APIというわけではなく、一般に公開されているものです。

レートリミットも2分に10件までと十分なくらいあります。使わせてもらいましょう。

ブックマークレットの開発

とりあえずTypeScriptが使いたいので、esbuildによってトランスパイル(ついでにminify)するような環境を整えました。その上で、生成されたJavaScriptをvoidとIIFEで囲った上でencodeURIComponentし、javascript:を先頭に書き加えるスクリプトも書きました。

そして次のようなTypeScriptを書きました。

const url = new URL("https://meta.wikimedia.org/w/api.php");
url.searchParams.set("origin", location.origin);

const res = await fetch(url, {
  method: "POST",
  mode: "cors",
  referrer: location.origin,
  credentials: "include",
  headers: {
    "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
  },
  body: new URLSearchParams({
    action: "shortenurl",
    format: "json",
    url: location.href,
  }).toString(),
});

CORS対策がいろいろとされていますが、やっていることは大したことではありません。x-www-form-urlencodedとしてクエリをPOSTしているだけです。どうやら、少なくともこのAPIではx-www-form-urlencodedとしてクエリをPOSTしなければならないようでした。formから入力されることしか考えていない設計ですが、それではWikipediaの各項目ページに設置されたあのボタンはどのような仕組みで動いているのでしょうか。謎です。気が向いたら開発者ツールで覗いてみます。

おわりに

このブックマークレットはGitHubの公開リポジトリで開発していますので何かありましたらIssueを作成してください。。

これでWikipediaのパーセントエンコーディングなURLとおさらばできます……。