On 21/01/2010 23:19, E R wrote:
> Actually, it seems that using just one more layer of indirection works:
>
> $vars = { foo => { bar => 'original foo.bar' }};
That'll do the trick. Another approach is to pass in an object or function
which the templates can call. e.g. (untested)
my @images;
my $image = sub {
my $href = shift;
push(@images, $href);
return qq{<img src="/images/$href"/>};
};
$tt->process($template, { img => $image })
|| die $$tt->error;
print "Images: ", join(', ', @images), "\n"
In the template:
[% img('foo.gif') %]
I prefer this approach because it keep the templates more declarative. In
presentation-land you're simply saying "Image goes here". I code-land you
can re-define the event handler for an image to do something more interesting.
> For example, any template that produced a <IMG SRC="cid:XXX"> tag
> could also add XXX to a list returned to the perl caller. That would
> allow the perl code to know what images are referenced by the template
> and need to be attached to the email.
Yes. I think that's a really good example of one of those times when you may
want to break the "templates shouldn't have side-effects" rule [makes mental
note to remember this when writing the relevant part of the TT3 docs]
TT3 will provide a general mechanism for this kind of thing.
[% img:foo.gif %]
An unquoted URI with a scheme: prefix (aka a resource namespace in TT3 speak)
will get mapped to a resource handler. So in this case it'll lookup whatever
object you've bound to the 'img' prefix and call a method on it.
I haven't finalised all the details yet but it'll look something like this:
my $tt3 = Template3->new(
# configure the resources we want to use
resources => {
# Template::Resources::Images
images => {
dir => '/path/to/your/images',
url => '/images',
metadata => {
'foo.gif' => {
alt => 'Alternate text for foo.gif',
css => 'logo',
},
# ...etc...
},
},
},
# map namespaces to resources
namespaces => {
img => 'images',
}
);
Template::Resources::Images will have a fetch() method that looks for the
image in /path/to/your/images (throwing an error if it's missing) and returns
a Template::Resource::Image object to represent it. That'll have a default
auto-stringification method that returns an <img/> tag.
So this:
[% img:foo.gif %]
is roughly equivalent to:
$images->fetch('foo.gif')->html_tag;
The fact that it's returning an object means that you can also do stuff like
this if you want to:
[% foo = img:foo.gif %]
<img src="[% foo.url %]"
width="[% foo.width %]"
height="[% foo.height %]"
alt="[% foo.alt # from metadata %]
class="[% foo.css # ditto %]
>
Then if you want to hook into a particular resource handler to keep track of
what resources are used then it's easy to do so. Either by subclassing and
defining your own fetch() method, or by defining an on_fetch handler which
the default fetch() method will call. e.g.
# Template::Resource::Images configuration
images => {
dir => '/path/to/your/images',
url => '/images',
metadata => { ... },
on_fetch => sub {
# your code here
},
},
Furthermore, TT3 contructs a complete parse tree that you can inspect.
Here's an example of the TT3 HTML debug output for a template, showing the
tokens, parse tree, variables used, and so on:
http://tt3.template-toolkit.org/talks/tt3-lpw2009/slides/examples/expressions.html
It would relatively simple to walk the tree and find all the 'img:' resource
references, for example. So that gives you the possibility of using static
source code analysis instead of runtime resource usage tracking.
Cheers
A
_______________________________________________
templates mailing list
[email protected]
http://mail.template-toolkit.org/mailman/listinfo/templates