| Typist documentation | Contained in the Typist distribution. |
Typist::Template::Context - contains and manages the context for a template
Set/get and template variable.
These three methods register template tags and take the same parameters. The difference is how the build will treat them. They require parameters of the tag name and a CODE reference to the tag handler.
If $this is an object the tag's scope will be tied to that specific object rather then the Typist::Template::Context class.
add_tag registers a variable tag. These tags must use $
inside the angle brackets such as <$MTEntryTitle$> These
types of tags do not have any type of contents.
add_container_tag registers a tag which can contain text
or other tags. Use container tags to create loops or
specific contexts.
add_conditional_tag registers a special type of container
tag that renders its contents if a some condition is true.
These tag handlers need only return a true or false value.
The rest is handled automatically. Container tags work with
the built-in Else tag to render context if a conditional
does not evaulate as true.
Registers a global filter handler. Requires the name of the filter and a reference to the filter handler be passed.
If $this is an object the filter's scope will be tied to that specific object rather then the Typist::Template::Context class.
| Typist documentation | Contained in the Typist distribution. |
package Typist::Template::Context; use strict; use base qw( Class::ErrorHandler ); use constant FALSE => -99999; use Exporter; *import = \&Exporter::import; use vars qw( @EXPORT ); @EXPORT = qw( FALSE pass_tokens pass_tokens_else ); use vars qw( %Handlers %Filters ); sub new { my $class = shift; my $ctx = bless {}, $class; $ctx->init(@_); } sub init { my $ctx = shift; my $class = ref($ctx); $ctx->{__handlers} = {}; $ctx->{__filters} = {}; if ($@) { # initialize stash. if (ref $_[0] eq 'HASH') { map { $ctx->stash($_, $_[0]->{$_}) } keys %{$_[0]}; } else { my @stash_pairs = ref $_[0] eq 'ARRAY' ? @{$_[0]} : @_; # ??? return $class->error( "Uneven number of arguments to initialize stash.") if (int(@stash_pairs) & 1); while (@stash_pairs) { my $key = shift @stash_pairs; my $val = shift @stash_pairs; $ctx->stash($key, $val); } } } $ctx; } sub var { $_[0]->{__var}->{$_[1]} = $_[2] if defined $_[2]; $_[0]->{__var}->{$_[1]}; } sub stash { my $ctx = shift; my $key = shift; $ctx->{__stash}->{$key} ||= []; if (@_) { push @{$ctx->{__stash}->{$key}}, shift; } wantarray ? @{$ctx->{__stash}->{$key}} : $ctx->{__stash}->{$key}->[-1]; } sub unstash { pop @{$_[0]->{__stash}->{$_[1]}} } #--- internal plugin methods sub register_handler { # $class/$object, $tag, $handler ref $_[0] ? $_[0]->{__handlers}->{$_[1]} = $_[2] : $Handlers{$_[1]} = $_[2]; } sub register_filter { ref $_[0] ? $_[0]->{__filters}->{$_[1]} = $_[2] : $Filters{$_[1]} = $_[2]; } sub handler_for { my $v = $_[0]->{__handlers}->{$_[1]} || $Handlers{$_[1]}; ref($v) eq 'ARRAY' ? @$v : $v; } sub post_process_handler { sub { my ($ctx, $args, $str) = @_; foreach my $name (keys %$args) { my $code = $ctx->{__filters}->{$name} || $Filters{$name} || next; $str = $code->($str, $args->{$name}, $ctx); } $str; } } #--- plugin API sub add_tag { my ($this, $name, $code) = @_; my $h = [$code, 0]; $this->register_handler($name, $h); } sub add_container_tag { my ($this, $name, $code) = @_; my $h = [$code, 1]; $this->register_handler($name, $h); } sub add_conditional_tag { my ($this, $name, $condition) = @_; my $h = [ sub { if ($condition->(@_)) { return pass_tokens(@_); } else { return pass_tokens_else(@_); } }, 1 ]; $this->register_handler($name, $h); } sub add_global_filter { my ($this, $name, $code) = @_; $this->register_filter($name, $code); } #-- exportable methods sub pass_tokens { $_[0]->stash('builder')->build($_[0], $_[0]->stash('tokens'), $_[2]); } sub pass_tokens_else { $_[0]->stash('builder')->build($_[0], $_[0]->stash('tokens_else'), $_[2]); } 1; __END__