akahukuplus 3.0 is out

すっかりここで告知するのを忘れていたのだけれど、赤福プラスを公開した。

http://akahuku.github.io/akahukuplus/

moon-crystal-power

赤福プラスをエクステンションのパッケージにビルドするための準備をした。

wasavi のビルドは ant を使っている。これは junit と selenium を使った機能テストと統合しているためである。一方で赤福プラスの場合はその手のテストが難しい。つまりやることの大半がふたばのサーバに対する応答なわけで、継続的な自動テストを行わせるにはふたばのサーバとして振る舞うダミーが必要になるのだが、それを真面目にやるのはなかなかな大仕事だということだ。もしかしたら junit & selenium とか、そういう話じゃなくなって、まったく別の仕組みを使う必要が出てくる可能性すらある。

となるとビルドに ant を使う必要もないわけで、赤福プラスのビルドは make で行うようにしてみた。ant でダメというわけでもないのだけれど、ビルドの手順を xml で書くのは、やっぱりとっても冗長なのである。まあきっと一般的には build.xml は直接触らず GUI でぽいぽい手順を指示するタイプのツールがメジャーなのであって、xml が冗長だ的な批判は的はずれなのだろう。xml を直接書くほうが頭おかしいのである。

しかし、それにしても、(シンプルなプロジェクトの)Makefile はやはりシンプルで、素朴で、いいなあと思いました。

mkdir -p

[cci]$ mkdir -p foo/bar/baz[/cci] とすると、パスを構成する各ディレクトリがなかったら、自動的に作ってくれるという賢い動作をしてくれるじゃないですか。

オンラインストレージの API でそういう動作をしてくれるかという話。

dropbox は、まさにそういう動作をする。というより、それ以外の動作(存在しないパスが指定されたらエラーにする的な)を指定できない。ファイルをアップロードする REST エンドポイントの構造は
[cci]https://api-content.dropbox.com/[VERSION]/files_put/[ROOT IDENTIFIER]/[PATH][/cci]
というものだ。VERSION は現在は [cci]1[/cci]、ROOT IDENTIFIER はユーザーに割り当てられた空間のどこをルートにするかという指定で、[cci]dropbox[/cci] は空間全体のルートを表し、[cci]sandbox[/cci] は登録したアプリケーションごとの専用のディレクトリを表す。

実際には、[cci]sandbox/foo.txt[/cci] は 例えば単に [cci]dropbox/app/akahukuplus/foo.txt[/cci] と同じ場所を示す。sandbox を指定している限り、誤っておかしなディレクトリのファイルを読み書きしてしまうことはないというシンプルだけど確かに効果のあるからくりだ。

そして、PATH で目的のファイルのパスを指定する。つまりエンドポイント URL に対象となるパスの、その階層構造も含まれている。

一方で、Google Drive はどうかというと、そもそも階層構造の中の特定の位置を文字列で示すという概念がない(気がする)。[cci]/foo/bar/baz.txt[/cci] というパスの baz.txt の情報を得るには、ルート上のファイルの中で [cci]foo[/cci] を検索し、そのディレクトリの下にある [cci]bar[/cci] を検索し…という処理を再帰的に行う必要があり、そのつど REST のネットワークアクセスが発生する。非常に、恐ろしく無駄だ。なぜ、パス文字列という概念を google が導入しないのかはわからない。そういう環境なので、そもそも mkdir -p 的な動作を期待できない。

 * * *

というわけで、akahukuplus のバックエンドの gdrive ファイルシステムモジュールでは、例えば [cci]/dat/b/1234567890.jpg[/cci] というパスにファイルを保存したい際は mkdir オプションを指定できるようにした。この値が [cci]auto[/cci] で、かつ指定のパスが存在していなかった場合は mkdir -p 相当の動作をエミュレートしてから保存処理を再度実行する。

reborn: akahukuplus

この一ヶ月特に何も作っていなかったというのはつまり、引っ越ししたのでそもそもネットから遮断されていたということなのだが、その直前までは何をしていたのかといえば、wasavi に関してはほとんどコードをいじっていない。

