File Coverage

blib/lib/Text/ScriptTemplate.pm
Criterion Covered Total %
statement 74 82 90.2
branch 21 32 65.6
condition 9 16 56.2
subroutine 11 12 91.6
pod 6 6 100.0
total 121 148 81.7


line stmt bran cond sub pod time code
1             # -*- mode: perl -*-
2              
3             package Text::ScriptTemplate;
4              
5             =head1 NAME
6              
7             Text::ScriptTemplate - Standalone ASP/JSP/PHP-style template processor
8              
9             =head1 SYNOPSIS
10              
11             use Text::ScriptTemplate;
12              
13             $text = <<'EOF'; # PHP/JSP/ASP-style template
14             <% for (1..3) { %> # - any Perl expression is supported
15             Message is: <%= $TEXT %>. # - also supports variable expansion
16             <% } %>
17             EOF
18              
19             $tmpl = new Text::ScriptTemplate; # create processor object
20             $tmpl->setq(TEXT => "hello, world"); # export data to template
21              
22             # load, fill, and print expanded result in single action
23             print $tmpl->pack($text)->fill;
24              
25             =head1 DESCRIPTION
26              
27             This is a successor of Text::SimpleTemplate, a module for template-
28             based text generation.
29              
30             Template-based text generation is a way to separate program code and
31             data, so non-programmer can control final result (like HTML) as desired
32             without tweaking the program code itself. By doing so, jobs like website
33             maintenance is much easier because you can leave program code unchanged
34             even if page redesign was needed.
35              
36             The idea of this module is simple. Whenever a block of text surrounded
37             by '<%' and '%>' (or any pair of delimiters you specify) is found, it
38             will be taken as Perl expression, and will be handled specially by
39             template processing engine. With this module, Perl script and text
40             can be intermixed closely.
41              
42             Major goal of this library is to provide support of powerful PHP-style
43             template with smaller resource. This is useful when PHP, Java/JSP,
44             or Apache::ASP is overkill, but their template style is still desired.
45              
46             =head1 INSTALLATION / REQUIREMENTS
47              
48             No other module is needed to use this module.
49             All you need is perl itself.
50              
51             For installation, standard procedure of
52              
53             perl Makefile.PL
54             make
55             make test
56             make install
57              
58             should work just fine.
59              
60             =head1 TEMPLATE SYNTAX AND USAGE
61              
62             Any block surrounded by '<%=' and '%>' will be replaced with
63             its evaluated result. So,
64              
65             <%= $message %>
66              
67             will expand to "hello" if $message variable contains "hello"
68             at the time of evaluation (when "fill" method is called).
69              
70             For block surrounded by '<%' and '%>, it will be taken as a
71             part of control structure. After all parts are merged into
72             one big script, it get evaluated and its result will become
73             expanded result. This means,
74              
75             <% for my $i (1..3) { %>
76             i = <%= %i %>
77             <% } %>
78              
79             will generate
80              
81             i = 1
82             i = 2
83             i = 3
84              
85             as a resulting output.
86              
87             Now, let's continue with more practical example.
88             Suppose you have a following template named "sample.tmpl":
89              
90             === Module Information ===
91             <% if ($HAS->{Text::ScriptTemplate}) { %>
92             Name: <%= $INFO->{Name}; %>
93             Description: <%= $INFO->{Description}; %>
94             Author: <%= $INFO->{Author}; %> <<%= $INFO->{Email}; %>>
95             <% } else { %>
96             Text::ScriptTemplate is not installed.
97             <% } %>
98              
99             With the following script...
100              
101             #!/usr/bin/perl
102              
103             use Safe;
104             use Text::ScriptTemplate;
105              
106             $tmpl = new Text::ScriptTemplate;
107             $tmpl->setq(INFO => {
108             Name => "Text::ScriptTemplate",
109             Description => "Lightweight processor for full-featured template",
110             Author => "Taisuke Yamada",
111             Email => "tyamadajp\@spam.rakugaki.org",
112             });
113             $tmpl->setq(HAS => { Text::ScriptTemplate => 1 }); # installed
114             $tmpl->load("sample.tmpl");
115              
116             print $tmpl->fill(PACKAGE => new Safe);
117              
118             ...you will get following result:
119              
120             === Module Information ===
121              
122             Name: Text::ScriptTemplate
123             Description: Lightweight processor for full-featured template
124             Author: Taisuke Yamada
125              
126             If you change
127              
128             $tmpl->setq(HAS => { Text::ScriptTemplate => 1 }); # installed
129              
130             to
131              
132             $tmpl->setq(HAS => { Text::ScriptTemplate => 0 }); # not installed
133              
134             , then you will get
135              
136             === Module Information ===
137              
138             Text::ScriptTemplate is not installed.
139              
140             You can embed any control structure as long as intermixed text
141             block is surround by set of braces. This means
142              
143             hello world<% if ($firsttime); %>
144              
145             must be written as
146              
147             <% do { %>hello world<% } if ($firsttime); %>
148              
149             to ensure surrounding block. If you want to know more on this
150             internal, please read TEMPLATE INTERNAL section for the detail.
151              
152             Also, as you might have noticed, any scalar data can be exported
153             to template namespace, even hash reference or code reference.
154              
155             Finally, although I had used "Safe" module in example above,
156             this is not a requirement. Either of
157              
158             print $tmpl->fill(PACKAGE => new Safe);
159             print $tmpl->fill(PACKAGE => new MyPackage);
160             print $tmpl->fill(PACKAGE => 'MyOtherPackage');
161             print $tmpl->fill; # uses calling context as package namespace
162              
163             will work. However, if you want to limit priviledge of program
164             logic embedded in template, using Safe module as sandbox is
165             recommended.
166              
167             =head1 RESERVED NAMES
168              
169             Currently, only reserved name pattern is the one starting
170             with "_" (underscore).
171              
172             Since template can be evaluated in separate namespace using
173             PACKAGE option (see "fill" method), this module does not have
174             much restriction on variable or function name you define in
175             theory. However, if you choose existing module namespace
176             as evaluating namespace, there could be some other predefined
177             names that may interfere with the symbols you have exported.
178              
179             Also, if you don't specify PACKAGE option, namespace of
180             calling context is used as default namespace. This means
181             all defined functions and variables in calling script
182             are visible from template, even if they weren't exported
183             by "setq" method.
184              
185             =head1 METHODS
186              
187             Following methods are currently available.
188              
189             =over 4
190              
191             =cut
192              
193 5     5   71104 use Carp;
  5         12  
  5         402  
