Template::Extract で遊ぶ

| 0 Comments | 0 TrackBacks

追記: 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)\*\*)");
}

No TrackBacks

TrackBack URL: http://blog.woremacx.com/MT/mt-tb.cgi/13

Leave a comment