いじっていたのは赤福プラスとよばれるブラウザ用拡張なのである。

かつてふたば☆ちゃんねる向けに IE のコンテキストメニューを拡張する赤福というツールを作った。赤福プラスはその Opera 版というわけだ。Opera 版は当時の Opera が搭載したばかりのユーザースクリプトの仕組に乗っかって動作し、コンテキストメニューにとどまらない様々な機能を持っていた。

その後、Chrome でも動くようにしたり、その過程でブラウザ拡張として構成しなおしたりしたのだが、さすがに建て増し続きだったし、また IE6 あたりでも動作するようにしていたので、例えば Selector API とか XPath とか続々とブラウザに搭載されていく新機能を使うわけにも行かず、中味はなかなかぐぬぬなコードになっていた。

今回、そんなわけで一から作り直してみようということである。残念ながら IE はサポート外となる。最近の IE 自身は、新しい赤福プラスを動作させるポテンシャルは十分あるのだけど、スクリプトベースの拡張の仕組みがないので。一方で、Presto Opera はサポートする。サポートするも何も、Opera 12 で開発してるので、未だにファーストクラスのブラウザだったりする。この他には Chrome と Blink Opera でテストする。気が向けば Firefox 版も作るかもしれない(気が向かないのは、Firefox には別の人が作った赤福がすでにあるからである)。

技術的な面に目を向けてみると、フロントエンドとバックエンドで全く違ういくつかのトピックがある。

まずフロントエンドからだが、赤福プラスというのはつまりふたばの画像掲示板の html を動的にちょっと書き換えるツールだ。ここではふたばの画像掲示板に DOMContentLoaded でスクリプトを引っ掛けて、ページの DOM をごにょごにょするのがフロントエンドの役割だ。

しかし、ふたばの画像掲示板が吐く html というのは、まああんまりそういう再利用はしやすくないのである。そこで、おそらく他のふたば用ツールはほとんどやっていないであろう手法を取る。ページを読み込んだらそれをスクレイピングし、一旦中間的な xml を構築する。さらにそれを XSLT プロセッサに与えて html に変換するのである。続きのレスを読んだりダイアログを出したりするときも必要なら XSL による変換が入るので、けっこう XSLT が大回転することになる。

これによってふたばの元々の html に振り回されるのはスクレイピング処理部だけになり、その他の部分は自分で完全に制御できる xml だけを見ればよくなる。また、ページ全体を制御できるのでよりダイナミックにページを構成することが可能になる。たとえばスティッキーなサムネイルとかバナー、固定ヘッダなどをなんでも導入できるようになる。

次にバックエンド。バックエンドとはつまり拡張の表に出てこない裏方の部分だが、実はこれは wasavi とちょっと関連する。wasavi もバックエンドを持っている。wasavi もまたいくつかのブラウザで動くため、各ブラウザの拡張の仕組みをある程度抽象化させた部分をもっているのだが、残念ながら完全ではなかった。また、wasavi というアプリケーションからも独立してるわけでもなかった。

これがずっと気にかかっていたので、今回を機にブラウザ拡張の抽象化層をきっちり作り、またアプリケーションからも完全に独立させたい。その抽象化層をベースにして赤福プラスのバックエンドを構築し、さらに wasavi にもバックポートする。なかなか遠大・壮大な計画なのである。

バックエンドに関してはもうひとつやることがある。オンラインストレージをアプリケーションから利用する際の承認において、dropbox はなんかなかなか OAuth 2.0 をサポートしなかった。ので、wasavi も jsOAuth というちょっと癖のあるライブラリを使って OAuth 1.0 で繋ぐしかなかったのである。しかし最近なのか結構前なのか知らないけど、いつの間にか OAuth 2.0 がサポートされていたのでそのへんの仕組みをごっそり書き直したい。当然この辺りも wasavi にバックポートされることになる。

