Kentaro Kuribayashi's blog

Software Engineering, Management, Books, and Daily Journal.

HTML::WidgetValidatorのプラグインを簡単に作成する

HTML::WidgetValidatorのプラグインを作成した」にて述べた通り、はてなダイアリーブログパーツ対応を可能にするモジュールであるところのHTML::WidgetValidatorのプラグインを作ったりした。今後、これを増やして行くに際して、プラグインを一個ずつちまちま作成するのは、非常に面倒である。ブログパーツは多数あれど、やるべきことは大して変わらないので、パーツのコード断片の入力さえあれば、作業をある程度までは自動化できるはずだ。
というわけで、plugin-start.plというスクリプトを書いた。スクリプトの、あまりにもてきとーな書きぶりについては、特に触れないことにする。

ここでは、Wassrを例として取り上げ、その対応プラグインを作成する。また、HTML::WidgetValidatorはすでにインストールされているものとする。
まず、以下のような書式でもって記述されたYAMLファイルを作成する。

---
author_name: プラグイン作者の名前
author_mail: プラグイン作者のメールアドレス
widgets:
  - module_name: プラグインのモジュール名(モジュール名.pmの「モジュール名」の部分)
    widget_code: ブログパーツのコード断片
    widget_name: ブログパーツの名前
    widget_url: ブログパーツ提供元のURL

  - module_name: プラグインのモジュール名(モジュール名.pmの「モジュール名」の部分)
    widget_code: ブログパーツのコード断片
    widget_name: ブログパーツの名前
    widget_url: ブログパーツ提供元のURL

...

ここでは、Wassrブログパーツ対応プラグインを作成するので、以下のようにファイルに書き込む。

---
author_name: Kentaro Kuribayashi
author_mail: kentaro at cpan.org
widgets:
  - module_name: Wassr
    widget_code: |
      <script type="text/javascript" src="http://wassr.jp/js/WassrBlogParts.js"></script><script type="text/javascript">wassr_host = "wassr.jp";wassr_userid = "kentaro";wassr_defaultview = "";wassr_bgcolor="";wassr_titlecolor="";wassr_textcolor="";wassr_boxcolor="";WassrFlashBlogParts();</script>
    widget_name: Wassr
    widget_url: http://wassr.jp/

これをwidget_info.ymlと名前を付けて保存し、以下の通り、plugin-start.plを実行する。

$ ./plugin-start.pl widget_info.yml
Creating directory lib/HTML/WidgetValidator/Widget
mkdir lib
mkdir lib/HTML
mkdir lib/HTML/WidgetValidator
mkdir lib/HTML/WidgetValidator/Widget
Creating lib/HTML/WidgetValidator/Widget/Wassr.pm
Creating directory t
mkdir t
Creating t/wassr.t

スクリプトを実行したディレクトリ直下のlibディレクトリ以下にプラグインが、tディレクトリ以下にテストが作成される。
次に、以下のようにして、テストを実行する。

$ prove -lv t/wassr.t
t/wassr....ok 1 - Wassr script - test1
ok 2 - Wassr script - test2
1..2
ok
All tests successful.
Files=1, Tests=2,  0 wallclock secs ( 0.04 cusr +  0.17 csys =  0.21 CPU)

シンプルなブログパーツなら、まずはだいたいテストが通るものと思われる(通らなくても、あとで修正するので問題ない)。生成されるテストは以下の通り。
wassr.t

use strict;
use Test::Base;
use HTML::WidgetValidator;

sub validate {
    my $validator = HTML::WidgetValidator->new(widgets => [ 'Wassr' ]);
    my $result = $validator->validate(shift);
    return $result ? $result->name : ' ';
}

filters {
    input    => [qw/chomp validate/],
    expected => [qw/chomp/],
};

__END__
=== Wassr script - test1
--- input
<script type="text/javascript" src="http://wassr.jp/js/WassrBlogParts.js"></script>
--- expected
Wassr

=== Wassr script - test2
--- input
<script type="text/javascript">wassr_host = "wassr.jp";wassr_userid = "kentaro";wassr_defaultview = "";wassr_bgcolor="";wassr_titlecolor="";wassr_textcolor="";wassr_boxcolor="";WassrFlashBlogParts();</script>
--- expected
Wassr

次に、生成されたひな形を元に、実際にプラグインを作成する。とはいえ、コード断片からデータ構造が大体抽出されているはずなので、必要な箇所を適宜手直しするだけで済むはずだ。たとえば、Wassrブログパーツの場合、ブログパーツを設置するユーザがテキスト色や背景色等を変更できるので、変更され得る部分については、正規表現でもって記述することになる。今回、変更が必要になるのはその部分のみである。
修正を終え、完成したプラグインは以下の通り。
Wassr.pm

package HTML::WidgetValidator::Widget::Wassr;
use strict;
use warnings;
use base qw(HTML::WidgetValidator::Widget);

our $VERSION = '0.01';

__PACKAGE__->name('Wassr');
__PACKAGE__->url('http://wassr.jp/');
__PACKAGE__->models([
   [
      {
         "name" => "script",
         "type" => "start",
         "attr" => {
            "src" => "http://wassr.jp/js/WassrBlogParts.js",
            "type" => "text/javascript"
         }
      },
      {
         "name" => "script",
         "type" => "end"
      }
   ],
   [
      {
         "name" => "script",
         "type" => "start",
         "attr" => {
            "type" => "text/javascript"
         }
      },
      {
         "text" => qr{\s*(?:wassr_host\s*=\s*"wassr\.jp";\s*|\s*wassr_userid\s*=\s*"\w+";\s*|\s*wassr_defaultview\s*=\s*"(?:user|friends|public|)";\s*|\s*wassr_bgcolor\s*=\s*"(?:[0-9A-Fa-f]{6}|)";\s*|\s*wassr_titlecolor\s*=\s*"(?:[0-9A-Fa-f]{6}|)";\s*|\s*wassr_textcolor\s*=\s*"(?:[0-9A-Fa-f]{6}|)";\s*|\s*wassr_boxcolor\s*=\s*"(?:[0-9A-Fa-f]{6}|)";\s*|WassrFlashBlogParts\(\);\s*)+\s*},
         "type" => "text"
      },
      {
         "name" => "script",
         "type" => "end"
      }
   ]
]);

1;

ユーザ入力による色等の設定や、コード自体の整形が行われた場合に備え、テストにたとえば以下のようなコード断片を追記する。

=== Wassr script - test3
--- input
<script type="text/javascript">
    wassr_host = "wassr.jp";
    wassr_userid = "kentaro";
    wassr_defaultview = "user";
    wassr_bgcolor="FDFAFA";
    wassr_titlecolor="C1B3B3";
    wassr_textcolor="5D5555";
    wassr_boxcolor="F8F5F5";
    WassrFlashBlogParts();
</script>
--- expected
Wassr

プラグインの動作を確認するために、再度、テストを実行する。

$ prove -lv t/wassr.t
t/wassr....ok 1 - Wassr script - test1
ok 2 - Wassr script - test2
ok 3 - Wassr script - test3
1..3
ok
All tests successful.
Files=1, Tests=3,  0 wallclock secs ( 0.06 cusr +  0.12 csys =  0.18 CPU)

以上により、Wassrブログパーツに対応したHTML::WidgetValidatorプラグインが作成できた。他のブログパーツに関しても、あまり複雑なものでないならば、同じようにして簡単にプラグインを作成することができるだろう。その際は、先に作成したwidget_info.ymlに、新たなブログパーツに関する情報を追記し、plugin-start.plを実行することになる。