[Templates] filtering includes

Andy Wardley abw@andywardley.com
Tue, 5 Nov 2002 13:55:12 +0000


Rafiq Ismail wrote:
> I'm looking for an easy way to solve a problem, which I'm currently
> facing.  We have a HUGE bunch of default html_header, footer, etc files
> which tie into our legacy non-template system.  They are all raw html with
> the exception of a couple of unconventioanl strings which get substituted
> into, in order to provide link uri's.

You could write your own custom parser for parsing templates with this
alternate syntax.  Here's an example of a parser which looks for template 
variables marked like this: <MYTAG:foo>.  

  package My::Parser;
  use Template::Directive;
  use Template::Base;
  use base qw( Template::Base );

  our $FACTORY = 'Template::Directive';

  sub parse {
      my ($self, $text, $info) = @_;

      my $perl = '';

      while ($text =~ / \G (.*?) <MYTAG: (.*?) > /sxgc) {
          if ($1) {
              # text preceeding a directive
              $perl .= $FACTORY->textblock($1) . "\n";
          }
          # a variable directive
          $perl .= $FACTORY->get($FACTORY->ident(["'$2'"])) . "\n";
      };
      # any text remaining at end of file after last directive
      if ($text =~ / \G (.*) $/sxg) {
          $perl .= $FACTORY->textblock($1) . "\n";
      }

      $perl = $FACTORY->template($perl);

      return {
          BLOCK     => $perl,
          DEFBLOCKS => { },
          METADATA  => { },
      };
  }

Now you can use this parser within TT to parse your own custom template
syntax.

  use Template;

  my $tt = Template->new({
      PARSER => My::Parser->new(),
  });

  my $vars = {
      animal => 'cat',
      place  => 'mat',
  };

  $tt->process(\*DATA, $vars) || die $tt->error();

  __DATA__
  The <MYTAG:animal> sat on the <MYTAG:place>.

You'll probably want to use multiple providers.  One for your custom
templates using the custom parser, another for all the other regular 
TT templates.

  my $tt = Template->new({
    LOAD_TEMPLATES => {
      # regular provider
      Template::Provider->new({ INCLUDE_PATH => '...' }),

      # provider for custom templates
      Template::Provider->new({ PARSER => My::Parser->new() }),
    },
  });


Subclassing the parser is a bit messy (something else that's destined
to get better in TT3) but if your existing tag syntax is nothing more
than variable substitution, the above should do the trick just fine.


HTH
A