赤福プラスにおいては、オンラインストレージは画像の保存・スレッドの保存時に利用することになる。画像のサムネイルから保存ボタンを押すとオンラインストレージの API を通して保存を行うのである。オンラインストレージ側の機能でローカルや複数デバイス間で同期することができる。

最近の状況はこんな感じです。

shortcuts in akahukuplus

赤福プラスのショートカット周りを書き直した。

以前にも書いたことがあるが、以下のショートカットが有効になる。ただし、カーソル移動系は古い(8 までの)IE では動作しない。

  • textarea / input[type=text] にフォーカスがある場合
    • Shift+Enter: 送信
    • Esc: フォームからフォーカスを外す。フォームが最小化可能である場合は、最小化する
    • Ctrl+S: カーソルを左へ1文字移動
    • Ctrl+D: カーソルを右へ1文字移動
    • Ctrl+Q: カーソルを行頭へ移動
    • Ctrl+P: カーソルを行末へ移動
    • Ctrl+H: カーソルの前の1文字、または選択範囲を削除
  • ない場合
    • Insert または i: コメント欄にフォーカスする
    • r: futaba.htm ~ 10.htm の場合、ページ先頭へスクロールした後リロードする。レス送信モードの場合、続きを読めるなら続きを読む。そうでなければリロードする。カタログモードの場合、リロードする
    • g: ページ先頭へスクロールする
    • Shift+g: ページ末尾へスクロールする

akahukuplus #2

赤福プラスの extension 版では、「続きを読む」で得たコメント群や読み込んだ画像を web sql database に保存している。このとき、画像については blob として保存していて、その blob は BlobBuilder オブジェクトを経由して生成していたのだが、BlobBuilder は deprecated になり、Blob のコンストラクタが使えるようになった。少なくとも仕様上は。

var bb = new BlobBuilder;
bb.append(array_buffer_variable);
var blob = bb.getBlob();

などとやっていたコードが

var blob = new Blob([array_buffer_variable]);

となる。

で……。

Opera 12.01 では、window.BlobBuilder はなくなっている。BlobBuilder がなくなっているということはつまり、Blob コンストラクタが使えるようになっているんだなー、と普通に考えたらそうなる。

しかし、Opera 12.01 では Blob コンストラクタを呼ぶとエラーになるのであった。したがって、Opera 12.01 ではどうあがいても blob を生成できない……?

ひどい話だ。もしこういうふざけた真似を、たとえば Mozilla がしでかしたら、怒り狂って bugzilla に同じバグレポートを 2 万件くらい登録するくらいの勢いだ。

しかし Opera なので。死んだ目で「まあ Opera だからね……」とつぶやくしかないのであった。まあ Opera だからね……。

 * * *

と思ったら勘違いしていた。そもそも Opera で BlobBuilder がサポートされたこと自体がなかった。おお、つまりこの記事自体が何の意味もなかったことに……。でもまあ、Opera だからね……。

akahukuplus

某掲示板の閲覧を快適にするためのツール、赤福プラスというものがあるのだが、こちらも chrome 版の manifest を更新した。

ところで赤福プラスには閲覧しているスレッドを保存する機能があるのだが、これはブラウザ側で生成した mht をそのままこのサーバへ送信し、サーバへ一旦保存し、それをダウンロードするという、なかなか無駄なことをしている。今では Chrome はサンドボックス化されたファイルシステムを扱える。つまりがんばればサーバを経由することなく mht を生成できるはずである。

しかしそれを素直に使うか? というと微妙だ。なにより Opera がまだ対応していないし、将来対応するかも不明だ。そしてそもそもサンドボックス化されたファイルシステムというのがなんか筋がよくない気がするのだ。ローカルの環境と完全に隔離されているのなら、blob を含めて何でも保存できる IndexedDB と機能がオーバーラップする。たぶん Opera も IndexedDB はそのうち実装するだろう。moveTo() とか copyTo() とか使えるのは分かりやすいといえば分かりやすいが……。