Hi!

Yes, this is a RFC for Yet Another Templating System. I know that
there are a lot of those around. But this own might be
different/interesting (at least I think/hope so...)

I also posted this on perlmonks:
http://www.perlmonks.org/index.pl?node_id=213300

So, here it is, in POD format:

=pod

=head1 NAME

Template::YetAnother

=head1 INTRODUCTION

=head2 Why another templating system?

There are a lot of templating modules on CPAN. Some are obvious, some
are hidden in very strange namespaces (eg HTML::Processor). Some are
used a lot, some not. I read a lot of manpages, but definitly not all
and none completly. If there is a module doing what I am proposing,
please inform me!

Before we continue, read Perrin Harkins' "Choosing a Templating
System", available here:
http://perl.apache.org/docs/tutorials/tmpl/comparison/comparison.html

There are different types of Templating Systems available. Some are
complete Application Frameworks, including stuff like Session
Management, Form Handling etc. Examples include Mason, AxKit and
Embperl. They are nice. They work. But that's not what I'm looking
for.

I want Just Templates.

Why?

Because IMO, the main reason for using templates is to seperate code
from markup. The code produces some data. The markup displays the
data. Those Application Frameworks don't seem to be too good at
seperating code and markup (I have to admit though, that I know next
to nothing about them, only that they are too big/powerfull). After
all, they B<embed> code in markup.

So I am looking for a "pipeline"-type, Just-Template System, which
reduces the number of available modules somewhat.

The best-known contestors here are TemplateToolkit
resp. Apache::Template and HTML::Template. But if you look at there
manpages, you'll quickly find references to stuff like C<TPL_LOOP>
(HTML::Template). TT2 even has it's own mini-language. So, once again,
code (even rather trivial) mixed with the markup.

There is one module, CGI::FastTemplate, that does seperate code from
markup completly. But the way different templates are strung together
seems rather comlicated to me.

But why is there no Templating System with a clean seperation of code
and markup?

There are two types of code (at least) that pollute nearly all
Templating Systems:

=over

=item * Loops

Loops are one of the things computers do best (for very good reasons,
mainly lazyness of humans). So, a template should be able to handle
large amounts of similar data using ... a template. Obvious. So a
Templating System must handle Loops. Most (all?) do it by adding some
sort of LOOP or FOREACH Syntax, thereby introducing code into the
markup. But there is another way to loop over data: Recursion.

=item * If-Blocks

As the template is rather general, you want it to handle slightly
different kinds of data differently. One very obvious example would be
to print something like "No Data" instead of C<undef>. Or to highlight
the current item in a list.

Often IF-Blocks are also used to present different kinds of data
differently, which can lead to long series of IF-ELSIF-ELSE
blocks. Which is a clear pointer that one should use Object
Orientation instead.

Another way would be to add something like attributes to the data. But as far as I 
know, attributes aren't included that thightly into Perl as OO.

=back

So I am looking for a Templating System that does Just Templating, no
code in the markup, maybe by using recursion and OO.

I didn't find anything.

So I am proposing this:

=head2 Template::YetAnother

The name is just a placeholder right now, other ideas are:

=over

=item * Template::Dumper

=item * Template::Stringify

=item * Template::OO

=item * Template::OO_Dumper

=item * any other ideas?

=back

Template::YetAnother is yet another Templating module, using a
slightly different approach than most of the other Templating modules.

The templates are completly dumb. There is B<absolutly no> piece of
code in a template - neither Perl nor "mini language". A template
consists of arbitrary text (e.g. HTML) and Template Tags, e.g.
[% title %]

Your application builds up a data structure. The data structure
consists of various Perl Data Types (Strings, Arrays, Hashes) and
Template::YetAnother Objects (or Data Structures marked with some
other kind of metainformation, e.g. with attributes)

The data structure gets passed to Template::YetAnother, which
magically find the right template for each object and replaces all
Template Tags (recursivly) with the dumped/stringified data structure.

Template::YetAnother is like Data::Dumper on steroids. It's the big
Stringifyer.

Template::YetAnother doesn't use one monolithic template, but a lot of
small template fragments, each one correlating to a data type
generated by the application.

Template::YetAnother is just an idea right now. I am trying the "write
documentation, write tests, write code" way of development... There is
only a small prove-of-concept type bit of code (I can send it/post it
if somebody cares..). I'll really appreciate feedback on this.

I hope that this descripction is clear enought. If not, let me know and I'll post some 
clarification / examples.

=head1 SYNOPSIS

  # generate a new template handler
  my $th=Template::YetAnother->new
                ({
                  namespace=>'acme',
                  template_dir=>'/projects/acme/templates/',
                 });
 
  # build up a data structure
  $data={
         title=>$th->title('this is the title'),
         breadcrumb=>[
                      $th->link({url=>'/index.html',text=>'Home'}),
                      $th->separator_breadcrumb,
                      $th->link({url=>'/acme/index.html',text=>'Acme'}),
                      $th->separator_breadcrumb,
                      $th->link({url=>'/acme/bleach.html',text=>'Bleach'}),
                     ],
         content=>[
                   $th->element({heading=>'SYNOPSIS',value=>'blabla'}),
                   $th->element({heading=>'DESCRIPTION',value=>'foo bar'}),
                  ],
         lastmod=>scalar localtime,
 
        };

   # fill template & print
   print $th->fill({data=>$data});
 
   ##################################################
   # for this to work, we need the following files in
   # /projects/acme/templates
 
   # file: main.tpl
   <html><head><title>[% title %]</title></head>
   <body>
   <center>[% breadcrumb %]</center>
   <h1>[% title %]</h1>
   [% content %]
   <hr>
   [% lastmod %]
 
   # file: link.tpl
   <a href='[% url %]'>[% text %]</a>
 
   # file: seperator.tpl
    / 
 
   # file: element.tpl
   <h3>[% heading %]</h3>
   <p>[% value %]</p>
 
   ##################################################
   # the finished template should look like this:
 
   <html><head><title>this is the title</title></head>
   <body>
   <center>
   <a href='/index.html'>Home</a> /
   <a href='/acme/index.html'>Acme</a> /
   <a href='/acme/bleach.html'>Bleach</a>
   </center>
   <h1>this is the title</h1>
   <h3>SYNOPSIS</h3>
   <p>blabla</p>
   <h3>DESCRIPTION</h3>
   <p>foo bar</p>
   <hr>
   Thu Nov  7 21:51:05 200


=head1 DESCRIPTION

=head2 new

  my $th=Template::YetAnother->new({
                            template_dir=>'/path/to/templates/',
                            # namespace=>'projectname',
                            # start_tag=>'<--',
                            # end_tag=>  '-->',
                            });

Generates a new Template::YetAnother Handler Object.

=head2 fill

  $th->fill($data);

Fill the template with the data in the data structure.

=head2 _gen

  my $fragment=$th->_gen('type',$data)

Generates a new Template Fragment

You usually do not have to call this. You just say

  $th->type($data)

and AUTOLOAD passes it to C<_gen>

=head1 EXPORT

Nothing.

=head1 SEE ALSO

Search for C<template> on http://search.cpan.org, if you dare.

=head1 AUTHOR

Thomas Klausner, [EMAIL PROTECTED], http://domm.zsi.at

=head1 COPYRIGHT

This module is Copyright (c) 2002 Thomas Klausner, ZSI.
All rights reserved.

You may use and distribute this module according to the same terms
that Perl is distributed under.

=cut


-- 
#!/usr/bin/perl                                http://domm.zsi.at
for(ref(bless[],just'another'perl'hacker)){s-:+-$"-g&&print$_.$/}

Reply via email to