line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Text::TemplateLite; |
2
|
|
|
|
|
|
|
|
3
|
2
|
|
|
2
|
|
62366
|
use 5.006; |
|
2
|
|
|
|
|
8
|
|
|
2
|
|
|
|
|
80
|
|
4
|
2
|
|
|
2
|
|
11
|
use strict; |
|
2
|
|
|
|
|
10
|
|
|
2
|
|
|
|
|
78
|
|
5
|
2
|
|
|
2
|
|
12
|
use warnings; |
|
2
|
|
|
|
|
28
|
|
|
2
|
|
|
|
|
58
|
|
6
|
2
|
|
|
2
|
|
11
|
use Carp; |
|
2
|
|
|
|
|
2
|
|
|
2
|
|
|
|
|
204
|
|
7
|
2
|
|
|
2
|
|
13
|
use Scalar::Util qw(blessed); |
|
2
|
|
|
|
|
4
|
|
|
2
|
|
|
|
|
160
|
|
8
|
2
|
|
|
2
|
|
1297
|
use Text::TemplateLite::Renderer; |
|
2
|
|
|
|
|
4
|
|
|
2
|
|
|
|
|
4927
|
|
9
|
|
|
|
|
|
|
|
10
|
|
|
|
|
|
|
=head1 NAME |
11
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
Text::TemplateLite - Pure-Perl text templates with bare-bones syntax, |
13
|
|
|
|
|
|
|
compact size, and limitable resource usage |
14
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
=head1 VERSION |
16
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
Version 0.01 |
18
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
=cut |
20
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
our $VERSION = '0.01'; |
22
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
=head1 SYNOPSIS |
24
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
use Text::TemplateLite; |
26
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
my $tpl = Text::TemplateLite->new; |
28
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
$tpl->set('Hello, <<$who>>'); |
30
|
|
|
|
|
|
|
print $tpl->render({ who => 'world' })->result; |
31
|
|
|
|
|
|
|
# Generates "Hello, world" |
32
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
my $rdr = $tpl->new_renderer; |
34
|
|
|
|
|
|
|
print $rdr->render({ who => 'universe' })->result; |
35
|
|
|
|
|
|
|
# Generates "Hello, universe" with a configurable and |
36
|
|
|
|
|
|
|
# reusable renderer (see Text::TemplateLite::Renderer) |
37
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
=head1 DESCRIPTION |
39
|
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
=head2 Overview |
41
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
Text::TemplateLite is intended primarily for "string-sized" templating |
43
|
|
|
|
|
|
|
(e.g. for message localization rather than entire "pages") using compact |
44
|
|
|
|
|
|
|
(terse?) templates with a (relatively) simple syntax. |
45
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
It is anticipated that templates may (at least sometimes) be entered or |
47
|
|
|
|
|
|
|
managed by users whose skill set does not include "Perl programmer" |
48
|
|
|
|
|
|
|
(perhaps a web site administrator, translator, or non-Perl programmer). |
49
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
Basic length and execution limits provide a measure of protection against |
51
|
|
|
|
|
|
|
accidental or malicious time- and/or space-based resource attacks. These |
52
|
|
|
|
|
|
|
are managed by the rendering companion class, |
53
|
|
|
|
|
|
|
L. |
54
|
|
|
|
|
|
|
|
55
|
|
|
|
|
|
|
By design, only basic functionality is included in this module. Use parts |
56
|
|
|
|
|
|
|
or all of the L function library and/or |
57
|
|
|
|
|
|
|
create your own custom library to extend its capabilities. |
58
|
|
|
|
|
|
|
|
59
|
|
|
|
|
|
|
=head2 Syntax |
60
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
A template consists of literal text and template code. Any text between |
62
|
|
|
|
|
|
|
"<<" and ">>" that does not contain "<<" or ">>" is treated as template |
63
|
|
|
|
|
|
|
code. Everything else is literal text. |
64
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
Template code can contain sequences in any combination of the following: |
66
|
|
|
|
|
|
|
|
67
|
|
|
|
|
|
|
=over |
68
|
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
=item Comments |
70
|
|
|
|
|
|
|
|
71
|
|
|
|
|
|
|
Anything from "/*" to the closest "*/" is ignored and does not count |
72
|
|
|
|
|
|
|
as a step (see L<"Steps">). |
73
|
|
|
|
|
|
|
|
74
|
|
|
|
|
|
|
=item String Literals |
75
|
|
|
|
|
|
|
|
76
|
|
|
|
|
|
|
To include literal text within code text, surround the text with single |
77
|
|
|
|
|
|
|
quotes (') or double quotes ("). You can "escape" either kind of quote |
78
|
|
|
|
|
|
|
or < or > in either kind of string by preceding it with a backslash |
79
|
|
|
|
|
|
|
(\', \", \<, or \>). Use '<\<' or '>\>' to generate "<<" or ">>" within |
80
|
|
|
|
|
|
|
code text. |
81
|
|
|
|
|
|
|
|
82
|
|
|
|
|
|
|
No variable substitution is performed within either kind of string literal. |
83
|
|
|
|
|
|
|
|
84
|
|
|
|
|
|
|
=item Numeric Literals |
85
|
|
|
|
|
|
|
|
86
|
|
|
|
|
|
|
Numeric literals consist of an optional minus sign and one or more |
87
|
|
|
|
|
|
|
digits, optionally followed by a decimal point and additional digits. |
88
|
|
|
|
|
|
|
|
89
|
|
|
|
|
|
|
=item Variable Substitutions |
90
|
|
|
|
|
|
|
|
91
|
|
|
|
|
|
|
A dollar sign ($) followed by a name consisting of one or more letters, |
92
|
|
|
|
|
|
|
digits, underscores (_), and/or non-initial periods (.) will be replaced |
93
|
|
|
|
|
|
|
by the corresponding value from the variables supplied either at rendering |
94
|
|
|
|
|
|
|
time or set during template execution. |
95
|
|
|
|
|
|
|
|
96
|
|
|
|
|
|
|
Variables can also store nested templates. Substituting a variable |
97
|
|
|
|
|
|
|
containing a nested template executes the nested template. These templates |
98
|
|
|
|
|
|
|
can be passed parameters using the same syntax as function calls. The |
99
|
|
|
|
|
|
|
parameters will appear in the nested template as template variables "$1", |
100
|
|
|
|
|
|
|
"$2", etc. Parameter "$0" will contain the number of parameters. |
101
|
|
|
|
|
|
|
|
102
|
|
|
|
|
|
|
Parameters after a non-template variable are ignored, unevaluated. |
103
|
|
|
|
|
|
|
|
104
|
|
|
|
|
|
|
$foo /* variable or nested template without parameters */ |
105
|
|
|
|
|
|
|
"$foo is " $foo /* only the second $foo is substituted */ |
106
|
|
|
|
|
|
|
$foo('hey', 'there') /* nested template(?) with parameters */ |
107
|
|
|
|
|
|
|
|
108
|
|
|
|
|
|
|
See L for information |
109
|
|
|
|
|
|
|
on creating nested templates. |
110
|
|
|
|
|
|
|
|
111
|
|
|
|
|
|
|
In future releases, periods in variable names may have structural meaning |
112
|
|
|
|
|
|
|
(e.g. to support lists or maps). Do not write templates that expect "$a" |
113
|
|
|
|
|
|
|
to be unrelated to "$a.b" or "$a.5", for example. For now, however, periods |
114
|
|
|
|
|
|
|
are just part of the name. |
115
|
|
|
|
|
|
|
|
116
|
|
|
|
|
|
|
=item Function And External Template Calls |
117
|
|
|
|
|
|
|
|
118
|
|
|
|
|
|
|
Any other combination of alpha-numeric characters, or combination of symbols |
119
|
|
|
|
|
|
|
other than parentheses or comma, are treated as the name of a function or |
120
|
|
|
|
|
|
|
external template call. Either may optionally be passed a list of zero or |
121
|
|
|
|
|
|
|
more parameters, surrounded by parentheses and separated by commas. |
122
|
|
|
|
|
|
|
|
123
|
|
|
|
|
|
|
Parameters to external templates should be provided in "name, value" pairs. |
124
|
|
|
|
|
|
|
|
125
|
|
|
|
|
|
|
cr nl /* call "cr" and "nl" without parameters */ |
126
|
|
|
|
|
|
|
foo('hey', 'there') /* pass foo two strings (or hey=there) */ |
127
|
|
|
|
|
|
|
|
128
|
|
|
|
|
|
|
See L for some related |
129
|
|
|
|
|
|
|
functions. |
130
|
|
|
|
|
|
|
|
131
|
|
|
|
|
|
|
Calls to unregistered names will instead call a definition with a zero-length |
132
|
|
|
|
|
|
|
name, if registered, or L<"undef_call($name, $args, $renderer)"> otherwise. |
133
|
|
|
|
|
|
|
|
134
|
|
|
|
|
|
|
=back |
135
|
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
=head2 Steps |
137
|
|
|
|
|
|
|
|
138
|
|
|
|
|
|
|
Each element (literal, substitution, call, etc.) evaluated during template |
139
|
|
|
|
|
|
|
execution is counted as a "step". For example: |
140
|
|
|
|
|
|
|
|
141
|
|
|
|
|
|
|
$=('a', 2) /* 3 steps: $=, 'a', and 2 */ |
142
|
|
|
|
|
|
|
??(=($a, 1), /* +4 steps: ??, =, $a, and 1 */ |
143
|
|
|
|
|
|
|
'$a is 1', /* 1 step not eval'd/counted (= was false) */ |
144
|
|
|
|
|
|
|
=($a, 2), /* +3 steps: =, $a, 2 */ |
145
|
|
|
|
|
|
|
'$a is 2', /* +1 step: '$a is 2' */ |
146
|
|
|
|
|
|
|
'other') /* 1 step not eval'd/counted (not reached) */ |
147
|
|
|
|
|
|
|
/* renders '$a is 2' in 11 steps */ |
148
|
|
|
|
|
|
|
|
149
|
|
|
|
|
|
|
?*(<($a, 4), 'loop' $=('a', +($a, 1))) |
150
|
|
|
|
|
|
|
/* 1 step: ?* |
151
|
|
|
|
|
|
|
+3 steps: <, $a, 4 (assuming $a is 2 from above) |
152
|
|
|
|
|
|
|
+6 steps: 'loop', $=, 'a', +, $a, 1 ($a becomes 3) |
153
|
|
|
|
|
|
|
+3 steps: <, $a, 4 |
154
|
|
|
|
|
|
|
+6 steps: 'loop', $=, 'a', +, $a, 1 ($a becomes 4) |
155
|
|
|
|
|
|
|
+3 steps: <, $a, 4 (now false, so loop stops) |
156
|
|
|
|
|
|
|
renders 'looploop' in 22 steps */ |
157
|
|
|
|
|
|
|
|
158
|
|
|
|
|
|
|
=head1 USER METHODS |
159
|
|
|
|
|
|
|
|
160
|
|
|
|
|
|
|
This section describes methods for normal usage. |
161
|
|
|
|
|
|
|
|
162
|
|
|
|
|
|
|
=head2 new( ) |
163
|
|
|
|
|
|
|
|
164
|
|
|
|
|
|
|
This returns a new Text::TemplateLite template engine. |
165
|
|
|
|
|
|
|
|
166
|
|
|
|
|
|
|
=cut |
167
|
|
|
|
|
|
|
|
168
|
|
|
|
|
|
|
sub new { |
169
|
2
|
|
|
2
|
1
|
22
|
my ($class) = @_; |
170
|
|
|
|
|
|
|
|
171
|
2
|
|
|
|
|
10
|
return bless { |
172
|
|
|
|
|
|
|
}, $class; |
173
|
|
|
|
|
|
|
} |
174
|
|
|
|
|
|
|
|
175
|
|
|
|
|
|
|
=head2 register($name, $definition) |
176
|
|
|
|
|
|
|
|
177
|
|
|
|
|
|
|
Register a function (coderef definition) or an external template |
178
|
|
|
|
|
|
|
(Text::TemplateLite definition). |
179
|
|
|
|
|
|
|
|
180
|
|
|
|
|
|
|
$ttl->register('my_function', sub { |
181
|
|
|
|
|
|
|
my ($name, $args, $renderer) = @_; |
182
|
|
|
|
|
|
|
"You called function $name." }); |
183
|
|
|
|
|
|
|
|
184
|
|
|
|
|
|
|
my $other_ttl = Text::TemplateLite->new(); |
185
|
|
|
|
|
|
|
$other_ttl->set('You called an external template.'); |
186
|
|
|
|
|
|
|
$ttl->register('external_tpl', $other_ttl); |
187
|
|
|
|
|
|
|
|
188
|
|
|
|
|
|
|
If you register a definition with a zero-length name, it will be called |
189
|
|
|
|
|
|
|
in place of any call to an undefined function or external template instead |
190
|
|
|
|
|
|
|
of using the default undefined-call handler, |
191
|
|
|
|
|
|
|
L<"undef_call($name, $args, $renderer)">. |
192
|
|
|
|
|
|
|
|
193
|
|
|
|
|
|
|
Library functions (registered as coderefs) are passed three parameters: |
194
|
|
|
|
|
|
|
|
195
|
|
|
|
|
|
|
=over |
196
|
|
|
|
|
|
|
|
197
|
|
|
|
|
|
|
=item $name |
198
|
|
|
|
|
|
|
|
199
|
|
|
|
|
|
|
This is the name of the function as it was invoked from the template. |
200
|
|
|
|
|
|
|
|
201
|
|
|
|
|
|
|
=item $args |
202
|
|
|
|
|
|
|
|
203
|
|
|
|
|
|
|
This is an arrayref of code sequences for any parameters passed from the |
204
|
|
|
|
|
|
|
template. See L<"execute_sequence($code, $renderer)"> and |
205
|
|
|
|
|
|
|
L<"execute_each($list, $renderer)">. |
206
|
|
|
|
|
|
|
|
207
|
|
|
|
|
|
|
=item $renderer |
208
|
|
|
|
|
|
|
|
209
|
|
|
|
|
|
|
This is the instance of L that is managing |
210
|
|
|
|
|
|
|
rendering of the template. |
211
|
|
|
|
|
|
|
|
212
|
|
|
|
|
|
|
=back |
213
|
|
|
|
|
|
|
|
214
|
|
|
|
|
|
|
=cut |
215
|
|
|
|
|
|
|
|
216
|
|
|
|
|
|
|
sub register { |
217
|
3
|
|
|
3
|
1
|
545
|
my ($self, $name, $def) = @_; |
218
|
|
|
|
|
|
|
|
219
|
3
|
|
|
|
|
11
|
$self->{defs}{$name} = $def; |
220
|
3
|
|
|
|
|
7
|
return $self; |
221
|
|
|
|
|
|
|
} |
222
|
|
|
|
|
|
|
|
223
|
|
|
|
|
|
|
=head2 unregister($name) |
224
|
|
|
|
|
|
|
|
225
|
|
|
|
|
|
|
Unregister a function or external template definition. |
226
|
|
|
|
|
|
|
|
227
|
|
|
|
|
|
|
=cut |
228
|
|
|
|
|
|
|
|
229
|
|
|
|
|
|
|
sub unregister { |
230
|
2
|
|
|
2
|
1
|
10
|
my ($self, $name) = @_; |
231
|
|
|
|
|
|
|
|
232
|
2
|
|
|
|
|
10
|
delete($self->{defs}{$name}); |
233
|
2
|
|
|
|
|
6
|
return $self; |
234
|
|
|
|
|
|
|
} |
235
|
|
|
|
|
|
|
|
236
|
|
|
|
|
|
|
=head2 set($string) |
237
|
|
|
|
|
|
|
|
238
|
|
|
|
|
|
|
Set or change the template string (see L<"Syntax">) and return the |
239
|
|
|
|
|
|
|
template object. |
240
|
|
|
|
|
|
|
|
241
|
|
|
|
|
|
|
=cut |
242
|
|
|
|
|
|
|
|
243
|
|
|
|
|
|
|
sub set { |
244
|
20
|
|
|
20
|
1
|
44
|
my ($self, $template) = @_; |
245
|
|
|
|
|
|
|
|
246
|
20
|
|
|
|
|
53
|
delete($self->{code}); |
247
|
|
|
|
|
|
|
|
248
|
20
|
|
|
|
|
150
|
my @parts = split(/<<(?!<)((?:[^<>]|<[^<]|>[^>])*)>>/s, $template); |
249
|
20
|
|
|
|
|
28
|
my @code; |
250
|
|
|
|
|
|
|
|
251
|
|
|
|
|
|
|
# Template "text<>text<>..." => (text, code, text, code, ...) |
252
|
20
|
|
|
|
|
55
|
for (my $literal = 1; @parts; $literal = !$literal) { |
253
|
37
|
100
|
|
|
|
118
|
if (length(my $part = shift(@parts))) { |
254
|
22
|
100
|
|
|
|
41
|
if ($literal) { |
255
|
|
|
|
|
|
|
# Even elements are literal text. |
256
|
8
|
|
|
|
|
36
|
push(@code, [ "''" => $part ]); |
257
|
|
|
|
|
|
|
} else { |
258
|
|
|
|
|
|
|
# Odd elements are template code text. |
259
|
14
|
|
|
|
|
62
|
my @tokens = $self->get_tokens($part); |
260
|
14
|
|
|
|
|
50
|
push(@code, $self->parse_list(\@tokens, [])); |
261
|
|
|
|
|
|
|
} |
262
|
|
|
|
|
|
|
} |
263
|
|
|
|
|
|
|
} |
264
|
|
|
|
|
|
|
|
265
|
20
|
|
|
|
|
40
|
$self->{code} = \@code; |
266
|
|
|
|
|
|
|
|
267
|
20
|
|
|
|
|
53
|
return $self; |
268
|
|
|
|
|
|
|
} |
269
|
|
|
|
|
|
|
|
270
|
|
|
|
|
|
|
=head2 new_renderer( ) |
271
|
|
|
|
|
|
|
|
272
|
|
|
|
|
|
|
Returns a new renderer companion object assigned to this template |
273
|
|
|
|
|
|
|
engine. See L. |
274
|
|
|
|
|
|
|
|
275
|
|
|
|
|
|
|
=cut |
276
|
|
|
|
|
|
|
|
277
|
|
|
|
|
|
|
sub new_renderer { |
278
|
5
|
|
|
5
|
1
|
2648
|
return Text::TemplateLite::Renderer->new->template(shift); |
279
|
|
|
|
|
|
|
} |
280
|
|
|
|
|
|
|
|
281
|
|
|
|
|
|
|
=head2 render(\%variables) |
282
|
|
|
|
|
|
|
|
283
|
|
|
|
|
|
|
Create a new renderer via L<"new_renderer( )">, render the template, |
284
|
|
|
|
|
|
|
and return the renderer (not the result). |
285
|
|
|
|
|
|
|
|
286
|
|
|
|
|
|
|
=cut |
287
|
|
|
|
|
|
|
|
288
|
|
|
|
|
|
|
sub render { |
289
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
290
|
|
|
|
|
|
|
|
291
|
0
|
|
|
|
|
0
|
return $self->new_renderer->render(@_); |
292
|
|
|
|
|
|
|
} |
293
|
|
|
|
|
|
|
|
294
|
|
|
|
|
|
|
=head1 AUTHOR METHODS |
295
|
|
|
|
|
|
|
|
296
|
|
|
|
|
|
|
This section describes methods generally only used by library function |
297
|
|
|
|
|
|
|
authors. |
298
|
|
|
|
|
|
|
|
299
|
|
|
|
|
|
|
=head2 execute_sequence($code, $renderer) |
300
|
|
|
|
|
|
|
|
301
|
|
|
|
|
|
|
Execute the code step(s), if any, in the sequence $code using renderer |
302
|
|
|
|
|
|
|
$renderer. |
303
|
|
|
|
|
|
|
|
304
|
|
|
|
|
|
|
A code sequence looks like: |
305
|
|
|
|
|
|
|
|
306
|
|
|
|
|
|
|
[ \@step1code, \@step2code, ... ] |
307
|
|
|
|
|
|
|
|
308
|
|
|
|
|
|
|
This method is useful for "progressive" evaluation of individual parameters to |
309
|
|
|
|
|
|
|
functions. It is also used to execute the code resulting from each section |
310
|
|
|
|
|
|
|
of template code in a template. |
311
|
|
|
|
|
|
|
|
312
|
|
|
|
|
|
|
Execution may stop or step results may be truncated in response to |
313
|
|
|
|
|
|
|
exceeded execution limits or a stop set in the rendering information. |
314
|
|
|
|
|
|
|
|
315
|
|
|
|
|
|
|
A sequence consisting of a single function call can return multiple values |
316
|
|
|
|
|
|
|
if execute_sequence is called in array context. Otherwise, the concatenation |
317
|
|
|
|
|
|
|
of step values is returned. |
318
|
|
|
|
|
|
|
|
319
|
|
|
|
|
|
|
=cut |
320
|
|
|
|
|
|
|
|
321
|
|
|
|
|
|
|
sub execute_sequence { |
322
|
31
|
|
|
31
|
1
|
41
|
my ($self, $code, $renderer) = @_; |
323
|
|
|
|
|
|
|
|
324
|
|
|
|
|
|
|
# Return nothing on empty sequence or rendering stop. |
325
|
31
|
50
|
100
|
|
|
206
|
return wantarray? (): '' |
|
|
100
|
66
|
|
|
|
|
326
|
|
|
|
|
|
|
if !$code || !@$code || $renderer->info->{stop}; |
327
|
|
|
|
|
|
|
|
328
|
27
|
|
|
|
|
77
|
my $max_len = $renderer->limit('step_length'); |
329
|
27
|
|
|
|
|
38
|
my @parts; |
330
|
|
|
|
|
|
|
|
331
|
27
|
100
|
66
|
|
|
71
|
if (wantarray && @$code == 1) { |
332
|
|
|
|
|
|
|
# A one-step sequence may return multiple values. |
333
|
2
|
|
|
|
|
6
|
@parts = $self->execute_step($code->[0], $renderer); |
334
|
|
|
|
|
|
|
|
335
|
2
|
50
|
|
|
|
11
|
if (defined($max_len)) { |
336
|
|
|
|
|
|
|
# Enforce the step-length limit value-by-value. |
337
|
0
|
|
|
|
|
0
|
foreach (@parts) { |
338
|
0
|
0
|
|
|
|
0
|
if (length > $max_len) { |
339
|
0
|
|
|
|
|
0
|
$_ = substr($_, 0, $max_len); |
340
|
0
|
|
|
|
|
0
|
$renderer->exceeded_limits('step_length'); |
341
|
|
|
|
|
|
|
} |
342
|
|
|
|
|
|
|
} |
343
|
|
|
|
|
|
|
} |
344
|
2
|
|
|
|
|
15
|
return @parts; |
345
|
|
|
|
|
|
|
} |
346
|
|
|
|
|
|
|
|
347
|
|
|
|
|
|
|
# Combine all the parts of a multi-step sequence into a single value. |
348
|
|
|
|
|
|
|
# The result must not exceed the step-length limit. |
349
|
25
|
|
|
|
|
53
|
foreach (@$code) { |
350
|
43
|
|
|
|
|
100
|
my $part = join('', $self->execute_step($_, $renderer)); |
351
|
|
|
|
|
|
|
|
352
|
43
|
100
|
|
|
|
119
|
if (defined($max_len)) { |
353
|
|
|
|
|
|
|
# Enforce the length limit for the entire sequence. |
354
|
1
|
|
|
|
|
3
|
my $part_len = length($part); |
355
|
1
|
50
|
|
|
|
5
|
if ($part_len > $max_len) { |
356
|
1
|
|
|
|
|
3
|
push(@parts, substr($part, 0, $max_len)); |
357
|
1
|
|
|
|
|
5
|
$renderer->exceeded_limits('step_length'); |
358
|
1
|
|
|
|
|
2
|
last; |
359
|
|
|
|
|
|
|
} |
360
|
0
|
|
|
|
|
0
|
$max_len -= $part_len; |
361
|
|
|
|
|
|
|
} |
362
|
|
|
|
|
|
|
|
363
|
42
|
|
|
|
|
105
|
push(@parts, $part); |
364
|
|
|
|
|
|
|
} |
365
|
|
|
|
|
|
|
|
366
|
25
|
|
|
|
|
115
|
return join('', @parts); |
367
|
|
|
|
|
|
|
} |
368
|
|
|
|
|
|
|
|
369
|
|
|
|
|
|
|
=head2 execute_each($list, $renderer) |
370
|
|
|
|
|
|
|
|
371
|
|
|
|
|
|
|
Execute an arrayref of code sequences and return a corresponding array |
372
|
|
|
|
|
|
|
of results. This is typically used by library functions to "bulk evaluate" |
373
|
|
|
|
|
|
|
their list of call parameters. |
374
|
|
|
|
|
|
|
|
375
|
|
|
|
|
|
|
$ttl->register('echo', sub { |
376
|
|
|
|
|
|
|
my ($name, $args, $renderer) = @_; |
377
|
|
|
|
|
|
|
|
378
|
|
|
|
|
|
|
"$name(" . join(', ', $renderer->execute_each($args)) |
379
|
|
|
|
|
|
|
. ")"; |
380
|
|
|
|
|
|
|
}); |
381
|
|
|
|
|
|
|
$ttl->set(q{<>}); |
382
|
|
|
|
|
|
|
$ttl->render; # renders "echo(hello, world)" |
383
|
|
|
|
|
|
|
|
384
|
|
|
|
|
|
|
$ttl->register('uses2', sub { |
385
|
|
|
|
|
|
|
my ($name, $args, $renderer) = @_; |
386
|
|
|
|
|
|
|
|
387
|
|
|
|
|
|
|
join('', $renderer->template->execute_each(@{$args}[0, 1])); |
388
|
|
|
|
|
|
|
}); |
389
|
|
|
|
|
|
|
$ttl->set(q{<>}); |
390
|
|
|
|
|
|
|
$ttl->render; # renders "justthese" using 3 steps (not 5) |
391
|
|
|
|
|
|
|
|
392
|
|
|
|
|
|
|
=cut |
393
|
|
|
|
|
|
|
|
394
|
|
|
|
|
|
|
sub execute_each { |
395
|
4
|
|
|
4
|
1
|
52
|
my ($self, $list, $renderer) = @_; |
396
|
|
|
|
|
|
|
|
397
|
4
|
|
|
|
|
17
|
return map($self->execute_sequence($_, $renderer), @$list); |
398
|
|
|
|
|
|
|
} |
399
|
|
|
|
|
|
|
|
400
|
|
|
|
|
|
|
=head2 execute_step($code, $renderer) |
401
|
|
|
|
|
|
|
|
402
|
|
|
|
|
|
|
Execute one code step $code with renderer $renderer unless the total_steps |
403
|
|
|
|
|
|
|
limit has been reached, in which case the total_steps limit is marked |
404
|
|
|
|
|
|
|
exceeded. |
405
|
|
|
|
|
|
|
|
406
|
|
|
|
|
|
|
=cut |
407
|
|
|
|
|
|
|
|
408
|
|
|
|
|
|
|
sub execute_step { |
409
|
45
|
|
|
45
|
1
|
60
|
my $self = shift; |
410
|
45
|
|
|
|
|
62
|
my ($code, $renderer) = @_; |
411
|
|
|
|
|
|
|
|
412
|
|
|
|
|
|
|
# This is a hack in case someone wants to sub-class step execution |
413
|
45
|
100
|
|
|
|
108
|
return $renderer->step? $self->_execute_step(@_): (); |
414
|
|
|
|
|
|
|
} |
415
|
|
|
|
|
|
|
|
416
|
|
|
|
|
|
|
=head2 _execute_step($code, $renderer) |
417
|
|
|
|
|
|
|
|
418
|
|
|
|
|
|
|
This method does the "heavy lifting" after execute_step checks resource |
419
|
|
|
|
|
|
|
usage. |
420
|
|
|
|
|
|
|
|
421
|
|
|
|
|
|
|
The step $code can be one of the following: |
422
|
|
|
|
|
|
|
|
423
|
|
|
|
|
|
|
[ "''" => $literal ] |
424
|
|
|
|
|
|
|
[ '$' => $var_name ] |
425
|
|
|
|
|
|
|
[ '()' => $fn_or_tpl [ \@a1codeseq, \@a2codeseq, ... ] ] |
426
|
|
|
|
|
|
|
|
427
|
|
|
|
|
|
|
A variable substitution is executed as a nested template if it's value |
428
|
|
|
|
|
|
|
looks like this: |
429
|
|
|
|
|
|
|
|
430
|
|
|
|
|
|
|
[ '<>' => \@code_sequence ] |
431
|
|
|
|
|
|
|
|
432
|
|
|
|
|
|
|
=cut |
433
|
|
|
|
|
|
|
|
434
|
|
|
|
|
|
|
sub _execute_step { |
435
|
43
|
|
|
43
|
|
70
|
my ($self, $code, $renderer) = @_; |
436
|
43
|
|
|
|
|
61
|
my $type = $code->[0]; |
437
|
43
|
|
|
|
|
45
|
my $value; |
438
|
|
|
|
|
|
|
|
439
|
|
|
|
|
|
|
# Figure out what to do in this step... |
440
|
|
|
|
|
|
|
|
441
|
|
|
|
|
|
|
# [ "''" => $string ] : Return a literal. |
442
|
43
|
100
|
|
|
|
108
|
if ($type eq "''") { |
443
|
32
|
|
|
|
|
113
|
return $code->[1]; |
444
|
|
|
|
|
|
|
} |
445
|
|
|
|
|
|
|
|
446
|
|
|
|
|
|
|
# Note: The only currently supported array values are internal |
447
|
|
|
|
|
|
|
# templates. They look like this: [ '<>' => \@code_sequence ] |
448
|
|
|
|
|
|
|
# Other array values are ignored. |
449
|
|
|
|
|
|
|
|
450
|
|
|
|
|
|
|
# [ '$' => $name ] : Interpolate a variable (possibly an internal template). |
451
|
11
|
100
|
|
|
|
26
|
if ($type eq '$') { |
452
|
3
|
|
|
|
|
10
|
$value = $renderer->vars->{$code->[1]}; |
453
|
|
|
|
|
|
|
|
454
|
|
|
|
|
|
|
# Check for an internal template. |
455
|
3
|
0
|
0
|
|
|
9
|
return ((@$value && $value->[0] eq '<>')? |
|
|
50
|
|
|
|
|
|
456
|
|
|
|
|
|
|
$self->execute_template($value->[1], [], $renderer): '') |
457
|
|
|
|
|
|
|
if ref($value) eq 'ARRAY'; |
458
|
|
|
|
|
|
|
|
459
|
|
|
|
|
|
|
# Ordinary variable substitution. |
460
|
3
|
50
|
|
|
|
14
|
return defined($value)? $value: ''; |
461
|
|
|
|
|
|
|
} |
462
|
|
|
|
|
|
|
|
463
|
|
|
|
|
|
|
# [ '()' => $name, [ @arg_code_sequences ] ] : |
464
|
|
|
|
|
|
|
# Call a function or a template (possibly with parameters). |
465
|
8
|
50
|
|
|
|
22
|
if ($type eq '()') { |
466
|
8
|
|
|
|
|
15
|
my $name = $code->[1]; |
467
|
|
|
|
|
|
|
|
468
|
8
|
50
|
|
|
|
23
|
if ($name =~ /^\$([a-zA-Z0-9_\.]+)$/) { |
469
|
0
|
|
|
|
|
0
|
$value = $renderer->vars->{$1}; |
470
|
|
|
|
|
|
|
|
471
|
0
|
0
|
|
|
|
0
|
if (ref($value) eq 'ARRAY') { |
472
|
0
|
0
|
0
|
|
|
0
|
return ((@$value && $value->[0] eq '<>')? |
473
|
|
|
|
|
|
|
$self->execute_template($value->[1], $code->[2], $renderer): |
474
|
|
|
|
|
|
|
()); |
475
|
|
|
|
|
|
|
} |
476
|
|
|
|
|
|
|
|
477
|
|
|
|
|
|
|
# Ignore any call parameters and revert to plain variable |
478
|
|
|
|
|
|
|
# substitution. |
479
|
0
|
0
|
|
|
|
0
|
return defined($value)? $value: ''; |
480
|
|
|
|
|
|
|
} |
481
|
|
|
|
|
|
|
|
482
|
8
|
|
|
|
|
19
|
$value = $self->{defs}{$name}; |
483
|
|
|
|
|
|
|
|
484
|
|
|
|
|
|
|
# Call an external template's renderer if available. |
485
|
8
|
100
|
66
|
|
|
59
|
return $renderer->render_external($value, |
486
|
|
|
|
|
|
|
{ $self->execute_each($code->[2], $renderer) })->result |
487
|
|
|
|
|
|
|
if blessed($value) && $value->can('render'); |
488
|
|
|
|
|
|
|
|
489
|
|
|
|
|
|
|
# Call a registered function (or an undefined-call handler). |
490
|
4
|
100
|
|
|
|
14
|
unless (ref($value) eq 'CODE') { |
491
|
3
|
|
|
|
|
5
|
$value = $self->{defs}{''}; |
492
|
3
|
100
|
|
|
|
13
|
$value = \&undef_call unless ref($value) eq 'CODE'; |
493
|
|
|
|
|
|
|
} |
494
|
4
|
|
|
|
|
11
|
return &$value($name, $code->[2], $renderer); |
495
|
|
|
|
|
|
|
} |
496
|
|
|
|
|
|
|
|
497
|
0
|
|
|
|
|
0
|
croak "Unrecognized " . blessed($self) . " step-type: $type"; |
498
|
|
|
|
|
|
|
} |
499
|
|
|
|
|
|
|
|
500
|
|
|
|
|
|
|
=head2 execute($renderer) |
501
|
|
|
|
|
|
|
|
502
|
|
|
|
|
|
|
Execute the main template code with renderer $renderer and return the result. |
503
|
|
|
|
|
|
|
|
504
|
|
|
|
|
|
|
You shouldn't need to use this method unless you're building or sub-classing |
505
|
|
|
|
|
|
|
a renderer. |
506
|
|
|
|
|
|
|
|
507
|
|
|
|
|
|
|
=cut |
508
|
|
|
|
|
|
|
|
509
|
|
|
|
|
|
|
sub execute { |
510
|
29
|
|
|
29
|
1
|
36
|
my ($self, $renderer) = @_; |
511
|
|
|
|
|
|
|
|
512
|
29
|
|
|
|
|
87
|
return scalar($self->execute_sequence($self->{code}, $renderer)); |
513
|
|
|
|
|
|
|
} |
514
|
|
|
|
|
|
|
|
515
|
|
|
|
|
|
|
=head2 execute_template($code, $args, $renderer) |
516
|
|
|
|
|
|
|
|
517
|
|
|
|
|
|
|
This executes the code from a nested template after saving any |
518
|
|
|
|
|
|
|
previous numeric variables and then setting $0 and parameters $1 through |
519
|
|
|
|
|
|
|
$I. |
520
|
|
|
|
|
|
|
|
521
|
|
|
|
|
|
|
Any previous numeric variables are restored before returning. |
522
|
|
|
|
|
|
|
|
523
|
|
|
|
|
|
|
You shouldn't need this method except possibly if you're extending |
524
|
|
|
|
|
|
|
nested template functionality in some way. |
525
|
|
|
|
|
|
|
|
526
|
|
|
|
|
|
|
=cut |
527
|
|
|
|
|
|
|
|
528
|
|
|
|
|
|
|
sub execute_template { |
529
|
0
|
|
|
0
|
1
|
0
|
my ($self, $code, $args, $renderer) = @_; |
530
|
0
|
|
|
|
|
0
|
my (%save_vars, $vars, $result); |
531
|
|
|
|
|
|
|
|
532
|
|
|
|
|
|
|
# Save and remove any previously existing numbered parameters. |
533
|
0
|
|
|
|
|
0
|
$vars = $renderer->vars; |
534
|
0
|
|
|
|
|
0
|
$save_vars{$_} = delete($vars->{$_}) foreach (grep(/^\d+$/, keys(%$vars))); |
535
|
|
|
|
|
|
|
|
536
|
|
|
|
|
|
|
# Save arguments as numbered parameters $1..$n. |
537
|
|
|
|
|
|
|
# Set $0 to the number of arguments. |
538
|
0
|
|
|
|
|
0
|
$vars->{0} = @$args; |
539
|
0
|
|
|
|
|
0
|
for (my $i = 0; $i < @$args; ++$i) { |
540
|
0
|
|
|
|
|
0
|
$vars->{$i + 1} = $self->execute_sequence($args->[$i], $renderer); |
541
|
|
|
|
|
|
|
} |
542
|
|
|
|
|
|
|
|
543
|
0
|
|
|
|
|
0
|
$result = $self->execute_sequence($code, $renderer); |
544
|
|
|
|
|
|
|
|
545
|
|
|
|
|
|
|
# Remove current numbered parameters and restore anything we removed. |
546
|
0
|
|
|
|
|
0
|
delete($vars->{$_}) foreach grep(/^\d+$/, keys(%$vars)); |
547
|
0
|
|
|
|
|
0
|
@$vars{keys(%save_vars)} = values(%save_vars); |
548
|
|
|
|
|
|
|
|
549
|
0
|
|
|
|
|
0
|
return $result; |
550
|
|
|
|
|
|
|
} |
551
|
|
|
|
|
|
|
|
552
|
|
|
|
|
|
|
=head2 undef_call($name, $args, $renderer) |
553
|
|
|
|
|
|
|
|
554
|
|
|
|
|
|
|
This function is the default undefined-call handler called by the |
555
|
|
|
|
|
|
|
L<"_execute_step($code, $renderer)"> method if no zero-length name is |
556
|
|
|
|
|
|
|
currently registered. |
557
|
|
|
|
|
|
|
|
558
|
|
|
|
|
|
|
It increments the C count in the rendering information and |
559
|
|
|
|
|
|
|
returns no value. |
560
|
|
|
|
|
|
|
|
561
|
|
|
|
|
|
|
=cut |
562
|
|
|
|
|
|
|
|
563
|
|
|
|
|
|
|
sub undef_call { |
564
|
2
|
|
|
2
|
1
|
4
|
my ($name, $args, $renderer) = @_; |
565
|
|
|
|
|
|
|
|
566
|
2
|
|
|
|
|
9
|
++$renderer->info->{undef_calls}; |
567
|
2
|
|
|
|
|
10
|
return (); |
568
|
|
|
|
|
|
|
} |
569
|
|
|
|
|
|
|
|
570
|
|
|
|
|
|
|
=head1 PARSING METHODS |
571
|
|
|
|
|
|
|
|
572
|
|
|
|
|
|
|
These methods are used for parsing. If you extend these in a sub-class it's |
573
|
|
|
|
|
|
|
likely to get ugly pretty quickly. |
574
|
|
|
|
|
|
|
|
575
|
|
|
|
|
|
|
=head2 get_tokens($text) |
576
|
|
|
|
|
|
|
|
577
|
|
|
|
|
|
|
Split template code text into tokens and return them as a list. |
578
|
|
|
|
|
|
|
|
579
|
|
|
|
|
|
|
=cut |
580
|
|
|
|
|
|
|
|
581
|
|
|
|
|
|
|
sub get_tokens { |
582
|
15
|
|
|
15
|
1
|
41
|
my ($self, $text) = @_; |
583
|
|
|
|
|
|
|
|
584
|
15
|
|
|
|
|
705
|
return grep(!/^\s*$/, split( |
585
|
|
|
|
|
|
|
/( |
586
|
|
|
|
|
|
|
\/\*.*?\*\/ # \/* comment *\/ |
587
|
|
|
|
|
|
|
| |
588
|
|
|
|
|
|
|
'(?:\\'|[^'])*' # 'string' |
589
|
|
|
|
|
|
|
| |
590
|
|
|
|
|
|
|
"(?:\\"|[^"])*" # "string" |
591
|
|
|
|
|
|
|
| |
592
|
|
|
|
|
|
|
\$[a-zA-Z0-9_][a-zA-Z0-9_\.]* # $vari.able |
593
|
|
|
|
|
|
|
| |
594
|
|
|
|
|
|
|
[a-zA-Z_][a-zA-Z0-9_]* # alpha-numeric function |
595
|
|
|
|
|
|
|
| |
596
|
|
|
|
|
|
|
-?\d+(?:\.\d*)? # integer or floating numeric literal |
597
|
|
|
|
|
|
|
| |
598
|
|
|
|
|
|
|
[(),] # (parameter, lists) |
599
|
|
|
|
|
|
|
| |
600
|
|
|
|
|
|
|
\s+ |
601
|
|
|
|
|
|
|
)/x, |
602
|
|
|
|
|
|
|
$text)); |
603
|
|
|
|
|
|
|
} |
604
|
|
|
|
|
|
|
|
605
|
|
|
|
|
|
|
=head2 parse_list(\@tokens, \@stops) |
606
|
|
|
|
|
|
|
|
607
|
|
|
|
|
|
|
Parse a block of code from the token list up to one of the stop |
608
|
|
|
|
|
|
|
symbols. This might be an entire code segment or parts of a call's |
609
|
|
|
|
|
|
|
parameter list. The code tree is returned. |
610
|
|
|
|
|
|
|
|
611
|
|
|
|
|
|
|
=cut |
612
|
|
|
|
|
|
|
|
613
|
|
|
|
|
|
|
sub parse_list { |
614
|
16
|
|
|
16
|
1
|
24
|
my ($self, $tokens, $stops) = @_; |
615
|
16
|
|
|
|
|
20
|
my (@code, $token); |
616
|
|
|
|
|
|
|
|
617
|
16
|
|
|
|
|
43
|
while (@$tokens) { |
618
|
27
|
|
|
|
|
36
|
$token = shift(@$tokens); |
619
|
|
|
|
|
|
|
|
620
|
|
|
|
|
|
|
# Remove comments |
621
|
27
|
100
|
|
|
|
75
|
next if $token =~ /^\/\*.*\*\/$/s; |
622
|
|
|
|
|
|
|
|
623
|
|
|
|
|
|
|
# String literals |
624
|
25
|
100
|
100
|
|
|
148
|
if ($token =~ /^'(.*)'$/s || $token =~ /^"(.*)"$/s) { |
625
|
17
|
|
|
|
|
43
|
push(@code, [ "''" => $self->unescape($1) ]); |
626
|
17
|
|
|
|
|
57
|
next; |
627
|
|
|
|
|
|
|
} |
628
|
|
|
|
|
|
|
|
629
|
|
|
|
|
|
|
# Numeric literals |
630
|
8
|
50
|
|
|
|
31
|
if ($token =~ /^-?\d+(?:\.\d*)?$/) { |
631
|
0
|
|
|
|
|
0
|
push(@code, [ "''" => $token ]); |
632
|
0
|
|
|
|
|
0
|
next; |
633
|
|
|
|
|
|
|
} |
634
|
|
|
|
|
|
|
|
635
|
|
|
|
|
|
|
# Variables or internal template calls |
636
|
8
|
100
|
|
|
|
25
|
if ($token =~ /^\$([a-zA-Z0-9_]+)$/) { |
637
|
3
|
50
|
66
|
|
|
18
|
if (@$tokens && $tokens->[0] eq '(') { |
638
|
0
|
|
|
|
|
0
|
push(@code, $self->parse_call($token, $tokens)); |
639
|
|
|
|
|
|
|
} else { |
640
|
3
|
|
|
|
|
10
|
push(@code, [ '$' => $1 ]); |
641
|
|
|
|
|
|
|
} |
642
|
3
|
|
|
|
|
9
|
next; |
643
|
|
|
|
|
|
|
} |
644
|
|
|
|
|
|
|
|
645
|
|
|
|
|
|
|
# Check stop list |
646
|
5
|
|
|
|
|
14
|
foreach (@$stops) { |
647
|
3
|
100
|
|
|
|
9
|
if ($token eq $_) { |
648
|
2
|
|
|
|
|
4
|
unshift(@$tokens, $token); |
649
|
2
|
|
|
|
|
9
|
return @code; |
650
|
|
|
|
|
|
|
} |
651
|
|
|
|
|
|
|
} |
652
|
|
|
|
|
|
|
|
653
|
|
|
|
|
|
|
# Function or external template call, with or without parameters |
654
|
3
|
|
|
|
|
9
|
push(@code, $self->parse_call($token, $tokens)); |
655
|
|
|
|
|
|
|
} |
656
|
|
|
|
|
|
|
|
657
|
14
|
|
|
|
|
84
|
return @code; |
658
|
|
|
|
|
|
|
} |
659
|
|
|
|
|
|
|
|
660
|
|
|
|
|
|
|
=head2 parse_call($name, $tokens) |
661
|
|
|
|
|
|
|
|
662
|
|
|
|
|
|
|
Parse a parameter list if one follows in the token stream and return the |
663
|
|
|
|
|
|
|
code tree for a call to the function or template in $name. |
664
|
|
|
|
|
|
|
|
665
|
|
|
|
|
|
|
=cut |
666
|
|
|
|
|
|
|
|
667
|
|
|
|
|
|
|
sub parse_call { |
668
|
3
|
|
|
3
|
1
|
6
|
my ($self, $name, $tokens) = @_; |
669
|
3
|
|
|
|
|
5
|
my (@args, $token); |
670
|
|
|
|
|
|
|
|
671
|
3
|
100
|
100
|
|
|
19
|
if (@$tokens && $tokens->[0] eq '(') { |
672
|
1
|
|
|
|
|
2
|
shift(@$tokens); |
673
|
1
|
|
|
|
|
7
|
while (@$tokens) { |
674
|
4
|
|
|
|
|
7
|
$token = $tokens->[0]; |
675
|
4
|
100
|
100
|
|
|
21
|
shift(@$tokens) if $token eq ',' || $token eq ')'; |
676
|
4
|
100
|
|
|
|
11
|
last if $token eq ')'; |
677
|
|
|
|
|
|
|
|
678
|
3
|
100
|
|
|
|
11
|
if ($token ne ',') { |
679
|
|
|
|
|
|
|
# The argument continues to the next ',' or ')'. |
680
|
2
|
|
|
|
|
10
|
my @code = $self->parse_list($tokens, [',', ')']); |
681
|
2
|
50
|
|
|
|
11
|
push(@args, \@code) if @code; |
682
|
|
|
|
|
|
|
} |
683
|
|
|
|
|
|
|
} |
684
|
|
|
|
|
|
|
} |
685
|
|
|
|
|
|
|
|
686
|
|
|
|
|
|
|
# [ '()' => $name, [ \@arg0_code_seq, \@arg1_code_seq, ... ] ] |
687
|
3
|
|
|
|
|
16
|
return [ '()' => $name, \@args ]; |
688
|
|
|
|
|
|
|
} |
689
|
|
|
|
|
|
|
|
690
|
|
|
|
|
|
|
=head2 unescape($string) |
691
|
|
|
|
|
|
|
|
692
|
|
|
|
|
|
|
Un-escape backslashed characters for string literals. |
693
|
|
|
|
|
|
|
|
694
|
|
|
|
|
|
|
=cut |
695
|
|
|
|
|
|
|
|
696
|
|
|
|
|
|
|
sub unescape { |
697
|
17
|
|
|
17
|
1
|
34
|
my ($self, $string) = @_; |
698
|
|
|
|
|
|
|
|
699
|
17
|
|
|
|
|
29
|
$string =~ s/\\(.)/$1/g; |
700
|
17
|
|
|
|
|
50
|
return $string; |
701
|
|
|
|
|
|
|
} |
702
|
|
|
|
|
|
|
|
703
|
|
|
|
|
|
|
=head1 AUTHOR |
704
|
|
|
|
|
|
|
|
705
|
|
|
|
|
|
|
Brian Katzung, C<< >> |
706
|
|
|
|
|
|
|
|
707
|
|
|
|
|
|
|
=head1 BUGS |
708
|
|
|
|
|
|
|
|
709
|
|
|
|
|
|
|
Please report any bugs or feature requests to |
710
|
|
|
|
|
|
|
C, or through the web interface at |
711
|
|
|
|
|
|
|
L. I |
712
|
|
|
|
|
|
|
will be notified, and then you'll automatically be notified of progress |
713
|
|
|
|
|
|
|
on your bug as I make changes. |
714
|
|
|
|
|
|
|
|
715
|
|
|
|
|
|
|
=head1 SUPPORT |
716
|
|
|
|
|
|
|
|
717
|
|
|
|
|
|
|
You can find documentation for this module with the perldoc command. |
718
|
|
|
|
|
|
|
|
719
|
|
|
|
|
|
|
perldoc Text::TemplateLite |
720
|
|
|
|
|
|
|
|
721
|
|
|
|
|
|
|
You can also look for information at: |
722
|
|
|
|
|
|
|
|
723
|
|
|
|
|
|
|
=over 4 |
724
|
|
|
|
|
|
|
|
725
|
|
|
|
|
|
|
=item * RT: CPAN's request tracker (report bugs here) |
726
|
|
|
|
|
|
|
|
727
|
|
|
|
|
|
|
L |
728
|
|
|
|
|
|
|
|
729
|
|
|
|
|
|
|
=item * AnnoCPAN: Annotated CPAN documentation |
730
|
|
|
|
|
|
|
|
731
|
|
|
|
|
|
|
L |
732
|
|
|
|
|
|
|
|
733
|
|
|
|
|
|
|
=item * CPAN Ratings |
734
|
|
|
|
|
|
|
|
735
|
|
|
|
|
|
|
L |
736
|
|
|
|
|
|
|
|
737
|
|
|
|
|
|
|
=item * Search CPAN |
738
|
|
|
|
|
|
|
|
739
|
|
|
|
|
|
|
L |
740
|
|
|
|
|
|
|
|
741
|
|
|
|
|
|
|
=back |
742
|
|
|
|
|
|
|
|
743
|
|
|
|
|
|
|
=head1 SEE ALSO |
744
|
|
|
|
|
|
|
|
745
|
|
|
|
|
|
|
L (the companion class to |
746
|
|
|
|
|
|
|
Text::TemplateLite for rendering management) and |
747
|
|
|
|
|
|
|
L (for standard library functions, |
748
|
|
|
|
|
|
|
with examples) |
749
|
|
|
|
|
|
|
|
750
|
|
|
|
|
|
|
L ("powerful, high-performance templating for web and beyond") |
751
|
|
|
|
|
|
|
|
752
|
|
|
|
|
|
|
L (an alternative template system based on embedding |
753
|
|
|
|
|
|
|
Perl code in templates) |
754
|
|
|
|
|
|
|
|
755
|
|
|
|
|
|
|
L (an alternative template system [based on "including |
756
|
|
|
|
|
|
|
the kitchen sink"]) |
757
|
|
|
|
|
|
|
|
758
|
|
|
|
|
|
|
L for a |
759
|
|
|
|
|
|
|
comparison of template modules |
760
|
|
|
|
|
|
|
|
761
|
|
|
|
|
|
|
=head2 EVEN MORE TEMPLATE MODULES |
762
|
|
|
|
|
|
|
|
763
|
|
|
|
|
|
|
L, |
764
|
|
|
|
|
|
|
L, |
765
|
|
|
|
|
|
|
L, |
766
|
|
|
|
|
|
|
L, |
767
|
|
|
|
|
|
|
L, |
768
|
|
|
|
|
|
|
L, |
769
|
|
|
|
|
|
|
L, |
770
|
|
|
|
|
|
|
L, |
771
|
|
|
|
|
|
|
L, |
772
|
|
|
|
|
|
|
L, |
773
|
|
|
|
|
|
|
L, |
774
|
|
|
|
|
|
|
L, |
775
|
|
|
|
|
|
|
L, |
776
|
|
|
|
|
|
|
L, |
777
|
|
|
|
|
|
|
L, |
778
|
|
|
|
|
|
|
L, |
779
|
|
|
|
|
|
|
L, |
780
|
|
|
|
|
|
|
L, |
781
|
|
|
|
|
|
|
L, |
782
|
|
|
|
|
|
|
L, |
783
|
|
|
|
|
|
|
L, |
784
|
|
|
|
|
|
|
L, |
785
|
|
|
|
|
|
|
L, |
786
|
|
|
|
|
|
|
L, |
787
|
|
|
|
|
|
|
L, |
788
|
|
|
|
|
|
|
L, |
789
|
|
|
|
|
|
|
L, |
790
|
|
|
|
|
|
|
L, |
791
|
|
|
|
|
|
|
L |
792
|
|
|
|
|
|
|
L, |
793
|
|
|
|
|
|
|
L, |
794
|
|
|
|
|
|
|
L |
795
|
|
|
|
|
|
|
|
796
|
|
|
|
|
|
|
... and probably some I missed. |
797
|
|
|
|
|
|
|
|
798
|
|
|
|
|
|
|
=head1 LICENSE AND COPYRIGHT |
799
|
|
|
|
|
|
|
|
800
|
|
|
|
|
|
|
Copyright 2012 Brian Katzung. |
801
|
|
|
|
|
|
|
|
802
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify it |
803
|
|
|
|
|
|
|
under the terms of either: the GNU General Public License as published |
804
|
|
|
|
|
|
|
by the Free Software Foundation; or the Artistic License. |
805
|
|
|
|
|
|
|
|
806
|
|
|
|
|
|
|
See http://dev.perl.org/licenses/ for more information. |
807
|
|
|
|
|
|
|
|
808
|
|
|
|
|
|
|
=cut |
809
|
|
|
|
|
|
|
|
810
|
|
|
|
|
|
|
1; # End of Text::TemplateLite |
811
|
|
|
|
|
|
|
|