interpolate-fancy.js: JavaScriptのごく簡単なテンプレート・システム

blosxomのプラグインにinterpolate_fancyというものがある。このプラグインは、あまり強力ではないblosxomのテンプレート・システムを強化するもので、ベーシックなif/unless系の分岐が可能になる(他にインストールしているプラグインのサブルーチンを呼べたりもする)。あまりややこしくない正規表現による置換で実装されている。というわけで、簡単なテンプレートシステムとして使うためにJavaScriptに移植してみた。

ベースになったのはprototype.jsの1.5.0_rc1に実装されているTemplateクラス。これのテンプレート変数の書き方をinterpolate_fancyに合わせた<foo/>という形固定にして、条件分岐の正規表現を付け加えるという形でライブラリにしてみた。

使い方は、interpolate-fancy.jsを読み込んでおいた上で、

var tmpl = new InterpolateFancy('<foo/> <bar/> <foobar/>');
return tmpl.evaluate({
  foo:    'this is foo.',
  bar:    'this is bar.',
  foobar: 'this is foobar.'
});

と、テンプレートを渡して初期化し、データを渡してevaluate()(つまりprototype.jsのTemplateクラスと一緒)。データはフラットな連想配列で、JSONというわけではない。テンプレートはinterpolate_fancyと一緒、といってもほとんどの人は知らないのでちょこっと書いておく。

<foo/> display "foo"

<?foo>display if "foo" is defined</?>
<?!foo>display if "foo" is not defined</?>

<?foo eq="123">display if "foo" is equal 123</?>
<?foo ne="123">display if "foo" is not equal than 123</?>
<?foo lt="123">display if "foo" is less than 123</?>
<?foo gt="123">display if "foo" is greater than 123</?>
<?foo like="123">display if "foo" includes 123</?>
<?foo unlike="123">display if "foo" does not include 123</?>

最初のが基本形でfooの値に置換される。上記のデータの場合だと一行目はthis is foo.になるということ。次がdefined/undefinedの分岐で、fooが定義されているかどうか(または定義されていないかどうか)で</?>までを表示するかどうか分岐する。残りは簡単な比較による分岐で、文字列を比較・数字の大きさを比較・正規表現で検索による結果の真偽値で分岐。簡単な実験HTMLを作っておいたので、これも参考にどうぞ。

渡せるデータがフラットな連想配列のみだったりとか、ループが無いのでループしたいときはテンプレートを小分けにしなくてはならないとか、そもそも書きづらいとかいろいろと欠点がある。特に前者はどっかから拾ってきたJSONのデータを丸投げというとても便利そうな手段が使えないということになるので、JSONが確固たる位置を築きはじめた現在においてはかなり致命的な欠点と言える。

それでも要素をシコシコ作ってappendChild()よりはマシ・・・だと思う。てか、こういったテンプレート・システムのことを考えてると「XMLをXSLTで最強じゃん?」みたいな方向に思考が流れていってしまう。