File Coverage

lib/Template/Twostep.pm
Criterion Covered Total %
statement 211 219 96.3
branch 86 106 81.1
condition 5 9 55.5
subroutine 28 28 100.0
pod 2 22 9.0
total 332 384 86.4


line stmt bran cond sub pod time code
1             package Template::Twostep;
2              
3 1     1   9117 use 5.008005;
  1         6  
  1         55  
4 1     1   6 use strict;
  1         2  
  1         51  
5 1     1   21 use warnings;
  1         3  
  1         37  
6 1     1   1184 use integer;
  1         14  
  1         6  
7              
8 1     1   31 use Carp;
  1         1  
  1         87  
9 1     1   984 use IO::File;
  1         25495  
  1         3607  
10              
11             our $VERSION = "1.05";
12              
13             #----------------------------------------------------------------------
14             # Create a new template engine
15              
16             sub new {
17 8     8 1 613 my ($pkg, %config) = @_;
18              
19 8         38 my $parameters = $pkg->parameters();
20 8         53 my %self = (%$parameters, %config);
21              
22 8         1772 my $self = bless(\%self, $pkg);
23 8         141 $self->set_patterns();
24              
25 8         43 return $self;
26             }
27              
28             #----------------------------------------------------------------------
29             # Coerce a value to the type indicated by the sigil
30              
31             sub coerce {
32 71     71 0 13178 my ($self, $sigil, $value) = @_;
33              
34 71         83 my $data;
35 71 100       148 if (defined $value) {
    100          
36 68         101 my $ref = ref $value;
37            
38 68 100       166 if ($sigil eq '$') {
    100          
    50          
39 52 100       86 if (! $ref) {
    100          
    50          
40 50         89 $data = \$value;
41             } elsif ($ref eq 'ARRAY') {
42 1         3 my $val = @$value;
43 1         2 $data = \$val;
44             } elsif ($ref eq 'HASH') {
45 1         4 my @data = %$value;
46 1         2 my $val = @data;
47 1         3 $data = \$val;
48             }
49            
50             } elsif ($sigil eq '@') {
51 8 100       35 if (! $ref) {
    100          
    50          
52 1         3 $data = [$value];
53             } elsif ($ref eq 'ARRAY') {
54 6         32 $data = $value;
55             } elsif ($ref eq 'HASH') {
56 1         4 my @data = %$value;
57 1         4499 $data = \@data;
58             }
59            
60             } elsif ($sigil eq '%') {
61 8 100 66     42 if ($ref eq 'ARRAY' && @$value % 2 == 0) {
    100          
62 1         4 my %data = @$value;
63 1         3 $data = \%data;
64             } elsif ($ref eq 'HASH') {
65 6         14 $data = $value;
66             }
67             }
68              
69             } elsif ($sigil eq '$') {
70 1         3 $data = \$value;
71             }
72            
73 71         1008 return $data;
74             }
75              
76             #----------------------------------------------------------------------
77             # Compile a template into a subroutine which when called fills itself
78              
79             sub compile {
80 9     9 1 27514 my ($pkg, @templates) = @_;
81 9 100       57 my $self = ref $pkg ? $pkg : $pkg->new();
82              
83             # Template precedes subtemplate, which precedes subsubtemplate
84              
85 9         20 my $text;
86 9         18 my $section = {};
87 9         32 while (my $template = pop(@templates)) {
88             # If a template contains a newline, it is a string,
89             # if not, it is a filename
90              
91 12 100       59 $text = ($template =~ /\n/) ? $template : $self->slurp($template);
92 12         45 $text = $self->substitute_sections($text, $section);
93             }
94              
95 9         36 return $self->construct_code($text);
96             }
97              
98             #----------------------------------------------------------------------
99             # Compile a subroutine from the code embedded in the template
100              
101             sub construct_code {
102 9     9 0 21 my ($self, $text) = @_;
103              
104 9         55 my @lines = split(/\n/, $text);
105              
106 9         18 my $start = <<'EOQ';
107             sub {
108             $self->init_stack();
109             $self->push_stack(@_);
110             my $text = '';
111             EOQ
112              
113 9         36 my @mid = $self->parse_code(\@lines);
114              
115 9         121 my $end .= <<'EOQ';
116             return $text;
117             }
118             EOQ
119              
120 9         42 my $code = join("\n", $start, @mid, $end);
121 9         26434 my $sub = eval ($code);
122 9 50       41 croak $@ unless $sub;
123              
124 9         79 return $sub;
125             }
126              
127             #----------------------------------------------------------------------
128             # Replace variable references with hashlist fetches
129              
130             sub encode_expression {
131 31     31 0 46 my ($self, $value) = @_;
132              
133 31 50       54 if (defined $value) {
134 31         44 my $pre = '{$self->fetch_stack(\'';
135 31         35 my $mid = '\',\'';
136 31         36 my $post = '\')}';
137 31         283 $value =~ s/(?
138              
139             } else {
140 0         0 $value = '';
141             }
142              
143 31         76 return $value;
144             }
145              
146             #----------------------------------------------------------------------
147             # Replace variable references with hashlist fetches
148              
149             sub encode_text {
150 36     36 0 56 my ($self, $value) = @_;
151              
152 36 50       54 if (defined $value) {
153 36         52 my $pre = '${$self->fill_in(\'';
154 36         52 my $mid = '\',\'';
155 36         43 my $post = '\')}';
156 36         153 $value =~ s/(?
157              
158             } else {
159 0         0 $value = '';
160             }
161              
162 36         169 return $value;
163             }
164              
165             #----------------------------------------------------------------------
166             # Escape a set of characters
167              
168             sub escape {
169 34     34 0 4981 my ($self, $data) = @_;
170              
171 34         181 $data =~ s/($self->{escaped_chars_pattern})/'&#' . ord($1) . ';'/ge;
  4         15  
172 34         371 return $data;
173             }
174              
175             #----------------------------------------------------------------------
176             # Find and retrieve a value from the hash stack
177              
178             sub fetch_stack {
179 59     59 0 174 my ($self, $sigil, $name) = @_;
180              
181 59         61 my $value;
182 59         74 for my $hash (@{$self->{stack}}) {
  59         193  
183 69 100       155 if (exists $hash->{$name}) {
184 59         90 $value = $hash->{$name};
185 59         164 last;
186             }
187             }
188              
189 59         146 $value = $self->coerce($sigil, $value);
190 59 50       119 croak "Illegal type conversion: $sigil$name" unless defined $value;
191              
192 59         1827 return $value;
193             }
194              
195             #----------------------------------------------------------------------
196             # Return a value to fill in a template
197              
198             sub fill_in {
199 28     28 0 1548 my ($self, $sigil, $name) = @_;
200              
201 28         65 my $data = $self->fetch_stack($sigil, $name);
202 28         70 my $result = $self->render($data);
203              
204 28         1135 return \$result;
205             }
206              
207             #----------------------------------------------------------------------
208             # Get the translation of a template command
209              
210             sub get_command {
211 56     56 0 74 my ($self, $cmd) = @_;
212              
213 56         559 my $commands = {
214             do => "%%;",
215             each => "while (my (\$k, \$v) = each %%) {\n" .
216             "\$self->push_stack({key=>\$k, value=>\$v});",
217             endeach => "\$self->pop_stack();\n}",
218             for => "foreach (%%) {\n\$self->push_stack(\$_);",
219             endfor => "\$self->pop_stack();\n}",
220             if => "if (%%) {",
221             elsif => "} elsif (%%) {",
222             else => "} else {",
223             endif => "}",
224             set => \&set_command,
225             while => "while (%%) {",
226             endwhile => "}",
227             with => "\$self->push_stack(\\%%);",
228             endwith => "\$self->pop_stack();",
229             };
230              
231 56         344 return $commands->{$cmd};
232             }
233              
234             #----------------------------------------------------------------------
235             # Initialize the data stack
236              
237             sub init_stack {
238 11     11 0 26 my ($self) = @_;
239              
240 11         45 $self->{stack} = [];
241 11         280 return;
242             }
243              
244             #----------------------------------------------------------------------
245             # Set default parameters for package
246              
247             sub parameters {
248 8     8 0 16 my ($pkg) = @_;
249              
250 8         64 my $parameters = {
251             command_start => '',
253             escaped_chars => '<>',
254             keep_sections => 0,
255             };
256              
257 8         21 return $parameters;
258             }
259              
260             #----------------------------------------------------------------------
261             # Parse the templace source
262              
263             sub parse_code {
264 19     19 0 44 my ($self, $lines, $command) = @_;
265              
266 19         24 my @code;
267             my @stash;
268              
269 19         56 while (defined (my $line = shift @$lines)) {
270 67         293 my ($cmd, $cmdline) = $self->parse_command($line);
271            
272 67 100       126 if (defined $cmd) {
273 31 100       66 if (@stash) {
274 18         40 push(@code, '$text .= <<"EOQ";', @stash, 'EOQ');
275 18         30 @stash = ();
276             }
277 31         48 push(@code, $cmdline);
278            
279 31 100       112 if (substr($cmd, 0, 3) eq 'end') {
    100          
280 10         15 my $startcmd = substr($cmd, 3);
281 10 50 33     58 die "Mismatched block end ($command/$cmd)"
282             if defined $startcmd && $startcmd ne $command;
283 10         75 return @code;
284              
285             } elsif ($self->get_command("end$cmd")) {
286 10         43 push(@code, $self->parse_code($lines, $cmd));
287             }
288            
289             } else {
290 36         80 push(@stash, $self->encode_text($line));
291             }
292             }
293              
294 9 50       21 die "Missing end (end$command)" if $command;
295 9 100       29 push(@code, '$text .= <<"EOQ";', @stash, 'EOQ') if @stash;
296              
297 9         60 return @code;
298             }
299              
300             #----------------------------------------------------------------------
301             # Parse a command and its argument
302              
303             sub parse_command {
304 67     67 0 104 my ($self, $line) = @_;
305              
306 67 100       556 return unless $line =~ s/$self->{command_start_pattern}//;
307              
308 35         246 $line =~ s/$self->{command_end_pattern}//;
309 35         94 my ($cmd, $arg) = split(' ', $line, 2);
310 35 100       76 $arg = '' unless defined $arg;
311            
312 35         77 my $cmdline = $self->get_command($cmd);
313 35 100       82 return unless $cmdline;
314            
315 31         45 my $ref = ref ($cmdline);
316              
317 31 100       72 if (! $ref) {
    50          
318 24         55 $arg = $self->encode_expression($arg);
319 24         62 $cmdline =~ s/%%/$arg/;
320            
321             } elsif ($ref eq 'CODE') {
322 7         24 $cmdline = $cmdline->($self, $arg);
323            
324             } else {
325 0         0 die "I don't know how to handle a $ref: $cmd";
326             }
327              
328 31         159 return ($cmd, $cmdline);
329             }
330              
331             #----------------------------------------------------------------------
332             # Remove hash pushed on the stack
333              
334             sub pop_stack {
335 12     12 0 19 my ($self) = @_;
336 12         15 return shift (@{$self->{stack}});
  12         814  
337             }
338              
339             #----------------------------------------------------------------------
340             # Push one or more hashes on the stack
341              
342             sub push_stack {
343 23     23 0 54 my ($self, @hash) = @_;
344              
345 23         53 foreach my $hash (@hash) {
346 23         178 my $newhash;
347 23 100       64 if (ref $hash eq 'HASH') {
348 18         28 $newhash = $hash;
349             } else {
350 5         13 $newhash = {data => $hash};
351             }
352              
353 23         29 unshift (@{$self->{stack}}, $newhash);
  23         93  
354             }
355              
356 23         769 return;
357             }
358              
359             #----------------------------------------------------------------------
360             # Render a data structure as html
361              
362             sub render {
363 36     36 0 2605 my ($self, $data) = @_;
364              
365 36         39 my $result;
366 36         1079 my $ref = ref $data;
367              
368 36 100       225 if ($ref eq 'SCALAR') {
    100          
    100          
369 30 100       105 $result = defined $$data ? $self->escape($$data) : '';
370              
371             } elsif ($ref eq 'ARRAY') {
372 1         3 my @result;
373 1         4 foreach my $datum (@$data) {
374 2         11 my $val = $self->render($datum);
375 2         6 push(@result, "
  • $val
  • ");
    376             }
    377              
    378 1         6 $result = join("\n", '
      ', @result, '
    ');
    379              
    380             } elsif ($ref eq 'HASH') {
    381 1         3 my @result;
    382 1         9 foreach my $key (sort keys %$data) {
    383 2         8 my $val = $self->render($data->{$key});
    384 2         10 push(@result, "
    $key
    ", "
    $val
    ");
    385             }
    386              
    387 1         5 $result = join("\n", '
    ', @result, '
    ');
    388              
    389             } else {
    390 4         12 $result = $self->escape("$data");
    391             }
    392              
    393              
    394 36         433 return $result;
    395             }
    396              
    397             #----------------------------------------------------------------------
    398             # Generate code for the set command, which stores results in the hashlist
    399              
    400             sub set_command {
    401 7     7 0 15 my ($self, $arg) = @_;
    402              
    403 7         33 my ($var, $expr) = split (/\s*=\s*/, $arg, 2);
    404 7         18 $expr = $self->encode_expression($expr);
    405              
    406 7         22 return "\$self->store_stack(\'$var\', ($expr));\n";
    407             }
    408              
    409             #----------------------------------------------------------------------
    410             # Set the regular expression patterns used to match a command
    411              
    412             sub set_patterns {
    413 8     8 0 16 my ($self) = @_;
    414              
    415 8         62 $self->{command_start_pattern} = '^\s*' . quotemeta($self->{command_start});
    416              
    417 8         35 $self->{command_end_pattern} = quotemeta($self->{command_end}) . '\s*$';
    418              
    419 8 50       144 $self->{command_end_pattern} = '\s*' . $self->{command_end_pattern}
    420             if length $self->{command_end};
    421              
    422 8         33 $self->{escaped_chars_pattern} =
    423             '[' . quotemeta($self->{escaped_chars}) . ']';
    424            
    425 8         15 return;
    426             }
    427              
    428             #----------------------------------------------------------------------
    429             # Read a file into a string
    430              
    431             sub slurp {
    432 2     2 0 10 my ($self, $input) = @_;
    433              
    434 2         7 my $in;
    435 2         19 local $/;
    436              
    437 2         19 $in = IO::File->new ($input, 'r');
    438 2 50       209 return '' unless defined $in;
    439              
    440 2         48 my $text = <$in>;
    441 2         19 $in->close;
    442              
    443 2         39 return $text;
    444             }
    445              
    446             #----------------------------------------------------------------------
    447             # Store a variable in the hashlist, used by set
    448              
    449             sub store_stack {
    450 11     11 0 116 my ($self, $var, @val) = @_;
    451              
    452 11         53 my ($sigil, $name) = $var =~ /([\$\@\%])(\w+)/;
    453 11 50       29 die "Unrecognized variable type: $name" unless defined $sigil;
    454              
    455 11         16 my $i;
    456 11         14 for ($i = 0; $i < @{$self->{stack}}; $i ++) {
      19         53  
    457 15 100       44 last if exists $self->{stack}[$i]{$name};
    458             }
    459              
    460 11 100       15 $i = 0 unless $i < @{$self->{stack}};
      11         32  
    461              
    462 11 50       24 if ($sigil eq '$') {
        0          
        0          
    463 11 100       29 my $val = @val == 1 ? $val[0] : @val;
    464 11         30 $self->{stack}[$i]{$name} = $val;
    465              
    466             } elsif ($sigil eq '@') {
    467 0         0 $self->{stack}[$i]{$name} = \@val;
    468              
    469             } elsif ($sigil eq '%') {
    470 0         0 my %val = @val;
    471 0         0 $self->{stack}[$i]{$name} = \%val;
    472             }
    473              
    474 11         291 return;
    475             }
    476              
    477             #----------------------------------------------------------------------
    478             # Substitue comment delimeted sections for same blacks in template
    479              
    480             sub substitute_sections {
    481 17     17 0 3560 my ($self, $text, $section) = @_;
    482              
    483 17         94 my $name;
    484             my @output;
    485            
    486 17         254 my @tokens = split (/()/, $text);
    487              
    488 17         48 foreach my $token (@tokens) {
    489 105 100       429 if ($token =~ /^/) {
        100          
        100          
    490 22 50       56 if (defined $name) {
    491 0         0 die "Nested sections in template: $name\n";
    492             }
    493              
    494 22         45 $name = $1;
    495 22 100       71 push(@output, $token) if $self->{keep_sections};
    496            
    497             } elsif ($token =~ /^\s*/) {
    498 22 50       63 if ($name ne $1) {
    499 0         0 die "Nested sections in template: $name\n";
    500             }
    501              
    502 22         30 undef $name;
    503 22 100       64 push(@output, $token) if $self->{keep_sections};
    504            
    505             } elsif (defined $name) {
    506 22   66     99 $section->{$name} ||= $token;
    507 22         46 push(@output, $section->{$name});
    508            
    509             } else {
    510 39         93 push(@output, $token);
    511             }
    512             }
    513            
    514 17         121 return join('', @output);
    515             }
    516              
    517             1;
    518              
    519             =pod
    520              
    521             =encoding utf-8
    522              
    523             =head1 NAME
    524              
    525             Template::Twostep - Compile templates into a subroutine
    526              
    527             =head1 SYNOPSIS
    528              
    529             use Template::Twostep;
    530             my $tt = Template::Twostep->new;
    531             my $sub = $tt->compile($template, $subtemplate);
    532             my $output = $sub->($hash);
    533              
    534             =head1 DESCRIPTION
    535              
    536             This module simplifies the job of producing html text output by letting
    537             you put data into a template. Templates support the control structures in
    538             Perl: "for" and "while" loops, "if-else" blocks, and some others. Creating output
    539             is a two step process. First you generate a subroutine from one or more
    540             templates, then you call the subroutine with your data to generate the output.
    541              
    542             The template format is line oriented. Commands occupy a single line and continue
    543             to the end of line. By default commands are enclosed in html comments (), but the command start and end strings are configurable via the new method.
    545             A command may be preceded by white space. If a command is a block command, it is
    546             terminated by the word "end" followed by the command name. For example, the
    547             "for" command is terminated by an "endfor" command and the "if" command by an
    548             "endif" command.
    549              
    550             All lines may contain variables. As in Perl, variables are a sigil character
    551             ('$,' '@,' or '%') followed by one or more word characters. For example,
    552             C<$name> or C<@names>. To indicate a literal character instead of a variable,
    553             precede the sigil with a backslash. When you run the subroutine that this module
    554             generates, you pass it a reference, usually a reference to a hash, containing
    555             some data. The subroutine replaces variables in the template with the value in
    556             the field of the same name in the hash. If the types of the two disagree, the
    557             code will coerce the data to the type of the sigil. You can pass a reference to
    558             an array instead of a hash to the subroutine this module generates. If you do,
    559             the template will use C<@data> to refer to the array.
    560              
    561             There are several other template packages. I wrote this one to have the specific
    562             set of features I want in a template package. First, I wanted templates to be
    563             compiled into code. This approach has the advantage of speeding things up when
    564             the same template is used more than once. However, it also poses a security risk
    565             because code you might not want executed may be included in the template. For
    566             this reason if the script using this module can be run from the web, make sure
    567             the account that runs it cannot write to the template. I made the templates
    568             command language line oriented rather than tag oriented to prevent spurious
    569             white space from appearing in the output. Template commands and variables are
    570             similar to Perl for familiarity. The power of the template language is limited
    571             to the essentials for the sake of simplicity and to prevent mixing code with
    572             presentation.
    573              
    574             =head1 METHODS
    575              
    576             This module has two public methods. The first, new, changes the module
    577             defaults. Compile generates a subroutine from one or more templates. You Tthen
    578             call this subroutine with a reference to the data you want to substitute into
    579             the template to produce output.
    580              
    581             Using subtemplates along with a template allows you to place the common design
    582             elements in the template. You indicate where to replace parts of the template
    583             with parts of the subtemplate by using the "section" command. If the template
    584             contains a section block with the same name as a section block in the
    585             subtemplates it replaces the contents inside the section block in the template
    586             with the contents of the corresponding block in the subtemplate.
    587              
    588             =over 4
    589              
    590             =item C<$obj = Template::Twostep-Enew(command_start =E '::', command_end =E '');>
    591              
    592             Create a new parser. The configuration allows you to set a set of characters to
    593             escape when found in the data (escaped_chars), the string which starts a command
    594             (command_start), the string which ends a command (command_end), and whether
    595             section comments are kept in the output (keep_sections). All commands end at the
    596             end of line. However, you may wish to place commands inside comments and
    597             comments may require a closing string. By setting command_end, the closing
    598             string will be stripped from the end of the command.
    599              
    600             =item C<$sub = $obj-Ecompile($template, $subtemplate);>
    601              
    602             Generate a subroutine used to render data from a template and optionally from
    603             one or more subtemplates. It can be invoked by an object created by a call to
    604             new, or you can invoke it using the package name (Template::Twostep), in which
    605             case it will first call new for you. If the template string does not contain a
    606             newline, the method assumes it is a filename and it reads the template from that
    607             file.
    608              
    609             =back
    610              
    611             =head1 TEMPLATE SYNTAX
    612              
    613             If the first non-white characters on a line are the command start string, the
    614             line is interpreted as a command. The command name continues up to the first
    615             white space character. The text following the initial span of white space is the
    616             command argument. The argument continues up to the command end string, or if
    617             this is empty, to the end of the line.
    618              
    619             Variables in the template have the same format as ordinary Perl variables,
    620             a string of word characters starting with a sigil character. for example,
    621              
    622             $SUMMARY @data %dictionary
    623              
    624             are examples of variables. The subroutine this module generates will substitute
    625             values in the data it is passed for the variables in the template. New variables
    626             can be added with the "set" command.
    627              
    628             Arrays and hashes are rendered as unordered lists and definition lists when
    629             interpolating them. This is done recursively, so arbitrary structures can be
    630             rendered. This is mostly intended for debugging, as it does not provide fine
    631             control over how the structures are rendered. For finer control, use the
    632             commands described below so that the scalar fields in the structures can be
    633             accessed. Scalar fields have the characters '<' and '>' escaped before
    634             interpolating them. This set of characters can be changed by setting the
    635             configuration parameter escaped chars. Undefined fields are replaced with the
    636             empty string when rendering. If the type of data passed to the subroutine
    637             differs from the sigil on the variable the variable is coerced to the type of
    638             the sigil. This works the same as an assignment. If an array is referenced as a
    639             scalar, the length of the array is output.
    640              
    641             The following commands are supported in templates:
    642              
    643             =over 4
    644              
    645             =item do
    646              
    647             The remainder of the line is interpreted as Perl code. For assignments, use
    648             the set command.
    649              
    650             =item each
    651              
    652             Repeat the text between the "each" and "endeach" commands for each entry in the
    653             hash table. The hast table key can be accessed through the variable $key and
    654             the hash table value through the variable $value. Key-value pairs are returned
    655             in random order. For example, this code displays the contents of a hash as a
    656             list:
    657              
    658            
    659            
    660            
  • $key $value
  • 661            
    662            
    663              
    664             =item for
    665              
    666             Expand the text between the "for" and "endfor" commands several times. The
    667             "for" command takes a name of a field in a hash as its argument. The value of this
    668             name should be a reference to a list. It will expand the text in the for block
    669             once for each element in the list. Within the "for" block, any element of the list
    670             is accessible. This is especially useful for displaying lists of hashes. For
    671             example, suppose the data field name PHONELIST points to an array. This array is
    672             a list of hashes, and each hash has two entries, NAME and PHONE. Then the code
    673              
    674            
    675            

    $NAME

    676             $PHONE

    677            
    678              
    679             displays the entire phone list.
    680              
    681             =item if
    682              
    683             The text until the matching C is included only if the expression in the
    684             "if" command is true. If false, the text is skipped. The "if" command can contain
    685             an C, in which case the text before the "else" is included if the
    686             expression in the "if" command is true and the text after the "else" is included
    687             if it is false. You can also place an "elsif" command in the "if" block, which
    688             includes the following text if its expression is true.
    689              
    690            
    691             $text
    692            
    693             $text
    694            
    695              
    696             =item section
    697              
    698             If a template contains a section, the text until the endsection command will be
    699             replaced by the section block with the same name in one the subtemplates. For
    700             example, if the main template has the code
    701              
    702            
    703            
    704            
    705              
    706             and the subtemplate has the lines
    707              
    708            
    709            
    This template is copyright with a Creative Commons License.
    710            
    711              
    712             The text will be copied from a section in the subtemplate into a section of the
    713             same name in the template. If there is no block with the same name in the
    714             subtemplate, the text is used unchanged.
    715              
    716             =item set
    717              
    718             Adds a new variable or updates the value of an existing variable. The argument
    719             following the command name looks like any Perl assignment statement minus the
    720             trailing semicolon. For example,
    721              
    722            
    723              
    724             =item while
    725              
    726             Expand the text between the C and C as long as the
    727             expression following the C is true.
    728              
    729            
    730            

    Countdown ...

    731            
    732             $i
    733            
    734            
    735              
    736             =item with
    737              
    738             Lists within a hash can be accessed using the "for" command. Hashes within a
    739             hash are accessed using the "with" command. For example:
    740              
    741            
    742            

    $street

    743             $city, $state $zip
    744            
    745              
    746             =back
    747              
    748             =head1 ERRORS
    749              
    750             What to check when this module throws an error
    751              
    752             =over 4
    753              
    754             =item Couldn't read template
    755              
    756             The template is in a file and the file could not be opened. Check the filename
    757             and permissions on the file. Relative filenames can cause problems and the web
    758             server is probably running another account than yours.
    759              
    760             =item Illegal type conversion
    761              
    762             The sigil on a variable differs from the data passed to the subroutine and
    763             conversion. between the two would not be legal. Or you forgot to escape the '@'
    764             in an email address by preceding it with a backslash.
    765              
    766             =item Unknown command
    767              
    768             Either a command was spelled incorrectly or a line that is not a command
    769             begins with the command start string.
    770              
    771             =item Missing end
    772              
    773             The template contains a command for the start of a block, but
    774             not the command for the end of the block. For example an "if" command
    775             is missing an "endif" command.
    776              
    777             =item Mismatched block end
    778              
    779             The parser found a different end command than the begin command for the block
    780             it was parsing. Either an end command is missing, or block commands are nested
    781             incorrectly.
    782              
    783             =item Syntax error
    784              
    785             The expression used in a command is not valid Perl.
    786              
    787             =back
    788              
    789             =head1 LICENSE
    790              
    791             Copyright (C) Bernie Simon.
    792              
    793             This library is free software; you can redistribute it and/or modify
    794             it under the same terms as Perl itself.
    795              
    796             =head1 AUTHOR
    797              
    798             Bernie Simon Ebernie.simon@gmail.comE
    799              
    800             =cut