mixi の中にテンプレートの変態度を競うコミュニティがあるのですが、今日はそこに投稿した、テンプレートで再帰処理を行った回答を紹介します。
5×5のテーブルでMTを表現する
お題はこれでした。
つまりは、以下のような表示になるHTMLをどうやって変態的に書くか、ということです。
再帰を使った回答
先に回答を書いてしまいます。
一言で表すと「mt:SetVarTemplate を利用した再帰処理」です。
MT (インデックステンプレート)
<mt:IncludeBlock module="dots">
bwwwb
bbwbb
bwbwb
bwwwb
</mt:IncludeBlock>
<mt:IncludeBlock module="dots">
bbbbb
wwbww
wwbww
wwbww
</mt:IncludeBlock>
dots (テンプレートモジュール)
<mt:SetVarTemplate name="row">
<mt:If name="contents">
<mt:Var name="contents" trim_to="1" setvar="col" />
<mt:Var name="contents" regex_replace="/.?(.*)$/","$1" setvar="contents" />
<mt:Var name="$col" />
<mt:Var name="row" />
</mt:If>
</mt:SetVarTemplate>
<mt:Var name="contents" trim="1" regex_replace="/\r\n|\r|\n/g","r" setvar="contents" />
<MTSetVars>
b=<td style="background: black"> </td>
w=<td style="background: white"> </td>
r=</tr><tr>
</MTSetVars>
<table>
<tr>
<mt:Var name="row" />
</tr>
</table>
正しい反応
素直に考えると、この場合はあえて再帰などしなくても正規表現で置換を行うだけで実現できるのですが、そこはスルーしてください。変態度で勝負しています。
再帰を使うに至った経緯
そしてここからが経緯などの説明です。
まず前提として、お題に加え以下の条件を満たすものを作成しようと考えました。
- WYSIWYGで編集できるようにする
- 任意の大きさのテーブルを表示できるようにする
MT には mt:Loop や mt:For などの繰り返し処理を行うためのタグはありますが、 「条件が満たすまで繰り返しを続ける」というような、 いわゆる while 文のような動作をさせることはできません。
そこで苦肉の策としてあがってきたのが、前置きが長くなりましたが、再帰です。
使えなかったテンプレートモジュールでの再帰1
まず普段使っている機能を利用して、テンプレートモジュールでの再帰を試みたのですが、MTがテンプレートモジュールの再帰をチェックしているためエラーとなりました。
この様な感じです。
再帰1 (テンプレートモジュール)
<mt:If name="condition">
<mt:.... />
<mt:.... />
<mt:Include module="再帰1" />
</mt:If>
使えなかったテンプレートモジュールでの再帰2
自分自身を呼び出すことができないのであれば、2つのテンプレートモジュールで相互に呼び出しあえばいけるのではないかと考えたのですが、これもMTのチェックに引っかかりエラーとなりました。なかなか手強いです。
この様な感じです。
再帰1 (テンプレートモジュール)
<mt:If name="condition">
<mt:.... />
<mt:.... />
<mt:Include module="再帰2" />
</mt:If>
再帰2 (テンプレートモジュール)
<mt:If name="condition">
<mt:.... />
<mt:.... />
<mt:Include module="再帰1" />
</mt:If>
最終的に選択された SetVarTemplate
そして最終的に選択されたのが、SetVarTemplate です。
このタグの機能は、テンプレートモジュールをテンプレート内で作成できるようなもので、プログラマにとってはなかなか心をくすぐられるところなのですが、それはそれとして、この機能については再帰がチェックされないようなので、今回の回答に採用されるところとなりました。
まとめ
「MTテンプレートで再帰的な処理を行う」ということでやり方を書いてきましたが、 一般的な良識としては、テンプレート言語でそこまで行うのはよい設計ではないと思いますので、 この Tips に関しては、よいこのみんなは真似をしないように、としておきます。
コメントする