早そうで有名なXslateの小技。詳しくはperldocを参照してください。使い方しらないけれどとりあえず自己流の便利と思ったものを掲載してみます。
一応、Text::Xslate::Bridge::Starを使っているのが前提です。
##共通マクロのimport
:macro multi_line -> $text {
:my $list = split($text,rx('\r?\n') );
:for $list -> $row {
:$row;
:if(!$~row.is_last) {
<br />
:}
:}
:}
:macro pager ->$pager{
<ul class="pager">
:for $pager.pages_in_navigation ->$page {
<li>
:if($page == $pager.current_page){
:$page
:}else{
<a href="<:$c.url_with({page => $page}):>"><:$page:></a>
:}
</li>
:}
</ul>
:}
:cascade with macro
:#$pagerはData::Page::Navigation
:pager($pager);
共通のマクロを1つのテンプレートに集めてcascade withで呼び出すとそれぞれのテンプレートで共通の関数が使えるようになります。
##DISPATCH処理
:macro dispatch -> $name {
:my $dispatch = {
: header => header,
: nav1 => nav1,
: nav2 => nav2,
: main => main,
: footer => footer
:}
: $dispatch[$name]();
:}
:macro header ->{}
:macro nav1 ->{}
:macro nav2 ->{}
:macro main ->{}
:macro footer ->{}
:cascade with dispatch;
:#dbから保存された表示順序を呼び出し
:# $display = ['header','nav1','main','nav2','footer']など
:for $display -> $name{
:dispatch($name);
:}
:
:override header {...}
:override main {...}
マクロをディスパッチ形式で書くことでDBやperl側で順序のソート、非表示、さまざまなパターンの記事を表現できます。
マクロは引数をつけなければブロックと同じように使えるはずなので引数なしではoverrideできます。用途によって使い分けれます。引数を使えば詳細記事を高度に書くこともできますし、呼び出しマクロとdispatch処理をわけてテンプレートごとにcascade withで分岐するとかいろいろ。
##マクロ、フィルタの応用
: form(->{
<p><label>text2</label><input type="text" /></p>
<p><label>text3</label><input type="text" /></p>
:}() ,1)| fillin($q);
:macro form -> $block,$flag{
<form>
<p><label>text</label><input type="text" /></p>
:#フォームを拡張
:$block
:given $flag{
:#分岐パターン ログイン前/後いろいろな組み合わせ
:}
</form>
:}
HTML::FillInForm::Liteを使ったFormの充足処理とフォームのパターンを組み合わせた複雑な処理を簡単にします。
1つのHTMLに同じようで違う複数のパターンのフォームを書くことも多い(非表示分またはscript要素に書いてのJSでの生成など)ので、macroで大枠のフォームを書いて匿名マクロを引数で渡して複数のパターンを使えるようにして汎用性を高めます(overrideではすべて上書きされてしまう)。
fillin関数の設定はText::Xslate::Manual::Cookbookを参照してください。
##macroでスクリプト要素のHTMLのシンタックスカラーが表示されないのを回避
エディターでscript要素内にhtmlを書くとテキストとして扱われてシンタックスカラーがテキストカラーになったり、表示がおかしいわけではないですが気持ちが乗らないときがあります。blockのoverrideやマクロで書く位置を変えることでわかりやすくかけます。
<!-- jsでテンプレート処理 -->
<!-- これはカラーリングされない-->
<script type="text/template">
<section>
<h1>テキストテキスト</h1>
</section>
</script>
<!-- マクロで展開 -->
<script type="text/template">
:template();
</script>
<!-- カラーリングされる -->
:macro template ->{
<section>
<h1>テキストテキスト</h1>
</section>
:}
##includeの挙動
includeで指定したテンプレートを実行して結果を展開するイメージ。
include($filename)とかdispatch的な処理ができたはずなのでそんな感じと勝手に思っています。