追記: Template::Extract をちょっと便利にをご覧ください。
こんなテンプレート
<h2[% /[^>]*/ %]>[% d %]</h2>
[% /(?:(?!<h2|<\/h2).)+/ %]
<h3[% /[^>]*/ %]>[% t %]</h3>
[% b %]
<[% /(?:(?!posted|>).)+"posted"/ %]
とか、こんなテンプレート
<h2[% /[^>]*/ %]>[% d %]</h2>
[% ... %]
<h3[% /[^>]*/ %]>[% t %]</h3>
[% b %]
<[% /(?:(?!posted|>).)+"posted"/ %]
を用意して、うちのブログの個別記事を Template::Extract に食わせたら バナー部分で <h2></h2> と空になっている部分に引っかかってダメでした。
ちなみに、後者の場合だと、以下のように展開されているのです。
\<h2(?:[^>]*)\>(.*?)(?{
_ext((['d'], $1, 1))
})\<\/h2\>(?:(?:(?!<h2|<\/h2).)+)\<h3(?:[^>]*)\>(.*?)(?{
_ext((['t'], $2, 2))
})\<\/h3\>(.*?)(?{
_ext((['b'], $3, 3))
})\<(?:(?:(?!posted|>).)+"posted")
このうち
(.*?)(?{ _ext((['d'], $1, 1)) })
の部分で、(.*?) にマッチした部分が d の値に代入されるわけですが、 (.*?) なので、空っぽとか、変なものにマッチしてしまってだめです。
できれば、自力でかまわないので、
((?!<h2|<\/h2).+?)(?{ _ext((['d'], $1, 1)) })
と書きたいです。
print デバッグをして調べてると、Template/Extract/Compile.pm の get という関数で、[% なんとか %] を変換しているのがわかりました。[% param %] や [% /regexp/ %] なら確実に渡るようです。なので、[% /regexp/ %] をベースにして書式を拡張することにしました。拡張と言っても、upstream に投げるわけでもなく、自己満足の世界なので、以下のような書式で。
[% /[['d'|((?!<h2|<\/h2).+?)]]/ %]
変更したコードは以下のようになりました。
sub get {
if ($_[1] =~ m#^/\[\[((?:(?!\]\]|\|).)+)\|((?:(?!\]\]).)+)\]\]/$#) {
++$paren_id;
return "$2" . _re("_ext(([".$1."], \$$paren_id, $paren_id)\*\*)");
}
if ($_[1] =~ m|^/(.*)/$|) {
return "(?:$1)";
}
++$paren_id;
# ** is the placeholder for parent loop ids
return "(.*?)" . _re("_ext(([$_[1]], \$$paren_id, $paren_id)\*\*)");
}

Leave a comment