blosxom 3.0のプラグインはどうなのか? とか適当に羅列してみる。あくまでも3.0+3iで適当にプラグインを書いた上での話ですので、将来に渡ってこの内容が「blosxom 3.0のプラグインはこういうものだ」ということを言っているとは保証しません。よくわからん序文だな。

まずは全般的な疑問として誰もが持つかもしれない、「2.0のプラグインと比べて使いやすいの?」というユーザーの立場からの疑問。これへの答えは「比較にならないほどややこしい」ということに尽きます。2.0のプラグインは多くの場合、プラグイン・ディレクトリに置くだけ(+プラグイン内の設定の書き換え)で利用できるわけですが、3.0ではそうはいきません。少なくともhandlers.flowもしくはhandlers.entryのどちらかを書き換える必要があります。

例として、とりあえず作ってみたPagingというページめくりを実現するプラグインを挙げると、設定は多岐に渡ります。順に羅列すると、

  1. プラグイン・ディレクトリにPaging.pmを置く
  2. テンプレート・ディレクトリ(*1)にflavourを置く
  3. handlers.flowのBlosxom::sort_entriesの後で、かつBlosxom::run_entriesの前にBlosxom::Plugin::Paging::initializeを挿入
  4. handlers.flowのBlosxom::run_entriesの後で、かつBlosxom::render_responseの前にBlosxom::Plugin::Paging::build_navigationを挿入
  5. handlers.entryのBlosxom::filter_entry_by_dateの後で、かつBlosxom::shortcut_max_entriesの前にBlosxom::Plugin::Paging::filter_entry_by_pageを挿入
  6. テンプレート・ディレクトリのflavourにPlugin::Paging::next::renderedなど実際に表示するためのコードを挿入

と、実際に動かすだけでこれだけの作業になります。「うえーっ」て感じすね。更には他のプラグインとの兼ね合いも考えて、handlers.*の調整もしなくてはならないでしょう。

このように、プラグインの導入は非常に煩雑なものになってます。2.0より更に柔軟なシステムがあだになった格好ですね。

しかし、Movable Typeのようにパッケージングしたものをリリースする予定もあるらしいですし、「それをそのまま使えば?」みたいな感じで、こういったことは解消できることかもしれません(それに無いものを導入する時に敷居がとんでもなく高くなるでしょうが)。それに柔軟でどうにでもできることは2.0以上なので、プラグインをガシガシ作っていじり倒す人(少ないけど)には良いとは思います。

次に「2.0のプラグインと比べて書きやすいの?」というプラグイン作者的な疑問。これは微妙ですね。アロー演算子の羅列になるPerlのOoは評価の分かれるところ(アロー演算子書くだけで幸せなので、個人的には好き)ですしね。全般的には書きやすい部類に入るんではないかと思います。ハッシュの構造も慣れればどうってことは無いですし、Blosxom::dumpすれば一目瞭然(ちょっと大げさで、けっこうややこしい)なので、2.0よりアプローチの幅が広がっただけでも書きやすくなったんではないかと(とっちらかるかもという危険はありますが)。それに加えて相変わらす作法的なものはあまりないので(start()とかもなくなりました)、自由に書けるという点もそのままです。そして、インチキ臭いRSS出力機能とか、HTTPヘッダ出力機能の固定とかそういう制限も無くなったので、そういう柔軟さの向上も評価に値すると思います。

最後に「2.0のプラグインを3.0に書き直すのはどうよ?」という疑問。これはけっこう簡単です。ほとんど機械的に出来るかもしれないです。2.0のプラグインを実行する3.0のプラグイン(ややこしい)も出るかもしれないですしね。プラグイン内のみのサブルーチンはほとんどそのまま(場合によってはハッシュを渡す処理を追加しなければなりませんけど)、2.0でのhead()story()などもhandlers.*に書く位置(実行される順番)に注意してやれば、ほぼそのままでいけると思います。ややこしいのはstart()filter()かな。start()は3.0+3iでget_plugins()が最初に呼ばれるようになったので、それなりに楽になりましたが、filter()はけっこうきついです。2.0のfilter()は、3.0ではfilter_entries_by_path()filter_entries_by_dateに分かれていることがちょっと混乱するかも。ひとつ作ってみるとなんとなくわかるかもしれません(肝は$self->{state}->{stop}->{handlers}->{entry}あたり)。なのでarchivesとかwritebackみたいなのは簡単、entries_indexとかpaginateみたいなのは辛いということになると思います。

長。

*1: 3.0+3iからテンプレートはサブ・ディレクトリに分けることも可能になりました。(2.0と同じようにエントリと同じディレクトリに置くことも可能です)。