194 5     5   22687 use FileHandle;
  5         151749  
  5         40  
195              
196 5     5   2395 use strict;
  5         25  
  5         277  
197 5     5   28 use vars qw($DEBUG $VERSION);
  5         12  
  5         7614  
198              
199             $DEBUG = 0;
200             $VERSION = '0.08';
201              
202             =item $tmpl = new Text::ScriptTemplate;
203              
204             Constructor. Returns newly created object.
205              
206             If this method was called through existing object, cloned object
207             will be returned. This cloned instance inherits all properties
208             except for internal buffer which holds template data. Cloning is
209             useful for chained template processing.
210              
211             =cut
212             sub new {
213 6     6 1 68 my $name = shift;
214 6   66     64 my $self = bless { hash => {} }, ref($name) || $name;
215              
216 6 100       60 return $self unless ref($name);
217              
218             ## inherit parent configuration
219 1         2 while (my($k, $v) = each %{$name}) {
  4         15  
220 3 100       18 $self->{$k} = $v unless $k eq 'buff';
221             }
222 1         9 $self;
223             }
224              
225             =item $tmpl->setq($name => $data, $name => $data, ...);
226              
227             Exports scalar data ($data) to template namespace,
228             with $name as a scalar variable name to be used in template.
229             You can repeat the pair to export multiple sets in one operation.
230              
231             Returns object reference to itself.
232              
233             =cut
234             sub setq {
235 10     10 1 18 my $self = shift;
236 10         39 my %pair = @_;
237              
238 10         57 while (my($key, $val) = each %pair) {
239 11         57 $self->{hash}->{$key} = $val;
240             }
241 10         34 $self;
242             }
243              
244             =item $tmpl->load($file, %opts);
245              
246             Loads template file ($file) for later evaluation.
247             File can be specified in either form of pathname or fileglob.
248              
249             This method accepts DELIM option, used to specify delimiter
250             for parsing template. It is speficied by passing reference
251             to array containing delimiter pair, just like below:
252              
253             $tmpl->load($file, DELIM => [qw()]);
254              
255             Returns object reference to itself.
256              
257             =cut
258             sub load {
259 2     2 1 4 my $self = shift;
260 2         6 my $file = shift;
261              
262 2 50 33     29 $file = new FileHandle($file) || croak($!) unless ref($file);
263 2         365 $self->pack(join("", <$file>), @_);
264             }
265              
266             =item $tmpl->pack($data, %opts);
267              
268             Loads in-memory data ($data) for later evaluation.
269             Except for this difference, works just like $tmpl->load.
270              
271             =cut
272             sub pack {
273 19     19 1 293 my $self = shift;
274 19         37 my $buff = shift;
275 19         40 my %opts = @_;
276 19         31 my $temp;
277              
278 19 50       80 $self->{DELIM} = [map { quotemeta } @{$opts{DELIM}}] if $opts{DELIM};
  0         0  
  0         0  
279 19   100     114 $self->{DELIM} ||= [qw(<% %>)];
280              
281 19         39 my $L = $self->{DELIM}->[0];
282 19         34 my $R = $self->{DELIM}->[1];
283              
284 19         40 undef $self->{buff};
285              
286 19         49 while ($buff) {
287             ## match: <%= ... %>
288 93 100       1669 if ($buff =~ s|^$L=(.*?)$R||s) {
    100          
    100          
289 26 50       164 $self->{buff} .= qq{\$_handle->(do { $1 \n});} if $1;
290             }
291             ## match: <% ... %>
292             elsif ($buff =~ s|^$L(.*?)$R||s) {
293 22 50       144 $self->{buff} .= qq{$1\n} if $1;
294             }
295             ## match: ... <% or ...
296             elsif ($buff =~ s|^(.*?)(?=$L)||s) {
297 34 50       121 if ($temp = $1) {
298 34         65 $temp =~ s|[\{\}]|\\$&|g;
299 34         716 $self->{buff} .= qq{\$_handle->(q{$temp});};
300             }
301             }
302             ## match: ... (EOF) or <% ... (EOF)
303             else {
304 11         28 last;
305             }
306              
307             #print STDERR "Remaining:\n$buff\n" if $DEBUG;
308             #print STDERR "Converted:\n$self->{buff}\n" if $DEBUG;
309             }
310              
311 19 100       56 if ($temp = $buff) {
312 11         46 $temp =~ s|[\{\}\\]|\\$&|g;
313 11         40 $self->{buff} .= qq{\$_handle->(q{$temp});};
314             }
315              
316 19 50       65 print STDERR "Converted:\n$self->{buff}\n" if $DEBUG;
317              
318 19         85 $self;
319             }
320              
321             =item $text = $tmpl->fill(%opts);
322              
323             Returns evaluated result of template, which was
324             preloaded by either $tmpl->pack or $tmpl->load method.
325              
326             This method accepts two options: PACKAGE and OHANDLE.
327              
328             PACKAGE option specifies the namespace where template
329             evaluation takes place. You can either pass the name of
330             the package, or the package object itself. So either of
331              
332             $tmpl->fill(PACKAGE => new Safe);
333             $tmpl->fill(PACKAGE => new Some::Module);
334             $tmpl->fill(PACKAGE => 'Some::Package');
335             $tmpl->fill; # uses calling context as evaluating namespace
336              
337             works. In case Safe module (or its subclass) was passed,
338             its "reval" method will be used instead of built-in eval.
339              
340             OHANDLE option is for output selection. By default, this
341             method returns the result of evaluation, but with OHANDLE
342             option set, you can instead make it print to given handle.
343             Either style of
344              
345             $tmpl->fill(OHANDLE => \*STDOUT);
346             $tmpl->fill(OHANDLE => new FileHandle(...));
347              
348             is supported.
349              
350             =cut
351             sub fill {
352 19     19 1 35 my $self = shift;
353 19         43 my %opts = @_;
354 19   66     107 my $from = $opts{PACKAGE} || caller;
355 19         29 my $name;
356             my $eval;
357              
358 5     5   41 no strict;
  5         10  
  5         3068  
359              
360             ## dynamically create evaluation engine
361 19 50       132 if (UNIVERSAL::isa($from, 'Safe')) {
362 0         0 $name = $from->root;
363 0 0   0   0 $eval = sub { my $v = $from->reval($_[0]); $@ ? $@ : $v; }
  0         0  
364 0         0 }
365             else {
366 19   33     93 $name = ref($from) || $from;
367 19         3131 $eval = eval qq{
368             package $name; sub { my \$v = eval(\$_[0]); \$@ ? \$@ : \$v; };
369             };
370             }
371              
372             ## export stored data to target namespace
373 19         42 while (my($key, $val) = each %{$self->{hash}}) {
  61         1080  
374 42 50       84 if ($DEBUG) {
375 0         0 print STDERR "Exporting to ${name}::${key}: $val\n";
376             }
377 42         42 $ {"${name}::${key}"} = $val;
  42         162  
378             }
379              
380             ## dynamically create handler for buffered or unbuffered mode
381 19 50       36 if ($ {"${name}::_OHANDLE"} = $opts{OHANDLE}) {
  19         87  
382 0         0 $eval->(q{$_handle = sub { print $_OHANDLE $_[0]; };});
383             }
384             else {
385 19         413 $eval->(q{$_handle = sub { $_OBUFFER .= $_[0]; };});
386             }
387              
388             ##
389 19         420 $eval->(qq{ undef \$_OBUFFER; $self->{buff}; \$_OBUFFER; });
390             }
391              
392             =item $text = $tmpl->include($file, \%vars, @args);
393              
394             This is a shortcut of doing
395              
396             $text = $tmpl->new->load($file)->setq(%vars)->fill(@args);
397              
398             Why a shortcut? Because this will allow you to write
399              
400             <%= $tmpl->include("subtemplate.tmpl") %>
401              
402             which is much (visually) cleaner way to include other
403             template fragment in current template.
404              
405             Note: you need to export instance as $tmpl beforehand
406             in above example.
407              
408             =cut
409             sub include {
410 1     1 1 2 my $self = shift;
411 1         2 my $file = shift;
412 1   50     5 my $vars = shift || {};
413              
414 1         3 $self->new->load($file)->setq(%{$vars})->fill(@_);
  1         4  
415             }
416              
417             =back
418              
419             =head1 TEMPLATE INTERNAL
420              
421             Internally, template processor converts template into one big
422             perl script, and then simply executes it. Conversion rule is
423             fairly simple - If you have following template,
424              
425             <% if ($bool) { %>
426             hello, <%= $name; %>
427             <% } %>
428              
429             it will be converted into
430              
431             if ($bool) {
432             $_handle->(q{
433             hello, });
434             $_handle->(do{ $name; });
435             $_handle->(q{
436             });
437             }
438              
439             Note line breaks are preserved. After all conversion is done, it
440             will be executed. And depending on existance of OHANDLE option,
441             $_handle (this is a code reference to predefined function) will
442             either print or buffer its argument.
443              
444             =head1 NOTES / BUGS
445              
446             Nested template delimiter will cause this module to fail.
447             In another word, don't do something like
448              
449             <%= "<%=" %>
450              
451             as it'll fail template parsing engine.
452              
453             =head1 SEE ALSO
454              
455             L and L
456              
457             =head1 CONTACT ADDRESS
458              
459             Please send any bug reports/comments to .
460              
461             NOTE: You need to replace "spam" to "list" in above email address
462             before sending.
463              
464             =head1 AUTHORS / CONTRIBUTORS
465              
466             - Taisuke Yamada
467              
468             =head1 COPYRIGHT
469              
470             Copyright 2001-2004. All rights reserved.
471              
472             This library is free software; you can redistribute it
473             and/or modify it under the same terms as Perl itself.
474              
475             =cut
476              
477             1;