line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Jemplate::Directive; |
2
|
22
|
|
|
22
|
|
318
|
use strict; |
|
22
|
|
|
|
|
53
|
|
|
22
|
|
|
|
|
1122
|
|
3
|
22
|
|
|
22
|
|
140
|
use warnings; |
|
22
|
|
|
|
|
50
|
|
|
22
|
|
|
|
|
78411
|
|
4
|
|
|
|
|
|
|
|
5
|
|
|
|
|
|
|
our $OUTPUT = 'output +='; |
6
|
|
|
|
|
|
|
our $WHILE_MAX = 1000; |
7
|
|
|
|
|
|
|
|
8
|
|
|
|
|
|
|
# parser state variable |
9
|
|
|
|
|
|
|
# only true when inside JAVASCRIPT blocks |
10
|
|
|
|
|
|
|
our $INJAVASCRIPT = 0; |
11
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
sub new { |
13
|
38
|
|
|
38
|
0
|
3034
|
my $class = shift; |
14
|
|
|
|
|
|
|
|
15
|
38
|
|
|
|
|
297
|
return bless {}, $class |
16
|
|
|
|
|
|
|
} |
17
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
sub template { |
19
|
17
|
|
|
17
|
0
|
540
|
my ($class, $block) = @_; |
20
|
|
|
|
|
|
|
|
21
|
17
|
100
|
|
|
|
142
|
return "function() { return ''; }" unless $block =~ /\S/; |
22
|
|
|
|
|
|
|
|
23
|
16
|
|
|
|
|
196
|
return <<"..."; |
24
|
|
|
|
|
|
|
function(context) { |
25
|
|
|
|
|
|
|
if (! context) throw('Jemplate function called without context\\n'); |
26
|
|
|
|
|
|
|
var stash = context.stash; |
27
|
|
|
|
|
|
|
var output = ''; |
28
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
try { |
30
|
|
|
|
|
|
|
$block |
31
|
|
|
|
|
|
|
} |
32
|
|
|
|
|
|
|
catch(e) { |
33
|
|
|
|
|
|
|
var error = context.set_error(e, output); |
34
|
|
|
|
|
|
|
throw(error); |
35
|
|
|
|
|
|
|
} |
36
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
return output; |
38
|
|
|
|
|
|
|
} |
39
|
|
|
|
|
|
|
... |
40
|
|
|
|
|
|
|
} |
41
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
# Try to do 1 .. 10 expansions |
43
|
|
|
|
|
|
|
sub _attempt_range_expand_val ($) { |
44
|
11
|
|
|
11
|
|
23
|
my $val = shift; |
45
|
11
|
50
|
|
|
|
75
|
return $val unless |
46
|
|
|
|
|
|
|
my ( $from, $to ) = $val =~ m/\s*\[\s*(\S+)\s*\.\.\s*(\S+)\s*\]/; |
47
|
|
|
|
|
|
|
|
48
|
0
|
0
|
0
|
|
|
0
|
die "Range expansion is current supported for positive/negative integer values only (e.g. [ 1 .. 10 ])\nCannot expand: $val" unless $from =~ m/^-?\d+$/ && $to =~ m/^-?\d+$/; |
49
|
|
|
|
|
|
|
|
50
|
0
|
|
|
|
|
0
|
return join '', '[', join( ',', $from .. $to ), ']'; |
51
|
|
|
|
|
|
|
} |
52
|
|
|
|
|
|
|
|
53
|
|
|
|
|
|
|
#------------------------------------------------------------------------ |
54
|
|
|
|
|
|
|
# textblock($text) |
55
|
|
|
|
|
|
|
#------------------------------------------------------------------------ |
56
|
|
|
|
|
|
|
|
57
|
|
|
|
|
|
|
sub textblock { |
58
|
71
|
|
|
71
|
0
|
11265
|
my ($class, $text) = @_; |
59
|
71
|
100
|
|
|
|
222
|
return $text if $INJAVASCRIPT; |
60
|
69
|
|
|
|
|
257
|
return "$OUTPUT " . $class->text($text) . ';'; |
61
|
|
|
|
|
|
|
} |
62
|
|
|
|
|
|
|
|
63
|
|
|
|
|
|
|
#------------------------------------------------------------------------ |
64
|
|
|
|
|
|
|
# text($text) |
65
|
|
|
|
|
|
|
#------------------------------------------------------------------------ |
66
|
|
|
|
|
|
|
|
67
|
|
|
|
|
|
|
sub text { |
68
|
70
|
|
|
70
|
0
|
270
|
my ($class, $text) = @_; |
69
|
70
|
|
|
|
|
166
|
for ($text) { |
70
|
70
|
|
|
|
|
168
|
s/([\'\\])/\\$1/g; |
71
|
70
|
|
|
|
|
322
|
s/\n/\\n/g; |
72
|
70
|
|
|
|
|
212
|
s/\r/\\r/g; |
73
|
|
|
|
|
|
|
} |
74
|
70
|
|
|
|
|
364
|
return "'" . $text . "'"; |
75
|
|
|
|
|
|
|
} |
76
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
#------------------------------------------------------------------------ |
78
|
|
|
|
|
|
|
# ident(\@ident) foo.bar(baz) |
79
|
|
|
|
|
|
|
#------------------------------------------------------------------------ |
80
|
|
|
|
|
|
|
|
81
|
|
|
|
|
|
|
sub ident { |
82
|
45
|
|
|
45
|
0
|
16025
|
my ($class, $ident) = @_; |
83
|
45
|
50
|
|
|
|
197
|
return "''" unless @$ident; |
84
|
45
|
|
|
|
|
69
|
my $ns; |
85
|
|
|
|
|
|
|
|
86
|
|
|
|
|
|
|
# does the first element of the identifier have a NAMESPACE |
87
|
|
|
|
|
|
|
# handler defined? |
88
|
45
|
50
|
66
|
|
|
404
|
if (ref $class && @$ident > 2 && ($ns = $class->{ NAMESPACE })) { |
|
|
|
66
|
|
|
|
|
89
|
0
|
|
|
|
|
0
|
my $key = $ident->[0]; |
90
|
0
|
|
|
|
|
0
|
$key =~ s/^'(.+)'$/$1/s; |
91
|
0
|
0
|
|
|
|
0
|
if ($ns = $ns->{ $key }) { |
92
|
0
|
|
|
|
|
0
|
return $ns->ident($ident); |
93
|
|
|
|
|
|
|
} |
94
|
|
|
|
|
|
|
} |
95
|
|
|
|
|
|
|
|
96
|
45
|
100
|
100
|
|
|
298
|
if (scalar @$ident <= 2 && ! $ident->[1]) { |
97
|
31
|
|
|
|
|
84
|
$ident = $ident->[0]; |
98
|
|
|
|
|
|
|
} |
99
|
|
|
|
|
|
|
else { |
100
|
14
|
|
|
|
|
78
|
$ident = '[' . join(', ', @$ident) . ']'; |
101
|
|
|
|
|
|
|
} |
102
|
45
|
|
|
|
|
202
|
return "stash.get($ident)"; |
103
|
|
|
|
|
|
|
} |
104
|
|
|
|
|
|
|
|
105
|
|
|
|
|
|
|
|
106
|
|
|
|
|
|
|
#------------------------------------------------------------------------ |
107
|
|
|
|
|
|
|
# assign(\@ident, $value, $default) foo = bar |
108
|
|
|
|
|
|
|
#------------------------------------------------------------------------ |
109
|
|
|
|
|
|
|
|
110
|
|
|
|
|
|
|
sub assign { |
111
|
10
|
|
|
10
|
0
|
51
|
my ($class, $var, $val, $default) = @_; |
112
|
|
|
|
|
|
|
|
113
|
10
|
50
|
|
|
|
40
|
if (ref $var) { |
114
|
10
|
100
|
66
|
|
|
74
|
if (scalar @$var == 2 && ! $var->[1]) { |
115
|
8
|
|
|
|
|
31
|
$var = $var->[0]; |
116
|
|
|
|
|
|
|
} |
117
|
|
|
|
|
|
|
else { |
118
|
2
|
|
|
|
|
10
|
$var = '[' . join(', ', @$var) . ']'; |
119
|
|
|
|
|
|
|
} |
120
|
|
|
|
|
|
|
} |
121
|
10
|
|
|
|
|
40
|
$val = _attempt_range_expand_val $val; |
122
|
10
|
50
|
|
|
|
40
|
$val .= ', 1' if $default; |
123
|
10
|
|
|
|
|
95
|
return "stash.set($var, $val)"; |
124
|
|
|
|
|
|
|
} |
125
|
|
|
|
|
|
|
|
126
|
|
|
|
|
|
|
|
127
|
|
|
|
|
|
|
#------------------------------------------------------------------------ |
128
|
|
|
|
|
|
|
# args(\@args) foo, bar, baz = qux |
129
|
|
|
|
|
|
|
#------------------------------------------------------------------------ |
130
|
|
|
|
|
|
|
|
131
|
|
|
|
|
|
|
sub args { |
132
|
7
|
|
|
7
|
0
|
3933
|
my ($class, $args) = @_; |
133
|
7
|
|
|
|
|
16
|
my $hash = shift @$args; |
134
|
7
|
50
|
|
|
|
22
|
push(@$args, '{ ' . join(', ', @$hash) . ' }') |
135
|
|
|
|
|
|
|
if @$hash; |
136
|
|
|
|
|
|
|
|
137
|
7
|
100
|
|
|
|
23
|
return '[]' unless @$args; |
138
|
6
|
|
|
|
|
39
|
return '[ ' . join(', ', @$args) . ' ]'; |
139
|
|
|
|
|
|
|
} |
140
|
|
|
|
|
|
|
|
141
|
|
|
|
|
|
|
|
142
|
|
|
|
|
|
|
#------------------------------------------------------------------------ |
143
|
|
|
|
|
|
|
# filenames(\@names) |
144
|
|
|
|
|
|
|
#------------------------------------------------------------------------ |
145
|
|
|
|
|
|
|
|
146
|
|
|
|
|
|
|
sub filenames { |
147
|
4
|
|
|
4
|
0
|
8
|
my ($class, $names) = @_; |
148
|
4
|
50
|
|
|
|
32
|
if (@$names > 1) { |
149
|
0
|
|
|
|
|
0
|
$names = '[ ' . join(', ', @$names) . ' ]'; |
150
|
|
|
|
|
|
|
} |
151
|
|
|
|
|
|
|
else { |
152
|
4
|
|
|
|
|
8
|
$names = shift @$names; |
153
|
|
|
|
|
|
|
} |
154
|
4
|
|
|
|
|
11
|
return $names; |
155
|
|
|
|
|
|
|
} |
156
|
|
|
|
|
|
|
|
157
|
|
|
|
|
|
|
|
158
|
|
|
|
|
|
|
#------------------------------------------------------------------------ |
159
|
|
|
|
|
|
|
# get($expr) [% foo %] |
160
|
|
|
|
|
|
|
#------------------------------------------------------------------------ |
161
|
|
|
|
|
|
|
|
162
|
|
|
|
|
|
|
sub get { |
163
|
21
|
|
|
21
|
0
|
2356
|
my ($class, $expr) = @_; |
164
|
21
|
|
|
|
|
106
|
return "$OUTPUT $expr;"; |
165
|
|
|
|
|
|
|
} |
166
|
|
|
|
|
|
|
|
167
|
|
|
|
|
|
|
sub block { |
168
|
60
|
|
|
60
|
0
|
8760
|
my ($class, $block) = @_; |
169
|
138
|
|
|
|
|
485
|
return join "\n", map { |
170
|
60
|
100
|
|
|
|
215
|
s/^#(?=line \d+)/\/\//gm; |
171
|
138
|
|
|
|
|
468
|
$_; |
172
|
60
|
|
|
|
|
101
|
} @{ $block || [] }; |
173
|
|
|
|
|
|
|
} |
174
|
|
|
|
|
|
|
|
175
|
|
|
|
|
|
|
#------------------------------------------------------------------------ |
176
|
|
|
|
|
|
|
# call($expr) [% CALL bar %] |
177
|
|
|
|
|
|
|
#------------------------------------------------------------------------ |
178
|
|
|
|
|
|
|
|
179
|
|
|
|
|
|
|
sub call { |
180
|
8
|
|
|
8
|
0
|
768
|
my ($class, $expr) = @_; |
181
|
8
|
|
|
|
|
21
|
$expr .= ';'; |
182
|
8
|
|
|
|
|
24
|
return $expr; |
183
|
|
|
|
|
|
|
} |
184
|
|
|
|
|
|
|
|
185
|
|
|
|
|
|
|
|
186
|
|
|
|
|
|
|
#------------------------------------------------------------------------ |
187
|
|
|
|
|
|
|
# set(\@setlist) [% foo = bar, baz = qux %] |
188
|
|
|
|
|
|
|
#------------------------------------------------------------------------ |
189
|
|
|
|
|
|
|
|
190
|
|
|
|
|
|
|
sub set { |
191
|
10
|
|
|
10
|
0
|
3848
|
my ($class, $setlist) = @_; |
192
|
10
|
|
|
|
|
18
|
my $output; |
193
|
10
|
|
|
|
|
52
|
while (my ($var, $val) = splice(@$setlist, 0, 2)) { |
194
|
10
|
|
|
|
|
46
|
$output .= $class->assign($var, $val) . ";\n"; |
195
|
|
|
|
|
|
|
} |
196
|
10
|
|
|
|
|
32
|
chomp $output; |
197
|
10
|
|
|
|
|
39
|
return $output; |
198
|
|
|
|
|
|
|
} |
199
|
|
|
|
|
|
|
|
200
|
|
|
|
|
|
|
|
201
|
|
|
|
|
|
|
#------------------------------------------------------------------------ |
202
|
|
|
|
|
|
|
# default(\@setlist) [% DEFAULT foo = bar, baz = qux %] |
203
|
|
|
|
|
|
|
#------------------------------------------------------------------------ |
204
|
|
|
|
|
|
|
|
205
|
|
|
|
|
|
|
sub default { |
206
|
0
|
|
|
0
|
0
|
0
|
my ($class, $setlist) = @_; |
207
|
0
|
|
|
|
|
0
|
my $output; |
208
|
0
|
|
|
|
|
0
|
while (my ($var, $val) = splice(@$setlist, 0, 2)) { |
209
|
0
|
|
|
|
|
0
|
$output .= &assign($class, $var, $val, 1) . ";\n"; |
210
|
|
|
|
|
|
|
} |
211
|
0
|
|
|
|
|
0
|
chomp $output; |
212
|
0
|
|
|
|
|
0
|
return $output; |
213
|
|
|
|
|
|
|
} |
214
|
|
|
|
|
|
|
|
215
|
|
|
|
|
|
|
|
216
|
|
|
|
|
|
|
#------------------------------------------------------------------------ |
217
|
|
|
|
|
|
|
# include(\@nameargs) [% INCLUDE template foo = bar %] |
218
|
|
|
|
|
|
|
# # => [ [ $file, ... ], \@args ] |
219
|
|
|
|
|
|
|
#------------------------------------------------------------------------ |
220
|
|
|
|
|
|
|
|
221
|
|
|
|
|
|
|
sub include { |
222
|
1
|
|
|
1
|
0
|
266
|
my ($class, $nameargs) = @_; |
223
|
1
|
|
|
|
|
3
|
my ($file, $args) = @$nameargs; |
224
|
1
|
|
|
|
|
3
|
my $hash = shift @$args; |
225
|
1
|
|
|
|
|
4
|
$file = $class->filenames($file); |
226
|
1
|
50
|
|
|
|
6
|
$file .= @$hash ? ', { ' . join(', ', @$hash) . ' }' : ''; |
227
|
1
|
|
|
|
|
6
|
return "$OUTPUT context.include($file);"; |
228
|
|
|
|
|
|
|
} |
229
|
|
|
|
|
|
|
|
230
|
|
|
|
|
|
|
|
231
|
|
|
|
|
|
|
#------------------------------------------------------------------------ |
232
|
|
|
|
|
|
|
# process(\@nameargs) [% PROCESS template foo = bar %] |
233
|
|
|
|
|
|
|
# # => [ [ $file, ... ], \@args ] |
234
|
|
|
|
|
|
|
#------------------------------------------------------------------------ |
235
|
|
|
|
|
|
|
|
236
|
|
|
|
|
|
|
sub process { |
237
|
3
|
|
|
3
|
0
|
1807
|
my ($class, $nameargs) = @_; |
238
|
3
|
|
|
|
|
9
|
my ($file, $args) = @$nameargs; |
239
|
3
|
|
|
|
|
7
|
my $hash = shift @$args; |
240
|
3
|
|
|
|
|
18
|
$file = $class->filenames($file); |
241
|
3
|
100
|
|
|
|
26
|
$file .= @$hash ? ', { ' . join(', ', @$hash) . ' }' : ''; |
242
|
3
|
|
|
|
|
18
|
return "$OUTPUT context.process($file);"; |
243
|
|
|
|
|
|
|
} |
244
|
|
|
|
|
|
|
|
245
|
|
|
|
|
|
|
|
246
|
|
|
|
|
|
|
#------------------------------------------------------------------------ |
247
|
|
|
|
|
|
|
# if($expr, $block, $else) [% IF foo < bar %] |
248
|
|
|
|
|
|
|
# ... |
249
|
|
|
|
|
|
|
# [% ELSE %] |
250
|
|
|
|
|
|
|
# ... |
251
|
|
|
|
|
|
|
# [% END %] |
252
|
|
|
|
|
|
|
#------------------------------------------------------------------------ |
253
|
|
|
|
|
|
|
|
254
|
|
|
|
|
|
|
sub if { |
255
|
7
|
|
|
7
|
0
|
560
|
my ($class, $expr, $block, $else) = @_; |
256
|
7
|
100
|
|
|
|
27
|
my @else = $else ? @$else : (); |
257
|
7
|
|
|
|
|
11
|
$else = pop @else; |
258
|
|
|
|
|
|
|
|
259
|
7
|
|
|
|
|
26
|
my $output = "if ($expr) {\n$block\n}\n"; |
260
|
|
|
|
|
|
|
|
261
|
7
|
|
|
|
|
19
|
foreach my $elsif (@else) { |
262
|
0
|
|
|
|
|
0
|
($expr, $block) = @$elsif; |
263
|
0
|
|
|
|
|
0
|
$output .= "else if ($expr) {\n$block\n}\n"; |
264
|
|
|
|
|
|
|
} |
265
|
7
|
100
|
|
|
|
19
|
if (defined $else) { |
266
|
2
|
|
|
|
|
5
|
$output .= "else {\n$else\n}\n"; |
267
|
|
|
|
|
|
|
} |
268
|
|
|
|
|
|
|
|
269
|
7
|
|
|
|
|
37
|
return $output; |
270
|
|
|
|
|
|
|
} |
271
|
|
|
|
|
|
|
|
272
|
|
|
|
|
|
|
#------------------------------------------------------------------------ |
273
|
|
|
|
|
|
|
# foreach($target, $list, $args, $block) [% FOREACH x = [ foo bar ] %] |
274
|
|
|
|
|
|
|
# ... |
275
|
|
|
|
|
|
|
# [% END %] |
276
|
|
|
|
|
|
|
#------------------------------------------------------------------------ |
277
|
|
|
|
|
|
|
|
278
|
|
|
|
|
|
|
sub foreach { |
279
|
1
|
|
|
1
|
0
|
59
|
my ($class, $target, $list, $args, $block) = @_; |
280
|
1
|
|
|
|
|
2
|
$args = shift @$args; |
281
|
1
|
50
|
|
|
|
5
|
$args = @$args ? ', { ' . join(', ', @$args) . ' }' : ''; |
282
|
|
|
|
|
|
|
|
283
|
1
|
|
|
|
|
2
|
my ($loop_save, $loop_set, $loop_restore, $setiter); |
284
|
1
|
50
|
|
|
|
2
|
if ($target) { |
285
|
1
|
|
|
|
|
6
|
$loop_save = |
286
|
|
|
|
|
|
|
'try { oldloop = ' . $class->ident(["'loop'"]) . ' } finally {}'; |
287
|
1
|
|
|
|
|
3
|
$loop_set = "stash.data['$target'] = value"; |
288
|
1
|
|
|
|
|
2
|
$loop_restore = "stash.set('loop', oldloop)"; |
289
|
|
|
|
|
|
|
} |
290
|
|
|
|
|
|
|
else { |
291
|
0
|
|
|
|
|
0
|
die "XXX - Not supported yet"; |
292
|
0
|
|
|
|
|
0
|
$loop_save = 'stash = context.localise()'; |
293
|
0
|
|
|
|
|
0
|
$loop_set = |
294
|
|
|
|
|
|
|
"stash.get(['import', [value]]) if typeof(value) == 'object'"; |
295
|
0
|
|
|
|
|
0
|
$loop_restore = 'stash = context.delocalise()'; |
296
|
|
|
|
|
|
|
} |
297
|
|
|
|
|
|
|
|
298
|
1
|
|
|
|
|
12
|
$list = _attempt_range_expand_val $list; |
299
|
|
|
|
|
|
|
|
300
|
1
|
|
|
|
|
7
|
return <
|
301
|
|
|
|
|
|
|
|
302
|
|
|
|
|
|
|
// FOREACH |
303
|
|
|
|
|
|
|
(function() { |
304
|
|
|
|
|
|
|
var list = $list; |
305
|
|
|
|
|
|
|
list = new Jemplate.Iterator(list); |
306
|
|
|
|
|
|
|
var retval = list.get_first(); |
307
|
|
|
|
|
|
|
var value = retval[0]; |
308
|
|
|
|
|
|
|
var done = retval[1]; |
309
|
|
|
|
|
|
|
var oldloop; |
310
|
|
|
|
|
|
|
$loop_save |
311
|
|
|
|
|
|
|
stash.set('loop', list); |
312
|
|
|
|
|
|
|
try { |
313
|
|
|
|
|
|
|
while (! done) { |
314
|
|
|
|
|
|
|
$loop_set; |
315
|
|
|
|
|
|
|
$block; |
316
|
|
|
|
|
|
|
retval = list.get_next(); |
317
|
|
|
|
|
|
|
value = retval[0]; |
318
|
|
|
|
|
|
|
done = retval[1]; |
319
|
|
|
|
|
|
|
} |
320
|
|
|
|
|
|
|
} |
321
|
|
|
|
|
|
|
catch(e) { |
322
|
|
|
|
|
|
|
throw(context.set_error(e, output)); |
323
|
|
|
|
|
|
|
} |
324
|
|
|
|
|
|
|
$loop_restore; |
325
|
|
|
|
|
|
|
})(); |
326
|
|
|
|
|
|
|
EOF |
327
|
|
|
|
|
|
|
} |
328
|
|
|
|
|
|
|
|
329
|
|
|
|
|
|
|
|
330
|
|
|
|
|
|
|
#------------------------------------------------------------------------ |
331
|
|
|
|
|
|
|
# next() [% NEXT %] |
332
|
|
|
|
|
|
|
# |
333
|
|
|
|
|
|
|
# Next iteration of a FOREACH loop (experimental) |
334
|
|
|
|
|
|
|
#------------------------------------------------------------------------ |
335
|
|
|
|
|
|
|
|
336
|
|
|
|
|
|
|
sub next { |
337
|
1
|
|
|
1
|
0
|
531
|
return <
|
338
|
|
|
|
|
|
|
retval = list.get_next(); |
339
|
|
|
|
|
|
|
value = retval[0]; |
340
|
|
|
|
|
|
|
done = retval[1]; |
341
|
|
|
|
|
|
|
continue; |
342
|
|
|
|
|
|
|
EOF |
343
|
|
|
|
|
|
|
} |
344
|
|
|
|
|
|
|
|
345
|
|
|
|
|
|
|
#------------------------------------------------------------------------ |
346
|
|
|
|
|
|
|
# wrapper(\@nameargs, $block) [% WRAPPER template foo = bar %] |
347
|
|
|
|
|
|
|
# # => [ [$file,...], \@args ] |
348
|
|
|
|
|
|
|
#------------------------------------------------------------------------ |
349
|
|
|
|
|
|
|
sub wrapper { |
350
|
4
|
|
|
4
|
0
|
178
|
my ($class, $nameargs, $block) = @_; |
351
|
4
|
|
|
|
|
9
|
my ($file, $args) = @$nameargs; |
352
|
4
|
|
|
|
|
6
|
my $hash = shift @$args; |
353
|
|
|
|
|
|
|
|
354
|
4
|
|
|
|
|
16
|
s/ => /: / for @$hash; |
355
|
4
|
100
|
|
|
|
14
|
return $class->multi_wrapper($file, $hash, $block) |
356
|
|
|
|
|
|
|
if @$file > 1; |
357
|
3
|
|
|
|
|
5
|
$file = shift @$file; |
358
|
3
|
|
|
|
|
7
|
push(@$hash, "'content': output"); |
359
|
3
|
50
|
|
|
|
17
|
$file .= @$hash ? ', { ' . join(', ', @$hash) . ' }' : ''; |
360
|
|
|
|
|
|
|
|
361
|
3
|
|
|
|
|
17
|
return <
|
362
|
|
|
|
|
|
|
|
363
|
|
|
|
|
|
|
// WRAPPER |
364
|
|
|
|
|
|
|
$OUTPUT (function() { |
365
|
|
|
|
|
|
|
var output = ''; |
366
|
|
|
|
|
|
|
$block; |
367
|
|
|
|
|
|
|
return context.include($file); |
368
|
|
|
|
|
|
|
})(); |
369
|
|
|
|
|
|
|
EOF |
370
|
|
|
|
|
|
|
} |
371
|
|
|
|
|
|
|
|
372
|
|
|
|
|
|
|
sub multi_wrapper { |
373
|
1
|
|
|
1
|
0
|
2
|
my ($class, $file, $hash, $block) = @_; |
374
|
|
|
|
|
|
|
|
375
|
1
|
|
|
|
|
3
|
push(@$hash, "'content': output"); |
376
|
1
|
50
|
|
|
|
6
|
$hash = @$hash ? ', { ' . join(', ', @$hash) . ' }' : ''; |
377
|
|
|
|
|
|
|
|
378
|
1
|
|
|
|
|
3
|
$file = join(', ', reverse @$file); |
379
|
|
|
|
|
|
|
# print STDERR "multi wrapper: $file\n"; |
380
|
|
|
|
|
|
|
|
381
|
1
|
|
|
|
|
10
|
return <
|
382
|
|
|
|
|
|
|
|
383
|
|
|
|
|
|
|
// WRAPPER |
384
|
|
|
|
|
|
|
$OUTPUT (function() { |
385
|
|
|
|
|
|
|
var output = ''; |
386
|
|
|
|
|
|
|
$block; |
387
|
|
|
|
|
|
|
var files = new Array($file); |
388
|
|
|
|
|
|
|
for (var i = 0; i < files.length; i++) { |
389
|
|
|
|
|
|
|
output = context.include(files[i]$hash); |
390
|
|
|
|
|
|
|
} |
391
|
|
|
|
|
|
|
return output; |
392
|
|
|
|
|
|
|
})(); |
393
|
|
|
|
|
|
|
EOF |
394
|
|
|
|
|
|
|
} |
395
|
|
|
|
|
|
|
|
396
|
|
|
|
|
|
|
|
397
|
|
|
|
|
|
|
#------------------------------------------------------------------------ |
398
|
|
|
|
|
|
|
# while($expr, $block) [% WHILE x < 10 %] |
399
|
|
|
|
|
|
|
# ... |
400
|
|
|
|
|
|
|
# [% END %] |
401
|
|
|
|
|
|
|
#------------------------------------------------------------------------ |
402
|
|
|
|
|
|
|
|
403
|
|
|
|
|
|
|
sub while { |
404
|
2
|
|
|
2
|
0
|
83
|
my ($class, $expr, $block) = @_; |
405
|
|
|
|
|
|
|
|
406
|
2
|
|
|
|
|
14
|
return <
|
407
|
|
|
|
|
|
|
|
408
|
|
|
|
|
|
|
// WHILE |
409
|
|
|
|
|
|
|
var failsafe = $WHILE_MAX; |
410
|
|
|
|
|
|
|
while (--failsafe && ($expr)) { |
411
|
|
|
|
|
|
|
$block |
412
|
|
|
|
|
|
|
} |
413
|
|
|
|
|
|
|
if (! failsafe) |
414
|
|
|
|
|
|
|
throw("WHILE loop terminated (> $WHILE_MAX iterations)\\n") |
415
|
|
|
|
|
|
|
EOF |
416
|
|
|
|
|
|
|
} |
417
|
|
|
|
|
|
|
|
418
|
|
|
|
|
|
|
#------------------------------------------------------------------------ |
419
|
|
|
|
|
|
|
# javascript($script) [% JAVASCRIPT %] |
420
|
|
|
|
|
|
|
# ... |
421
|
|
|
|
|
|
|
# [% END %] |
422
|
|
|
|
|
|
|
#------------------------------------------------------------------------ |
423
|
|
|
|
|
|
|
sub javascript { |
424
|
1
|
|
|
1
|
0
|
41
|
my ( $class, $javascript ) = @_; |
425
|
1
|
|
|
|
|
2
|
return $javascript; |
426
|
|
|
|
|
|
|
} |
427
|
|
|
|
|
|
|
|
428
|
|
|
|
|
|
|
sub no_javascript { |
429
|
1
|
|
|
1
|
0
|
54
|
my ( $class ) = @_; |
430
|
1
|
|
|
|
|
14
|
die "EVAL_JAVASCRIPT has not been enabled, cannot process [% JAVASCRIPT %] blocks"; |
431
|
|
|
|
|
|
|
} |
432
|
|
|
|
|
|
|
|
433
|
|
|
|
|
|
|
#------------------------------------------------------------------------ |
434
|
|
|
|
|
|
|
# switch($expr, \@case) [% SWITCH %] |
435
|
|
|
|
|
|
|
# [% CASE foo %] |
436
|
|
|
|
|
|
|
# ... |
437
|
|
|
|
|
|
|
# [% END %] |
438
|
|
|
|
|
|
|
#------------------------------------------------------------------------ |
439
|
|
|
|
|
|
|
|
440
|
|
|
|
|
|
|
sub switch { |
441
|
1
|
|
|
1
|
0
|
117
|
my ($class, $expr, $case) = @_; |
442
|
1
|
|
|
|
|
4
|
my @case = @$case; |
443
|
1
|
|
|
|
|
2
|
my ($match, $block, $default); |
444
|
1
|
|
|
|
|
2
|
my $caseblock = ''; |
445
|
|
|
|
|
|
|
|
446
|
1
|
|
|
|
|
2
|
$default = pop @case; |
447
|
|
|
|
|
|
|
|
448
|
1
|
|
|
|
|
2
|
foreach $case (@case) { |
449
|
1
|
|
|
|
|
3
|
$match = $case->[0]; |
450
|
1
|
|
|
|
|
2
|
$block = $case->[1]; |
451
|
|
|
|
|
|
|
# $block = pad($block, 1) if $PRETTY; |
452
|
1
|
|
|
|
|
5
|
$caseblock .= <
|
453
|
|
|
|
|
|
|
case $match: |
454
|
|
|
|
|
|
|
$block |
455
|
|
|
|
|
|
|
break; |
456
|
|
|
|
|
|
|
|
457
|
|
|
|
|
|
|
EOF |
458
|
|
|
|
|
|
|
} |
459
|
|
|
|
|
|
|
|
460
|
1
|
50
|
|
|
|
5
|
if (defined $default) { |
461
|
1
|
|
|
|
|
3
|
$caseblock .= <
|
462
|
|
|
|
|
|
|
default: |
463
|
|
|
|
|
|
|
$default |
464
|
|
|
|
|
|
|
break; |
465
|
|
|
|
|
|
|
EOF |
466
|
|
|
|
|
|
|
} |
467
|
|
|
|
|
|
|
# $caseblock = pad($caseblock, 2) if $PRETTY; |
468
|
|
|
|
|
|
|
|
469
|
1
|
|
|
|
|
7
|
return <
|
470
|
|
|
|
|
|
|
|
471
|
|
|
|
|
|
|
switch($expr) { |
472
|
|
|
|
|
|
|
$caseblock |
473
|
|
|
|
|
|
|
} |
474
|
|
|
|
|
|
|
|
475
|
|
|
|
|
|
|
EOF |
476
|
|
|
|
|
|
|
} |
477
|
|
|
|
|
|
|
|
478
|
|
|
|
|
|
|
|
479
|
|
|
|
|
|
|
#------------------------------------------------------------------------ |
480
|
|
|
|
|
|
|
# throw(\@nameargs) [% THROW foo "bar error" %] |
481
|
|
|
|
|
|
|
# # => [ [$type], \@args ] |
482
|
|
|
|
|
|
|
#------------------------------------------------------------------------ |
483
|
|
|
|
|
|
|
|
484
|
|
|
|
|
|
|
sub throw { |
485
|
1
|
|
|
1
|
0
|
419
|
my ($class, $nameargs) = @_; |
486
|
1
|
|
|
|
|
4
|
my ($type, $args) = @$nameargs; |
487
|
1
|
|
|
|
|
4
|
my $hash = shift(@$args); |
488
|
1
|
|
|
|
|
2
|
my $info = shift(@$args); |
489
|
1
|
|
|
|
|
2
|
$type = shift @$type; |
490
|
|
|
|
|
|
|
|
491
|
1
|
|
|
|
|
7
|
return qq{throw([$type, $info]);}; |
492
|
|
|
|
|
|
|
} |
493
|
|
|
|
|
|
|
|
494
|
|
|
|
|
|
|
|
495
|
|
|
|
|
|
|
#------------------------------------------------------------------------ |
496
|
|
|
|
|
|
|
# clear() [% CLEAR %] |
497
|
|
|
|
|
|
|
# |
498
|
|
|
|
|
|
|
# NOTE: this is redundant, being hard-coded (for now) into Parser.yp |
499
|
|
|
|
|
|
|
#------------------------------------------------------------------------ |
500
|
|
|
|
|
|
|
|
501
|
|
|
|
|
|
|
sub clear { |
502
|
1
|
|
|
1
|
0
|
114
|
return "output = '';"; |
503
|
|
|
|
|
|
|
} |
504
|
|
|
|
|
|
|
|
505
|
|
|
|
|
|
|
|
506
|
|
|
|
|
|
|
#------------------------------------------------------------------------ |
507
|
|
|
|
|
|
|
# break() [% BREAK %] |
508
|
|
|
|
|
|
|
# |
509
|
|
|
|
|
|
|
# NOTE: this is redundant, being hard-coded (for now) into Parser.yp |
510
|
|
|
|
|
|
|
#------------------------------------------------------------------------ |
511
|
|
|
|
|
|
|
|
512
|
|
|
|
|
|
|
sub break { |
513
|
1
|
|
|
1
|
0
|
82
|
return 'break;'; |
514
|
|
|
|
|
|
|
} |
515
|
|
|
|
|
|
|
|
516
|
|
|
|
|
|
|
#------------------------------------------------------------------------ |
517
|
|
|
|
|
|
|
# return() [% RETURN %] |
518
|
|
|
|
|
|
|
#------------------------------------------------------------------------ |
519
|
|
|
|
|
|
|
|
520
|
|
|
|
|
|
|
sub return { |
521
|
1
|
|
|
1
|
0
|
541
|
return "return output;" |
522
|
|
|
|
|
|
|
} |
523
|
|
|
|
|
|
|
|
524
|
|
|
|
|
|
|
|
525
|
|
|
|
|
|
|
#------------------------------------------------------------------------ |
526
|
|
|
|
|
|
|
# stop() [% STOP %] |
527
|
|
|
|
|
|
|
#------------------------------------------------------------------------ |
528
|
|
|
|
|
|
|
|
529
|
|
|
|
|
|
|
sub stop { |
530
|
1
|
|
|
1
|
0
|
87
|
return "throw('Jemplate.STOP\\n' + output);"; |
531
|
|
|
|
|
|
|
} |
532
|
|
|
|
|
|
|
|
533
|
|
|
|
|
|
|
|
534
|
|
|
|
|
|
|
#------------------------------------------------------------------------ |
535
|
|
|
|
|
|
|
# use(\@lnameargs) [% USE alias = plugin(args) %] |
536
|
|
|
|
|
|
|
# # => [ [$file, ...], \@args, $alias ] |
537
|
|
|
|
|
|
|
#------------------------------------------------------------------------ |
538
|
|
|
|
|
|
|
|
539
|
|
|
|
|
|
|
sub use { |
540
|
0
|
|
|
0
|
0
|
0
|
my ($class, $lnameargs) = @_; |
541
|
0
|
|
|
|
|
0
|
my ($file, $args, $alias) = @$lnameargs; |
542
|
0
|
|
|
|
|
0
|
$file = shift @$file; # same production rule as INCLUDE |
543
|
0
|
|
0
|
|
|
0
|
$alias ||= $file; |
544
|
0
|
|
|
|
|
0
|
$args = &args($class, $args); |
545
|
0
|
0
|
|
|
|
0
|
$file .= ", $args" if $args; |
546
|
0
|
|
|
|
|
0
|
return "// USE\n" |
547
|
|
|
|
|
|
|
. "stash.set($alias, context.plugin($file));"; |
548
|
|
|
|
|
|
|
} |
549
|
|
|
|
|
|
|
|
550
|
|
|
|
|
|
|
|
551
|
|
|
|
|
|
|
#------------------------------------------------------------------------ |
552
|
|
|
|
|
|
|
# raw(\@lnameargs) [% RAW alias = plugin(args) %] |
553
|
|
|
|
|
|
|
# # => [ [$file, ...], \@args, $alias ] |
554
|
|
|
|
|
|
|
#------------------------------------------------------------------------ |
555
|
|
|
|
|
|
|
|
556
|
|
|
|
|
|
|
sub raw { |
557
|
0
|
|
|
0
|
0
|
0
|
my ($class, $lnameargs) = @_; |
558
|
0
|
|
|
|
|
0
|
my ($file, $args, $alias) = @$lnameargs; |
559
|
0
|
|
|
|
|
0
|
$file = shift @$file; # same production rule as INCLUDE |
560
|
0
|
|
0
|
|
|
0
|
$alias ||= $file; |
561
|
0
|
|
|
|
|
0
|
$args = &args($class, $args); |
562
|
|
|
|
|
|
|
# $file .= ", $args" if $args; |
563
|
0
|
|
|
|
|
0
|
$file =~ s/'|"//g; |
564
|
0
|
|
|
|
|
0
|
return "// RAW\n" |
565
|
|
|
|
|
|
|
. "stash.set($alias, $file);"; |
566
|
|
|
|
|
|
|
} |
567
|
|
|
|
|
|
|
|
568
|
|
|
|
|
|
|
|
569
|
|
|
|
|
|
|
#------------------------------------------------------------------------ |
570
|
|
|
|
|
|
|
# stubs() [% STOP %] |
571
|
|
|
|
|
|
|
#------------------------------------------------------------------------ |
572
|
|
|
|
|
|
|
|
573
|
|
|
|
|
|
|
sub filter { |
574
|
0
|
|
|
0
|
0
|
0
|
my ($class, $lnameargs, $block) = @_; |
575
|
0
|
|
|
|
|
0
|
my ($name, $args, $alias) = @$lnameargs; |
576
|
0
|
|
|
|
|
0
|
$name = shift @$name; |
577
|
0
|
|
|
|
|
0
|
$args = &args($class, $args); |
578
|
0
|
0
|
|
|
|
0
|
$args = $args ? "$args, $alias" : ", null, $alias" |
|
|
0
|
|
|
|
|
|
579
|
|
|
|
|
|
|
if $alias; |
580
|
0
|
0
|
|
|
|
0
|
$name .= ", $args" if $args; |
581
|
0
|
|
|
|
|
0
|
return <
|
582
|
|
|
|
|
|
|
|
583
|
|
|
|
|
|
|
// FILTER |
584
|
|
|
|
|
|
|
$OUTPUT (function() { |
585
|
|
|
|
|
|
|
var output = ''; |
586
|
|
|
|
|
|
|
|
587
|
|
|
|
|
|
|
$block |
588
|
|
|
|
|
|
|
|
589
|
|
|
|
|
|
|
return context.filter(output, $name); |
590
|
|
|
|
|
|
|
})(); |
591
|
|
|
|
|
|
|
EOF |
592
|
|
|
|
|
|
|
} |
593
|
|
|
|
|
|
|
|
594
|
|
|
|
|
|
|
sub quoted { |
595
|
1
|
|
|
1
|
0
|
121
|
my $class = shift; |
596
|
1
|
50
|
33
|
|
|
8
|
if ( @_ && ref($_[0]) ) { |
597
|
1
|
|
|
|
|
3
|
return join( " + ", @{$_[0]} ); |
|
1
|
|
|
|
|
6
|
|
598
|
|
|
|
|
|
|
} |
599
|
0
|
|
|
|
|
0
|
return "throw('QUOTED called with unknown arguments in Jemplate');"; |
600
|
|
|
|
|
|
|
} |
601
|
|
|
|
|
|
|
|
602
|
|
|
|
|
|
|
#------------------------------------------------------------------------ |
603
|
|
|
|
|
|
|
# macro($name, $block, \@args) |
604
|
|
|
|
|
|
|
#------------------------------------------------------------------------ |
605
|
|
|
|
|
|
|
|
606
|
|
|
|
|
|
|
sub macro { |
607
|
1
|
|
|
1
|
0
|
95
|
my ($class, $ident, $block, $args) = @_; |
608
|
|
|
|
|
|
|
|
609
|
1
|
50
|
|
|
|
5
|
if ($args) { |
610
|
1
|
|
|
|
|
3
|
$args = join(';', map { "args['$_'] = fargs.shift()" } @$args); |
|
2
|
|
|
|
|
8
|
|
611
|
|
|
|
|
|
|
|
612
|
1
|
|
|
|
|
11
|
return <
|
613
|
|
|
|
|
|
|
|
614
|
|
|
|
|
|
|
//MACRO |
615
|
|
|
|
|
|
|
stash.set('$ident', function () { |
616
|
|
|
|
|
|
|
var output = ''; |
617
|
|
|
|
|
|
|
var args = {}; |
618
|
|
|
|
|
|
|
var fargs = Array.prototype.slice.call(arguments); |
619
|
|
|
|
|
|
|
$args; |
620
|
|
|
|
|
|
|
args.arguments = Array.prototype.slice.call(arguments); |
621
|
|
|
|
|
|
|
|
622
|
|
|
|
|
|
|
var params = fargs.shift() || {}; |
623
|
|
|
|
|
|
|
|
624
|
|
|
|
|
|
|
for (var key in params) { |
625
|
|
|
|
|
|
|
args[key] = params[key]; |
626
|
|
|
|
|
|
|
} |
627
|
|
|
|
|
|
|
|
628
|
|
|
|
|
|
|
context.stash.clone(args); |
629
|
|
|
|
|
|
|
try { |
630
|
|
|
|
|
|
|
$block |
631
|
|
|
|
|
|
|
} |
632
|
|
|
|
|
|
|
catch(e) { |
633
|
|
|
|
|
|
|
var error = context.set_error(e, output); |
634
|
|
|
|
|
|
|
throw(error); |
635
|
|
|
|
|
|
|
} |
636
|
|
|
|
|
|
|
|
637
|
|
|
|
|
|
|
context.stash.declone(); |
638
|
|
|
|
|
|
|
return output; |
639
|
|
|
|
|
|
|
}); |
640
|
|
|
|
|
|
|
|
641
|
|
|
|
|
|
|
EOF |
642
|
|
|
|
|
|
|
|
643
|
|
|
|
|
|
|
} |
644
|
|
|
|
|
|
|
else { |
645
|
0
|
|
|
|
|
|
return <
|
646
|
|
|
|
|
|
|
|
647
|
|
|
|
|
|
|
//MACRO |
648
|
|
|
|
|
|
|
|
649
|
|
|
|
|
|
|
stash.set('$ident', function () { |
650
|
|
|
|
|
|
|
var output = ''; |
651
|
|
|
|
|
|
|
var args = {}; |
652
|
|
|
|
|
|
|
|
653
|
|
|
|
|
|
|
var fargs = Array.prototype.slice.call(arguments); |
654
|
|
|
|
|
|
|
args.arguments = Array.prototype.slice.call(arguments); |
655
|
|
|
|
|
|
|
|
656
|
|
|
|
|
|
|
if (typeof arguments[0] == 'object') args = arguments[0]; |
657
|
|
|
|
|
|
|
|
658
|
|
|
|
|
|
|
context.stash.clone(args); |
659
|
|
|
|
|
|
|
try { |
660
|
|
|
|
|
|
|
$block |
661
|
|
|
|
|
|
|
} |
662
|
|
|
|
|
|
|
catch(e) { |
663
|
|
|
|
|
|
|
var error = context.set_error(e, output); |
664
|
|
|
|
|
|
|
throw(error); |
665
|
|
|
|
|
|
|
} |
666
|
|
|
|
|
|
|
|
667
|
|
|
|
|
|
|
context.stash.declone(); |
668
|
|
|
|
|
|
|
return output;}); |
669
|
|
|
|
|
|
|
|
670
|
|
|
|
|
|
|
EOF |
671
|
|
|
|
|
|
|
} |
672
|
|
|
|
|
|
|
} |
673
|
|
|
|
|
|
|
|
674
|
|
|
|
|
|
|
sub capture { |
675
|
0
|
|
|
0
|
0
|
|
my ($class, $name, $block) = @_; |
676
|
|
|
|
|
|
|
|
677
|
0
|
0
|
|
|
|
|
if (ref $name) { |
678
|
0
|
0
|
0
|
|
|
|
if (scalar @$name == 2 && ! $name->[1]) { |
679
|
0
|
|
|
|
|
|
$name = $name->[0]; |
680
|
|
|
|
|
|
|
} |
681
|
|
|
|
|
|
|
else { |
682
|
0
|
|
|
|
|
|
$name = '[' . join(', ', @$name) . ']'; |
683
|
|
|
|
|
|
|
} |
684
|
|
|
|
|
|
|
} |
685
|
|
|
|
|
|
|
|
686
|
0
|
|
|
|
|
|
return <
|
687
|
|
|
|
|
|
|
|
688
|
|
|
|
|
|
|
// CAPTURE |
689
|
|
|
|
|
|
|
(function() { |
690
|
|
|
|
|
|
|
var output = ''; |
691
|
|
|
|
|
|
|
$block |
692
|
|
|
|
|
|
|
stash.set($name, output); |
693
|
|
|
|
|
|
|
})(); |
694
|
|
|
|
|
|
|
EOF |
695
|
|
|
|
|
|
|
|
696
|
|
|
|
|
|
|
} |
697
|
|
|
|
|
|
|
|
698
|
|
|
|
|
|
|
BEGIN { |
699
|
22
|
|
|
22
|
|
1140
|
return; # Comment out this line to get callback traces |
700
|
22
|
|
|
22
|
|
591
|
no strict 'refs'; |
|
22
|
|
|
|
|
63
|
|
|
22
|
|
|
|
|
1294
|
|
701
|
0
|
|
|
|
|
0
|
my $pkg = __PACKAGE__ . '::'; |
702
|
0
|
|
|
|
|
0
|
my $stash = \ %$pkg; |
703
|
22
|
|
|
22
|
|
134
|
use strict 'refs'; |
|
22
|
|
|
|
|
95
|
|
|
22
|
|
|
|
|
1728
|
|
704
|
0
|
|
|
|
|
0
|
for my $name (keys %$stash) { |
705
|
0
|
|
|
|
|
0
|
my $glob = $stash->{$name}; |
706
|
0
|
0
|
|
|
|
0
|
if (*$glob{CODE}) { |
707
|
0
|
|
|
|
|
0
|
my $code = *$glob{CODE}; |
708
|
22
|
|
|
22
|
|
219
|
no warnings 'redefine'; |
|
22
|
|
|
|
|
49
|
|
|
22
|
|
|
|
|
2991
|
|
709
|
|
|
|
|
|
|
$stash->{$name} = sub { |
710
|
0
|
|
|
|
|
0
|
warn "Calling $name(@_)\n"; |
711
|
0
|
|
|
|
|
0
|
&$code(@_); |
712
|
0
|
|
|
|
|
0
|
}; |
713
|
|
|
|
|
|
|
} |
714
|
|
|
|
|
|
|
} |
715
|
|
|
|
|
|
|
} |
716
|
|
|
|
|
|
|
|
717
|
|
|
|
|
|
|
|
718
|
|
|
|
|
|
|
1; |
719
|
|
|
|
|
|
|
|
720
|
|
|
|
|
|
|
__END__ |