line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Text::Xslate::Syntax::HTMLTemplate; |
2
|
|
|
|
|
|
|
|
3
|
21
|
|
|
21
|
|
2411627
|
use 5.008_001; |
|
21
|
|
|
|
|
83
|
|
|
21
|
|
|
|
|
841
|
|
4
|
|
|
|
|
|
|
|
5
|
21
|
|
|
21
|
|
127
|
use strict; |
|
21
|
|
|
|
|
43
|
|
|
21
|
|
|
|
|
889
|
|
6
|
21
|
|
|
21
|
|
120
|
use warnings FATAL => 'recursion'; |
|
21
|
|
|
|
|
37
|
|
|
21
|
|
|
|
|
1518
|
|
7
|
|
|
|
|
|
|
|
8
|
|
|
|
|
|
|
our $VERSION = '0.1005'; |
9
|
|
|
|
|
|
|
|
10
|
21
|
|
|
21
|
|
37328
|
use Any::Moose; |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
extends qw(Text::Xslate::Parser); |
13
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
use HTML::Template::Parser; |
15
|
|
|
|
|
|
|
use Text::Xslate::Symbol; |
16
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
our %htp_compatible_function = ( |
18
|
|
|
|
|
|
|
sin => sub { sprintf("%f", sin @_); }, |
19
|
|
|
|
|
|
|
cos => sub { sprintf("%f", cos @_); }, |
20
|
|
|
|
|
|
|
atan => sub { sprintf("%f", atan2($_[0], $_[1])/2); }, |
21
|
|
|
|
|
|
|
log => sub { sprintf("%f", log @_); }, |
22
|
|
|
|
|
|
|
exp => sub { sprintf("%f", exp @_); }, |
23
|
|
|
|
|
|
|
sqrt => sub { sprintf("%f", sqrt @_); }, |
24
|
|
|
|
|
|
|
atan2 => sub { sprintf("%f", atan2($_[0], $_[1])); }, |
25
|
|
|
|
|
|
|
abs => sub { sprintf("%f", abs @_); }, |
26
|
|
|
|
|
|
|
defined => sub { defined $_[0]; }, |
27
|
|
|
|
|
|
|
int => sub { int($_[0]); }, |
28
|
|
|
|
|
|
|
hex => sub { hex($_[0]); }, |
29
|
|
|
|
|
|
|
length => sub { length($_[0]); }, |
30
|
|
|
|
|
|
|
oct => sub { oct($_[0]); }, |
31
|
|
|
|
|
|
|
); |
32
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
sub install_Xslate_as_HTMLTemplate { |
34
|
|
|
|
|
|
|
package Text::Xslate::Syntax::HTMLTemplate::_delegate; |
35
|
|
|
|
|
|
|
use strict; |
36
|
|
|
|
|
|
|
use warnings; |
37
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
require HTML::Template::Pro; |
39
|
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
our $xslate_engine; |
41
|
|
|
|
|
|
|
our $html_escape; |
42
|
|
|
|
|
|
|
|
43
|
|
|
|
|
|
|
my $original_HTP_new = \&HTML::Template::Pro::new; |
44
|
|
|
|
|
|
|
{ |
45
|
|
|
|
|
|
|
no strict 'refs'; |
46
|
|
|
|
|
|
|
no warnings 'redefine'; |
47
|
|
|
|
|
|
|
|
48
|
|
|
|
|
|
|
*{'HTML::Template::Pro::new'} = sub { |
49
|
|
|
|
|
|
|
my $self = { |
50
|
|
|
|
|
|
|
htp_engine => $original_HTP_new->(@_), |
51
|
|
|
|
|
|
|
}; |
52
|
|
|
|
|
|
|
bless $self, __PACKAGE__; |
53
|
|
|
|
|
|
|
if(! $xslate_engine){ |
54
|
|
|
|
|
|
|
$xslate_engine = Text::Xslate->new(syntax => 'HTMLTemplate', |
55
|
|
|
|
|
|
|
type => 'html', |
56
|
|
|
|
|
|
|
compiler => 'Text::Xslate::Compiler::HTMLTemplate', |
57
|
|
|
|
|
|
|
path => $self->{htp_engine}->{path}, |
58
|
|
|
|
|
|
|
function => { |
59
|
|
|
|
|
|
|
$html_escape ? |
60
|
|
|
|
|
|
|
( |
61
|
|
|
|
|
|
|
html => $html_escape, |
62
|
|
|
|
|
|
|
html_escape => $html_escape, |
63
|
|
|
|
|
|
|
) : (), |
64
|
|
|
|
|
|
|
__has_value__ => \&Text::Xslate::Syntax::HTMLTemplate::default_has_value, |
65
|
|
|
|
|
|
|
__choise_global_var__ => \&Text::Xslate::Syntax::HTMLTemplate::default_choise_global_var, |
66
|
|
|
|
|
|
|
}, |
67
|
|
|
|
|
|
|
); |
68
|
|
|
|
|
|
|
} |
69
|
|
|
|
|
|
|
$self; |
70
|
|
|
|
|
|
|
}; |
71
|
|
|
|
|
|
|
} |
72
|
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
sub set_html_escape_function { |
74
|
|
|
|
|
|
|
my($html_escape_arg) = @_; |
75
|
|
|
|
|
|
|
$html_escape = $html_escape_arg; |
76
|
|
|
|
|
|
|
$xslate_engine = undef; |
77
|
|
|
|
|
|
|
} |
78
|
|
|
|
|
|
|
|
79
|
|
|
|
|
|
|
sub param { |
80
|
|
|
|
|
|
|
shift->{htp_engine}->param(@_); |
81
|
|
|
|
|
|
|
} |
82
|
|
|
|
|
|
|
sub output_original_HTMLTemplate { |
83
|
|
|
|
|
|
|
shift->{htp_engine}->output(@_); |
84
|
|
|
|
|
|
|
} |
85
|
|
|
|
|
|
|
sub output { |
86
|
|
|
|
|
|
|
my $self = shift; |
87
|
|
|
|
|
|
|
|
88
|
|
|
|
|
|
|
$self->{param} = {}; |
89
|
|
|
|
|
|
|
foreach my $key ($self->{htp_engine}->param()){ |
90
|
|
|
|
|
|
|
$self->{param}->{$key} = $self->{htp_engine}->param($key); |
91
|
|
|
|
|
|
|
} |
92
|
|
|
|
|
|
|
$self->_set_function_as_param($self->{htp_engine}->{expr_func}); |
93
|
|
|
|
|
|
|
$self->_set_function_as_param(\%HTML::Template::Pro::FUNC); |
94
|
|
|
|
|
|
|
|
95
|
|
|
|
|
|
|
local $Text::Xslate::Syntax::HTMLTemplate::before_parse_hook = sub { |
96
|
|
|
|
|
|
|
my $parser = shift; |
97
|
|
|
|
|
|
|
$parser->use_global_vars($self->{htp_engine}{global_vars}); |
98
|
|
|
|
|
|
|
$parser->use_has_value(1); |
99
|
|
|
|
|
|
|
$parser->use_loop_context_vars($self->{htp_engine}{loop_context_vars}); |
100
|
|
|
|
|
|
|
$parser->use_path_like_variable_scope($self->{htp_engine}{path_like_variable_scope}); |
101
|
|
|
|
|
|
|
}; |
102
|
|
|
|
|
|
|
$xslate_engine->render_string(${$self->{htp_engine}->{scalarref}}, $self->{param}); |
103
|
|
|
|
|
|
|
} |
104
|
|
|
|
|
|
|
sub _set_function_as_param { |
105
|
|
|
|
|
|
|
my($self, $function_hash) = @_; |
106
|
|
|
|
|
|
|
|
107
|
|
|
|
|
|
|
while (my($k, $v) = each %$function_hash) { |
108
|
|
|
|
|
|
|
if (exists $self->{param}->{$k}) { |
109
|
|
|
|
|
|
|
$v = Text::Xslate::Syntax::HTMLTemplate::StringOrFunction->new($self->{param}->{$k}, $v); |
110
|
|
|
|
|
|
|
} |
111
|
|
|
|
|
|
|
$self->{param}->{$k} = $v; |
112
|
|
|
|
|
|
|
} |
113
|
|
|
|
|
|
|
} |
114
|
|
|
|
|
|
|
|
115
|
|
|
|
|
|
|
package Text::Xslate::Syntax::HTMLTemplate::StringOrFunction; |
116
|
|
|
|
|
|
|
use strict; |
117
|
|
|
|
|
|
|
use warnings; |
118
|
|
|
|
|
|
|
|
119
|
|
|
|
|
|
|
use overload |
120
|
|
|
|
|
|
|
q{""} => sub { shift->{string}; }, |
121
|
|
|
|
|
|
|
'&{}' => sub { shift->{function}; }, |
122
|
|
|
|
|
|
|
; |
123
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
sub new { |
125
|
|
|
|
|
|
|
my($class, $string, $function) = @_; |
126
|
|
|
|
|
|
|
my $self = { |
127
|
|
|
|
|
|
|
string => $string, |
128
|
|
|
|
|
|
|
function => $function, |
129
|
|
|
|
|
|
|
}; |
130
|
|
|
|
|
|
|
bless $self, $class; |
131
|
|
|
|
|
|
|
} |
132
|
|
|
|
|
|
|
} |
133
|
|
|
|
|
|
|
|
134
|
|
|
|
|
|
|
sub default_has_value { |
135
|
|
|
|
|
|
|
return 0 if(@_ == 0); |
136
|
|
|
|
|
|
|
return @{$_[0]} != 0 if($_[0] and ref($_[0]) eq 'ARRAY'); |
137
|
|
|
|
|
|
|
$_[0]; |
138
|
|
|
|
|
|
|
} |
139
|
|
|
|
|
|
|
|
140
|
|
|
|
|
|
|
sub default_choise_global_var { |
141
|
|
|
|
|
|
|
my($global, $name, @loop_var_list) = @_; |
142
|
|
|
|
|
|
|
foreach my $loop_var (@loop_var_list){ |
143
|
|
|
|
|
|
|
if(exists $loop_var->{$name}){ |
144
|
|
|
|
|
|
|
return $loop_var->{$name}; |
145
|
|
|
|
|
|
|
} |
146
|
|
|
|
|
|
|
} |
147
|
|
|
|
|
|
|
$global; |
148
|
|
|
|
|
|
|
} |
149
|
|
|
|
|
|
|
|
150
|
|
|
|
|
|
|
our $before_parse_hook = undef; |
151
|
|
|
|
|
|
|
|
152
|
|
|
|
|
|
|
before 'parse' => sub { |
153
|
|
|
|
|
|
|
if($before_parse_hook and ref($before_parse_hook) eq 'CODE'){ |
154
|
|
|
|
|
|
|
my $self = shift; |
155
|
|
|
|
|
|
|
$before_parse_hook->($self); |
156
|
|
|
|
|
|
|
} |
157
|
|
|
|
|
|
|
}; |
158
|
|
|
|
|
|
|
|
159
|
|
|
|
|
|
|
our %loop_context_vars = ( |
160
|
|
|
|
|
|
|
__counter__ => \&iterator_counter, |
161
|
|
|
|
|
|
|
__first__ => \&iterator_first, |
162
|
|
|
|
|
|
|
__odd__ => \&iterator_odd, |
163
|
|
|
|
|
|
|
__inner__ => \&iterator_inner, |
164
|
|
|
|
|
|
|
__last__ => \&iterator_last, |
165
|
|
|
|
|
|
|
); |
166
|
|
|
|
|
|
|
|
167
|
|
|
|
|
|
|
has input_filter => ( |
168
|
|
|
|
|
|
|
is => 'rw', |
169
|
|
|
|
|
|
|
isa => 'CodeRef', |
170
|
|
|
|
|
|
|
); |
171
|
|
|
|
|
|
|
|
172
|
|
|
|
|
|
|
has parser => ( |
173
|
|
|
|
|
|
|
is => 'rw', |
174
|
|
|
|
|
|
|
required => 1, |
175
|
|
|
|
|
|
|
lazy => 1, |
176
|
|
|
|
|
|
|
builder => '_build_parser', |
177
|
|
|
|
|
|
|
); |
178
|
|
|
|
|
|
|
|
179
|
|
|
|
|
|
|
has use_has_value => ( |
180
|
|
|
|
|
|
|
is => 'rw', |
181
|
|
|
|
|
|
|
default => 0, |
182
|
|
|
|
|
|
|
); |
183
|
|
|
|
|
|
|
|
184
|
|
|
|
|
|
|
has use_global_vars => ( |
185
|
|
|
|
|
|
|
is => 'rw', |
186
|
|
|
|
|
|
|
isa => 'Bool', |
187
|
|
|
|
|
|
|
default => 0, |
188
|
|
|
|
|
|
|
); |
189
|
|
|
|
|
|
|
|
190
|
|
|
|
|
|
|
has use_loop_context_vars => ( |
191
|
|
|
|
|
|
|
is => 'rw', |
192
|
|
|
|
|
|
|
isa => 'Bool', |
193
|
|
|
|
|
|
|
default => 0, |
194
|
|
|
|
|
|
|
); |
195
|
|
|
|
|
|
|
|
196
|
|
|
|
|
|
|
has use_path_like_variable_scope => ( |
197
|
|
|
|
|
|
|
is => 'rw', |
198
|
|
|
|
|
|
|
isa => 'Bool', |
199
|
|
|
|
|
|
|
default => 0, |
200
|
|
|
|
|
|
|
); |
201
|
|
|
|
|
|
|
|
202
|
|
|
|
|
|
|
has has_value_function_name => ( |
203
|
|
|
|
|
|
|
is => 'rw', |
204
|
|
|
|
|
|
|
default => '__has_value__', |
205
|
|
|
|
|
|
|
); |
206
|
|
|
|
|
|
|
|
207
|
|
|
|
|
|
|
has choise_global_var_function_name => ( |
208
|
|
|
|
|
|
|
is => 'rw', |
209
|
|
|
|
|
|
|
default => '__choise_global_var__', |
210
|
|
|
|
|
|
|
); |
211
|
|
|
|
|
|
|
|
212
|
|
|
|
|
|
|
has loop_context_var_function_name => ( |
213
|
|
|
|
|
|
|
is => 'rw', |
214
|
|
|
|
|
|
|
default => '__get_loop_context_var__', |
215
|
|
|
|
|
|
|
); |
216
|
|
|
|
|
|
|
|
217
|
|
|
|
|
|
|
has dummy_loop_item_name => ( |
218
|
|
|
|
|
|
|
is => 'rw', |
219
|
|
|
|
|
|
|
required => 1, |
220
|
|
|
|
|
|
|
default => '__dummy_item__', |
221
|
|
|
|
|
|
|
); |
222
|
|
|
|
|
|
|
|
223
|
|
|
|
|
|
|
has loop_depth => ( |
224
|
|
|
|
|
|
|
is => 'rw', |
225
|
|
|
|
|
|
|
isa => 'Int', |
226
|
|
|
|
|
|
|
default => 0, |
227
|
|
|
|
|
|
|
); |
228
|
|
|
|
|
|
|
|
229
|
|
|
|
|
|
|
has is_escaped_var => ( |
230
|
|
|
|
|
|
|
is => 'rw', |
231
|
|
|
|
|
|
|
isa => 'CodeRef', |
232
|
|
|
|
|
|
|
default => sub { sub {0;} }, |
233
|
|
|
|
|
|
|
); |
234
|
|
|
|
|
|
|
|
235
|
|
|
|
|
|
|
has op_to_type_table => ( |
236
|
|
|
|
|
|
|
is => 'rw', |
237
|
|
|
|
|
|
|
isa => 'HashRef', |
238
|
|
|
|
|
|
|
lazy => 1, |
239
|
|
|
|
|
|
|
builder => '_build_op_to_type_table', |
240
|
|
|
|
|
|
|
); |
241
|
|
|
|
|
|
|
|
242
|
|
|
|
|
|
|
sub _build_parser { |
243
|
|
|
|
|
|
|
my($self) = @_; |
244
|
|
|
|
|
|
|
|
245
|
|
|
|
|
|
|
return HTML::Template::Parser->new; |
246
|
|
|
|
|
|
|
} |
247
|
|
|
|
|
|
|
|
248
|
|
|
|
|
|
|
sub _build_op_to_type_table { |
249
|
|
|
|
|
|
|
my %op_to_type_table = ( |
250
|
|
|
|
|
|
|
'not' => 'not_sym', |
251
|
|
|
|
|
|
|
'!' => 'not', |
252
|
|
|
|
|
|
|
); |
253
|
|
|
|
|
|
|
foreach my $bin_operator (qw(or and || && > >= < <= != == le ge eq ne lt gt + - * / % =~ !~)){ |
254
|
|
|
|
|
|
|
$op_to_type_table{$bin_operator} = 'binary'; |
255
|
|
|
|
|
|
|
} |
256
|
|
|
|
|
|
|
\%op_to_type_table; |
257
|
|
|
|
|
|
|
} |
258
|
|
|
|
|
|
|
|
259
|
|
|
|
|
|
|
sub parse { |
260
|
|
|
|
|
|
|
my($self, $input, %no_use) = @_; |
261
|
|
|
|
|
|
|
|
262
|
|
|
|
|
|
|
$self->input_filter->(\$input) if($self->input_filter); |
263
|
|
|
|
|
|
|
|
264
|
|
|
|
|
|
|
my $tree = $self->parser->parse($input); |
265
|
|
|
|
|
|
|
my @ast = $self->tree_to_ast($tree); |
266
|
|
|
|
|
|
|
\@ast; |
267
|
|
|
|
|
|
|
} |
268
|
|
|
|
|
|
|
|
269
|
|
|
|
|
|
|
sub tree_to_ast { |
270
|
|
|
|
|
|
|
my($self, $tree) = @_; |
271
|
|
|
|
|
|
|
|
272
|
|
|
|
|
|
|
# require YAML;print STDERR "XXX tree:", YAML::Dump($tree), '=' x 80,"\n"; # @@@ |
273
|
|
|
|
|
|
|
|
274
|
|
|
|
|
|
|
$self->convert_children($tree->children); |
275
|
|
|
|
|
|
|
} |
276
|
|
|
|
|
|
|
|
277
|
|
|
|
|
|
|
sub convert_children { |
278
|
|
|
|
|
|
|
my($self, $children) = @_; |
279
|
|
|
|
|
|
|
|
280
|
|
|
|
|
|
|
my @ast; |
281
|
|
|
|
|
|
|
foreach my $node (@{ $children }){ |
282
|
|
|
|
|
|
|
push(@ast, $self->convert_node($node)); |
283
|
|
|
|
|
|
|
} |
284
|
|
|
|
|
|
|
@ast; |
285
|
|
|
|
|
|
|
} |
286
|
|
|
|
|
|
|
|
287
|
|
|
|
|
|
|
|
288
|
|
|
|
|
|
|
sub convert_node { |
289
|
|
|
|
|
|
|
my($self, $node) = @_; |
290
|
|
|
|
|
|
|
|
291
|
|
|
|
|
|
|
if($node->type eq 'string'){ |
292
|
|
|
|
|
|
|
$self->convert_string($node); |
293
|
|
|
|
|
|
|
}elsif($node->type eq 'var'){ |
294
|
|
|
|
|
|
|
$self->convert_tmpl_var($node); |
295
|
|
|
|
|
|
|
}elsif($node->type eq 'group'){ |
296
|
|
|
|
|
|
|
$self->convert_group($node); |
297
|
|
|
|
|
|
|
}elsif($node->type eq 'include'){ |
298
|
|
|
|
|
|
|
$self->convert_include($node); |
299
|
|
|
|
|
|
|
}else{ |
300
|
|
|
|
|
|
|
die "not implemented [", $node->type, "]"; # @@@ |
301
|
|
|
|
|
|
|
} |
302
|
|
|
|
|
|
|
} |
303
|
|
|
|
|
|
|
|
304
|
|
|
|
|
|
|
sub convert_string { |
305
|
|
|
|
|
|
|
my($self, $node) = @_; |
306
|
|
|
|
|
|
|
|
307
|
|
|
|
|
|
|
(my $id = $node->text) =~ s/\n/\\n/g; # @@@ |
308
|
|
|
|
|
|
|
|
309
|
|
|
|
|
|
|
$self->generate_print_raw($self->generate_literal($node->text, qq{"$id"})); |
310
|
|
|
|
|
|
|
} |
311
|
|
|
|
|
|
|
|
312
|
|
|
|
|
|
|
sub convert_tmpl_var { |
313
|
|
|
|
|
|
|
my($self, $node) = @_; |
314
|
|
|
|
|
|
|
|
315
|
|
|
|
|
|
|
my $expr = $self->convert_name_or_expr($node->name_or_expr); |
316
|
|
|
|
|
|
|
|
317
|
|
|
|
|
|
|
my $do_mark_raw = 0; |
318
|
|
|
|
|
|
|
if(defined $node->{escape} and $node->{escape} eq '0'){ |
319
|
|
|
|
|
|
|
$do_mark_raw = 1; |
320
|
|
|
|
|
|
|
} |
321
|
|
|
|
|
|
|
if($node->name_or_expr->[0] eq 'name' and $self->is_escaped_var->($node->name_or_expr->[1]->[1])){ |
322
|
|
|
|
|
|
|
$do_mark_raw = 1; |
323
|
|
|
|
|
|
|
} |
324
|
|
|
|
|
|
|
|
325
|
|
|
|
|
|
|
if($do_mark_raw){ |
326
|
|
|
|
|
|
|
$expr = $self->generate_call('mark_raw', [ $expr ]); |
327
|
|
|
|
|
|
|
} |
328
|
|
|
|
|
|
|
$self->generate_print($expr); |
329
|
|
|
|
|
|
|
} |
330
|
|
|
|
|
|
|
|
331
|
|
|
|
|
|
|
sub convert_group { |
332
|
|
|
|
|
|
|
my($self, $node) = @_; |
333
|
|
|
|
|
|
|
|
334
|
|
|
|
|
|
|
if($node->sub_type eq 'if' or $node->sub_type eq 'unless'){ |
335
|
|
|
|
|
|
|
my @children = ( @{ $node->children } ); # copy |
336
|
|
|
|
|
|
|
pop @children; # remove Node::IfEnd |
337
|
|
|
|
|
|
|
|
338
|
|
|
|
|
|
|
my $if = $self->convert_if(\@children); |
339
|
|
|
|
|
|
|
$if; |
340
|
|
|
|
|
|
|
}elsif($node->sub_type eq 'loop'){ |
341
|
|
|
|
|
|
|
my $loop = $self->convert_loop($node->children->[0]); |
342
|
|
|
|
|
|
|
$loop; |
343
|
|
|
|
|
|
|
}else{ |
344
|
|
|
|
|
|
|
die "not implemented sub_type[", $node->sub_type, "]"; # @@@ |
345
|
|
|
|
|
|
|
} |
346
|
|
|
|
|
|
|
} |
347
|
|
|
|
|
|
|
|
348
|
|
|
|
|
|
|
sub convert_if { |
349
|
|
|
|
|
|
|
my($self, $children) = @_; |
350
|
|
|
|
|
|
|
|
351
|
|
|
|
|
|
|
my $node = shift(@{ $children }); |
352
|
|
|
|
|
|
|
if($node->type eq 'else'){ |
353
|
|
|
|
|
|
|
return $self->convert_children($node->children), |
354
|
|
|
|
|
|
|
} |
355
|
|
|
|
|
|
|
my $type = $node->type; |
356
|
|
|
|
|
|
|
|
357
|
|
|
|
|
|
|
my $expr = $self->convert_name_or_expr($node->name_or_expr); |
358
|
|
|
|
|
|
|
if($self->use_has_value){ |
359
|
|
|
|
|
|
|
$expr = $self->generate_call($self->has_value_function_name, [ $expr ]); |
360
|
|
|
|
|
|
|
} |
361
|
|
|
|
|
|
|
if($node->type eq 'unless'){ |
362
|
|
|
|
|
|
|
$type = 'if'; |
363
|
|
|
|
|
|
|
$expr = $self->generate_unary('!', $expr); |
364
|
|
|
|
|
|
|
} |
365
|
|
|
|
|
|
|
my $if = $self->generate_if($type, $expr, [ $self->convert_children($node->children) ]); |
366
|
|
|
|
|
|
|
if(@{$children}){ |
367
|
|
|
|
|
|
|
$if->third([ $self->convert_if($children) ]); |
368
|
|
|
|
|
|
|
} |
369
|
|
|
|
|
|
|
$if; |
370
|
|
|
|
|
|
|
} |
371
|
|
|
|
|
|
|
|
372
|
|
|
|
|
|
|
sub convert_loop { |
373
|
|
|
|
|
|
|
my($self, $node) = @_; |
374
|
|
|
|
|
|
|
|
375
|
|
|
|
|
|
|
my $loop = $self->generate_for($self->convert_name_or_expr($node->name_or_expr)); |
376
|
|
|
|
|
|
|
|
377
|
|
|
|
|
|
|
$self->loop_depth($self->loop_depth + 1); |
378
|
|
|
|
|
|
|
$loop->second([ $self->generate_variable('$'.$self->dummy_loop_item_name . $self->loop_depth) ]); |
379
|
|
|
|
|
|
|
$loop->third([ $self->convert_children($node->children) ]); |
380
|
|
|
|
|
|
|
$self->loop_depth($self->loop_depth - 1); |
381
|
|
|
|
|
|
|
|
382
|
|
|
|
|
|
|
$loop; |
383
|
|
|
|
|
|
|
} |
384
|
|
|
|
|
|
|
|
385
|
|
|
|
|
|
|
sub convert_include { |
386
|
|
|
|
|
|
|
my($self, $node) = @_; |
387
|
|
|
|
|
|
|
|
388
|
|
|
|
|
|
|
if($node->name_or_expr->[0] eq 'name'){ |
389
|
|
|
|
|
|
|
# treat as string |
390
|
|
|
|
|
|
|
$node->name_or_expr->[0] = 'expr'; |
391
|
|
|
|
|
|
|
$node->name_or_expr->[1][0] = 'string'; |
392
|
|
|
|
|
|
|
} |
393
|
|
|
|
|
|
|
my $include = $self->generate_include($self->convert_name_or_expr($node->name_or_expr)); |
394
|
|
|
|
|
|
|
|
395
|
|
|
|
|
|
|
if($self->loop_depth){ |
396
|
|
|
|
|
|
|
$include->second([ |
397
|
|
|
|
|
|
|
$self->generate_methodcall( |
398
|
|
|
|
|
|
|
'.', |
399
|
|
|
|
|
|
|
$self->generate_vars('__ROOT__'), |
400
|
|
|
|
|
|
|
$self->generate_literal(undef, 'merge'), |
401
|
|
|
|
|
|
|
$self->generate_variable('$'.$self->dummy_loop_item_name.$self->loop_depth), |
402
|
|
|
|
|
|
|
)]); |
403
|
|
|
|
|
|
|
} |
404
|
|
|
|
|
|
|
$include; |
405
|
|
|
|
|
|
|
} |
406
|
|
|
|
|
|
|
|
407
|
|
|
|
|
|
|
sub convert_name_or_expr { |
408
|
|
|
|
|
|
|
my($self, $name_or_expr) = @_; |
409
|
|
|
|
|
|
|
|
410
|
|
|
|
|
|
|
if($name_or_expr->[0] eq 'name'){ |
411
|
|
|
|
|
|
|
$self->convert_name($name_or_expr->[1]); |
412
|
|
|
|
|
|
|
}else{ # expr |
413
|
|
|
|
|
|
|
$self->convert_expr($name_or_expr->[1]); |
414
|
|
|
|
|
|
|
} |
415
|
|
|
|
|
|
|
} |
416
|
|
|
|
|
|
|
|
417
|
|
|
|
|
|
|
sub convert_name { |
418
|
|
|
|
|
|
|
my($self, $name) = @_; |
419
|
|
|
|
|
|
|
|
420
|
|
|
|
|
|
|
if($self->use_path_like_variable_scope and $name->[1] =~ m{^/(.*)}){ |
421
|
|
|
|
|
|
|
# path like variables. abs path |
422
|
|
|
|
|
|
|
return $self->generate_variable('$' . $1); |
423
|
|
|
|
|
|
|
} |
424
|
|
|
|
|
|
|
if ($self->loop_depth) { |
425
|
|
|
|
|
|
|
if($self->use_path_like_variable_scope and $name->[1] =~ m{^../}){ |
426
|
|
|
|
|
|
|
# path like variables. relative path |
427
|
|
|
|
|
|
|
my $name = $name->[1]; |
428
|
|
|
|
|
|
|
my $depth = $self->loop_depth; |
429
|
|
|
|
|
|
|
$depth -- while($name =~ s{^../}{}); |
430
|
|
|
|
|
|
|
|
431
|
|
|
|
|
|
|
if($depth < 1){ |
432
|
|
|
|
|
|
|
return $self->generate_variable('$' . $name); |
433
|
|
|
|
|
|
|
} |
434
|
|
|
|
|
|
|
|
435
|
|
|
|
|
|
|
my $item_name = '$' . $self->dummy_loop_item_name . $depth; |
436
|
|
|
|
|
|
|
return $self->generate_field('.', |
437
|
|
|
|
|
|
|
$self->generate_variable($item_name), |
438
|
|
|
|
|
|
|
$self->generate_literal($name)); |
439
|
|
|
|
|
|
|
} |
440
|
|
|
|
|
|
|
|
441
|
|
|
|
|
|
|
if($self->is_loop_context_vars($name)){ |
442
|
|
|
|
|
|
|
$self->convert_loop_context_vars($name); |
443
|
|
|
|
|
|
|
}elsif ($self->use_global_vars) { |
444
|
|
|
|
|
|
|
# __choise_global_var__($loop_item_1.name, $loop_item_2.name, .... $name); |
445
|
|
|
|
|
|
|
my $name = $name->[1]; |
446
|
|
|
|
|
|
|
my @args; |
447
|
|
|
|
|
|
|
|
448
|
|
|
|
|
|
|
push(@args, $self->generate_variable($name)); |
449
|
|
|
|
|
|
|
push(@args, $self->generate_literal($name)); |
450
|
|
|
|
|
|
|
|
451
|
|
|
|
|
|
|
for (my $n = $self->loop_depth;$n > 0;$n --) { |
452
|
|
|
|
|
|
|
my $item_name = '$' . $self->dummy_loop_item_name . $n; |
453
|
|
|
|
|
|
|
push(@args, $self->generate_variable($item_name)); |
454
|
|
|
|
|
|
|
} |
455
|
|
|
|
|
|
|
$self->generate_call($self->choise_global_var_function_name, \@args); |
456
|
|
|
|
|
|
|
} else { |
457
|
|
|
|
|
|
|
my $item_name = '$' . $self->dummy_loop_item_name . $self->loop_depth; |
458
|
|
|
|
|
|
|
$self->generate_field('.', |
459
|
|
|
|
|
|
|
$self->generate_variable($item_name), |
460
|
|
|
|
|
|
|
$self->generate_literal($name->[1])); |
461
|
|
|
|
|
|
|
} |
462
|
|
|
|
|
|
|
} else { |
463
|
|
|
|
|
|
|
$self->generate_variable('$' . $name->[1]); |
464
|
|
|
|
|
|
|
} |
465
|
|
|
|
|
|
|
} |
466
|
|
|
|
|
|
|
|
467
|
|
|
|
|
|
|
sub convert_expr { |
468
|
|
|
|
|
|
|
my($self, $expr) = @_; |
469
|
|
|
|
|
|
|
|
470
|
|
|
|
|
|
|
my $type = $expr->[0]; |
471
|
|
|
|
|
|
|
if ($type eq 'op') { |
472
|
|
|
|
|
|
|
my $op_to_type = $self->op_to_type_table->{$expr->[1]}; |
473
|
|
|
|
|
|
|
die "Unknown op_name[$expr->[1]]\n" unless $op_to_type; |
474
|
|
|
|
|
|
|
$type = $op_to_type; |
475
|
|
|
|
|
|
|
} |
476
|
|
|
|
|
|
|
|
477
|
|
|
|
|
|
|
if ($type eq 'variable') { |
478
|
|
|
|
|
|
|
$self->convert_name($expr); |
479
|
|
|
|
|
|
|
} elsif ($type eq 'number') { |
480
|
|
|
|
|
|
|
$self->generate_literal($expr->[1]); |
481
|
|
|
|
|
|
|
} elsif ($type eq 'string') { |
482
|
|
|
|
|
|
|
$self->generate_literal($expr->[1], '"'.$expr->[1].'"'); |
483
|
|
|
|
|
|
|
} elsif ($type eq 'binary') { |
484
|
|
|
|
|
|
|
my %op_translate_table = ( |
485
|
|
|
|
|
|
|
'eq' => '==', |
486
|
|
|
|
|
|
|
'ne' => '!=', |
487
|
|
|
|
|
|
|
'or' => '||', |
488
|
|
|
|
|
|
|
'and' => '&&', |
489
|
|
|
|
|
|
|
); |
490
|
|
|
|
|
|
|
my $op = $op_translate_table{$expr->[1]} || $expr->[1]; |
491
|
|
|
|
|
|
|
my $ast = $self->generate_binary($op, $self->convert_expr($expr->[2]), $self->convert_expr($expr->[3])); |
492
|
|
|
|
|
|
|
if($op eq '==' and $ast->second->arity eq 'literal' and !$ast->second->value){ |
493
|
|
|
|
|
|
|
# @@@ special case |
494
|
|
|
|
|
|
|
# HTML::Tempalte treat (undef == 0) as true |
495
|
|
|
|
|
|
|
# HTML::Tempalte treat (undef == '') as true |
496
|
|
|
|
|
|
|
# convert 'x == 0' to '(x || 0) == 0' |
497
|
|
|
|
|
|
|
# convert 'x == ""' to '(x || "") == ""' |
498
|
|
|
|
|
|
|
$ast = $self->generate_binary($op, |
499
|
|
|
|
|
|
|
$self->generate_binary('||', $ast->first, $ast->second), |
500
|
|
|
|
|
|
|
$ast->second); |
501
|
|
|
|
|
|
|
} |
502
|
|
|
|
|
|
|
$ast; |
503
|
|
|
|
|
|
|
} elsif ($type eq 'function') { |
504
|
|
|
|
|
|
|
my(undef, $name, @raw_args) = @{ $expr }; |
505
|
|
|
|
|
|
|
my @args = map { $self->convert_expr($_) } @raw_args; |
506
|
|
|
|
|
|
|
$self->generate_call($name->[1], \@args); |
507
|
|
|
|
|
|
|
}elsif($type eq 'not_sym' or $type eq 'not'){ |
508
|
|
|
|
|
|
|
$self->generate_unary('!', $self->convert_expr($expr->[2])); |
509
|
|
|
|
|
|
|
} else { |
510
|
|
|
|
|
|
|
die "not implemented yet [$expr->[0]]"; # @@@ |
511
|
|
|
|
|
|
|
} |
512
|
|
|
|
|
|
|
} |
513
|
|
|
|
|
|
|
|
514
|
|
|
|
|
|
|
sub is_loop_context_vars { |
515
|
|
|
|
|
|
|
my($self, $name) = @_; |
516
|
|
|
|
|
|
|
|
517
|
|
|
|
|
|
|
$self->use_loop_context_vars and $loop_context_vars{$name->[1]}; |
518
|
|
|
|
|
|
|
} |
519
|
|
|
|
|
|
|
|
520
|
|
|
|
|
|
|
sub convert_loop_context_vars { |
521
|
|
|
|
|
|
|
my($self, $name) = @_; |
522
|
|
|
|
|
|
|
|
523
|
|
|
|
|
|
|
if($self->loop_depth == 0){ # outside loop |
524
|
|
|
|
|
|
|
return $self->generate_literal(0); |
525
|
|
|
|
|
|
|
} |
526
|
|
|
|
|
|
|
|
527
|
|
|
|
|
|
|
my $var_name = $name->[1]; |
528
|
|
|
|
|
|
|
my $iterator_name = '$~' . $self->dummy_loop_item_name . $self->loop_depth; |
529
|
|
|
|
|
|
|
my $item_name = '$' . $self->dummy_loop_item_name . $self->loop_depth; |
530
|
|
|
|
|
|
|
|
531
|
|
|
|
|
|
|
my $generator = $loop_context_vars{$var_name}; |
532
|
|
|
|
|
|
|
return $generator->($self, $iterator_name, $item_name); |
533
|
|
|
|
|
|
|
} |
534
|
|
|
|
|
|
|
|
535
|
|
|
|
|
|
|
sub iterator_counter { |
536
|
|
|
|
|
|
|
my($self, $iterator_name, $item_name) = @_; |
537
|
|
|
|
|
|
|
|
538
|
|
|
|
|
|
|
$self->generate_binary('+', $self->generate_iterator($iterator_name, $item_name), $self->generate_literal(1)); |
539
|
|
|
|
|
|
|
} |
540
|
|
|
|
|
|
|
|
541
|
|
|
|
|
|
|
sub iterator_first { |
542
|
|
|
|
|
|
|
my($self, $iterator_name, $item_name) = @_; |
543
|
|
|
|
|
|
|
|
544
|
|
|
|
|
|
|
$self->generate_binary('==', $self->generate_iterator($iterator_name, $item_name), $self->generate_literal(0)); |
545
|
|
|
|
|
|
|
} |
546
|
|
|
|
|
|
|
|
547
|
|
|
|
|
|
|
sub iterator_odd { |
548
|
|
|
|
|
|
|
my($self, $iterator_name, $item_name) = @_; |
549
|
|
|
|
|
|
|
|
550
|
|
|
|
|
|
|
$self->generate_binary('==', |
551
|
|
|
|
|
|
|
$self->generate_binary('%', |
552
|
|
|
|
|
|
|
$self->generate_iterator($iterator_name, $item_name), |
553
|
|
|
|
|
|
|
$self->generate_literal(2)), |
554
|
|
|
|
|
|
|
$self->generate_literal(0)); |
555
|
|
|
|
|
|
|
} |
556
|
|
|
|
|
|
|
|
557
|
|
|
|
|
|
|
sub iterator_inner { |
558
|
|
|
|
|
|
|
my($self, $iterator_name, $item_name) = @_; |
559
|
|
|
|
|
|
|
|
560
|
|
|
|
|
|
|
$self->generate_unary('!', $self->generate_binary('||', |
561
|
|
|
|
|
|
|
$self->iterator_first($iterator_name, $item_name), |
562
|
|
|
|
|
|
|
$self->iterator_last($iterator_name, $item_name))); |
563
|
|
|
|
|
|
|
} |
564
|
|
|
|
|
|
|
|
565
|
|
|
|
|
|
|
sub iterator_last { |
566
|
|
|
|
|
|
|
my($self, $iterator_name, $item_name) = @_; |
567
|
|
|
|
|
|
|
|
568
|
|
|
|
|
|
|
$self->generate_binary('==', |
569
|
|
|
|
|
|
|
$self->generate_iterator($iterator_name, $item_name), |
570
|
|
|
|
|
|
|
$self->generate_iterator_max_index($iterator_name, $item_name)); |
571
|
|
|
|
|
|
|
} |
572
|
|
|
|
|
|
|
|
573
|
|
|
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
574
|
|
|
|
|
|
|
sub generate_print { |
575
|
|
|
|
|
|
|
my($self, @args) = @_; |
576
|
|
|
|
|
|
|
|
577
|
|
|
|
|
|
|
Text::Xslate::Symbol->new(arity => 'print', first => [ @args ], id => 'print'); |
578
|
|
|
|
|
|
|
} |
579
|
|
|
|
|
|
|
|
580
|
|
|
|
|
|
|
sub generate_print_raw { |
581
|
|
|
|
|
|
|
my($self, @args) = @_; |
582
|
|
|
|
|
|
|
|
583
|
|
|
|
|
|
|
Text::Xslate::Symbol->new(arity => 'print', first => [ @args ], id => 'print_raw'); |
584
|
|
|
|
|
|
|
} |
585
|
|
|
|
|
|
|
|
586
|
|
|
|
|
|
|
sub generate_include { |
587
|
|
|
|
|
|
|
my($self, $first) = @_; |
588
|
|
|
|
|
|
|
Text::Xslate::Symbol->new(arity => 'include', id => 'include', first => $first, second => undef); |
589
|
|
|
|
|
|
|
} |
590
|
|
|
|
|
|
|
|
591
|
|
|
|
|
|
|
sub generate_literal { |
592
|
|
|
|
|
|
|
my($self, $value, $id) = @_; |
593
|
|
|
|
|
|
|
|
594
|
|
|
|
|
|
|
$id = $value if(not defined $id); |
595
|
|
|
|
|
|
|
my $literal = Text::Xslate::Symbol->new(arity => 'literal', id => $id); |
596
|
|
|
|
|
|
|
$literal->value($value) if defined $value; |
597
|
|
|
|
|
|
|
$literal; |
598
|
|
|
|
|
|
|
} |
599
|
|
|
|
|
|
|
|
600
|
|
|
|
|
|
|
sub generate_vars { |
601
|
|
|
|
|
|
|
my($self, $name) = @_; |
602
|
|
|
|
|
|
|
|
603
|
|
|
|
|
|
|
Text::Xslate::Symbol->new(arity => 'vars', id => $name); |
604
|
|
|
|
|
|
|
} |
605
|
|
|
|
|
|
|
|
606
|
|
|
|
|
|
|
sub generate_variable { |
607
|
|
|
|
|
|
|
my($self, $name) = @_; |
608
|
|
|
|
|
|
|
|
609
|
|
|
|
|
|
|
Text::Xslate::Symbol->new(arity => 'variable', id => $name); |
610
|
|
|
|
|
|
|
} |
611
|
|
|
|
|
|
|
|
612
|
|
|
|
|
|
|
sub generate_name { |
613
|
|
|
|
|
|
|
my($self, $name) = @_; |
614
|
|
|
|
|
|
|
|
615
|
|
|
|
|
|
|
Text::Xslate::Symbol->new(arity => 'name', id => $name); |
616
|
|
|
|
|
|
|
} |
617
|
|
|
|
|
|
|
|
618
|
|
|
|
|
|
|
sub generate_field { |
619
|
|
|
|
|
|
|
my($self, $id, $first, $second) = @_; |
620
|
|
|
|
|
|
|
|
621
|
|
|
|
|
|
|
Text::Xslate::Symbol->new(arity => 'field', id => $id, first => $first, second => $second); |
622
|
|
|
|
|
|
|
} |
623
|
|
|
|
|
|
|
|
624
|
|
|
|
|
|
|
sub generate_unary { |
625
|
|
|
|
|
|
|
my($self, $id, $expr) = @_; |
626
|
|
|
|
|
|
|
|
627
|
|
|
|
|
|
|
Text::Xslate::Symbol->new(arity => 'unary', id => $id, first => $expr); |
628
|
|
|
|
|
|
|
} |
629
|
|
|
|
|
|
|
|
630
|
|
|
|
|
|
|
sub generate_call { |
631
|
|
|
|
|
|
|
my($self, $name, $args) = @_; |
632
|
|
|
|
|
|
|
|
633
|
|
|
|
|
|
|
Text::Xslate::Symbol->new(arity => 'call', id => '(', first => $self->generate_name($name), second => $args); |
634
|
|
|
|
|
|
|
} |
635
|
|
|
|
|
|
|
|
636
|
|
|
|
|
|
|
sub generate_methodcall { |
637
|
|
|
|
|
|
|
my($self, $name, $first, $second, @other_args) = @_; |
638
|
|
|
|
|
|
|
|
639
|
|
|
|
|
|
|
Text::Xslate::Symbol->new(arity => 'methodcall', id => $name, first => $first, second => $second, third => \@other_args); |
640
|
|
|
|
|
|
|
} |
641
|
|
|
|
|
|
|
|
642
|
|
|
|
|
|
|
|
643
|
|
|
|
|
|
|
|
644
|
|
|
|
|
|
|
sub generate_binary { |
645
|
|
|
|
|
|
|
my($self, $id, $first, $second) = @_; |
646
|
|
|
|
|
|
|
Text::Xslate::Symbol->new( |
647
|
|
|
|
|
|
|
arity => 'binary', |
648
|
|
|
|
|
|
|
id => $id, |
649
|
|
|
|
|
|
|
first => $first, |
650
|
|
|
|
|
|
|
second => $second |
651
|
|
|
|
|
|
|
); |
652
|
|
|
|
|
|
|
} |
653
|
|
|
|
|
|
|
|
654
|
|
|
|
|
|
|
sub generate_if { |
655
|
|
|
|
|
|
|
my($self, $id, $first, $second) = @_; |
656
|
|
|
|
|
|
|
|
657
|
|
|
|
|
|
|
Text::Xslate::Symbol->new(arity => 'if', id => $id, first => $first, second => $second); |
658
|
|
|
|
|
|
|
} |
659
|
|
|
|
|
|
|
|
660
|
|
|
|
|
|
|
sub generate_for { |
661
|
|
|
|
|
|
|
my($self, $first) = @_; |
662
|
|
|
|
|
|
|
|
663
|
|
|
|
|
|
|
Text::Xslate::Symbol->new(arity => 'for', id => 'for', first => $first); |
664
|
|
|
|
|
|
|
} |
665
|
|
|
|
|
|
|
|
666
|
|
|
|
|
|
|
sub generate_iterator { |
667
|
|
|
|
|
|
|
my($self, $iterator_name, $item_name) = @_; |
668
|
|
|
|
|
|
|
|
669
|
|
|
|
|
|
|
Text::Xslate::Symbol->new( |
670
|
|
|
|
|
|
|
arity => 'iterator', |
671
|
|
|
|
|
|
|
id => $item_name, |
672
|
|
|
|
|
|
|
first => $self->generate_variable($item_name), |
673
|
|
|
|
|
|
|
); |
674
|
|
|
|
|
|
|
} |
675
|
|
|
|
|
|
|
|
676
|
|
|
|
|
|
|
sub generate_iterator_max_index { |
677
|
|
|
|
|
|
|
my($self, $iterator_name, $item_name) = @_; |
678
|
|
|
|
|
|
|
|
679
|
|
|
|
|
|
|
$self->generate_unary('max_index', $self->generate_iterator_body($iterator_name, $item_name)); |
680
|
|
|
|
|
|
|
} |
681
|
|
|
|
|
|
|
|
682
|
|
|
|
|
|
|
sub generate_iterator_body { |
683
|
|
|
|
|
|
|
my($self, $iterator_name, $item_name) = @_; |
684
|
|
|
|
|
|
|
|
685
|
|
|
|
|
|
|
Text::Xslate::Symbol->new(arity => 'iterator_body', id => $iterator_name, |
686
|
|
|
|
|
|
|
first => $self->generate_iterator($iterator_name, $item_name), |
687
|
|
|
|
|
|
|
second => $self->generate_iterator($iterator_name, $item_name), |
688
|
|
|
|
|
|
|
); |
689
|
|
|
|
|
|
|
} |
690
|
|
|
|
|
|
|
|
691
|
|
|
|
|
|
|
sub generate_iterator_size { |
692
|
|
|
|
|
|
|
my($self, $iterator_name, $item_name) = @_; |
693
|
|
|
|
|
|
|
|
694
|
|
|
|
|
|
|
Text::Xslate::Symbol->new(arity => 'iterator_body', id => $iterator_name, |
695
|
|
|
|
|
|
|
first => $self->generate_iterator($iterator_name, $item_name), |
696
|
|
|
|
|
|
|
second => $self->generate_iterator($iterator_name, $item_name), |
697
|
|
|
|
|
|
|
); |
698
|
|
|
|
|
|
|
} |
699
|
|
|
|
|
|
|
|
700
|
|
|
|
|
|
|
no Any::Moose; |
701
|
|
|
|
|
|
|
__PACKAGE__->meta->make_immutable; |
702
|
|
|
|
|
|
|
|
703
|
|
|
|
|
|
|
=head1 NAME |
704
|
|
|
|
|
|
|
|
705
|
|
|
|
|
|
|
Text::Xslate::Syntax::HTMLTemplate - An alternative syntax compatible with HTML Template |
706
|
|
|
|
|
|
|
|
707
|
|
|
|
|
|
|
=head1 SYNOPSIS |
708
|
|
|
|
|
|
|
|
709
|
|
|
|
|
|
|
use Text::Xslate; |
710
|
|
|
|
|
|
|
|
711
|
|
|
|
|
|
|
local $Text::Xslate::Syntax::HTP::before_parse_hook = sub { |
712
|
|
|
|
|
|
|
my $parser = shift; |
713
|
|
|
|
|
|
|
$parser->use_global_vars(1); |
714
|
|
|
|
|
|
|
$parser->use_loop_context_vars(1); |
715
|
|
|
|
|
|
|
$parser->use_has_value(1); |
716
|
|
|
|
|
|
|
}; |
717
|
|
|
|
|
|
|
my $tx = Text::Xslate->new(syntax => 'HTMLTemplate', compiler => 'Text::Xslate::Compiler::HTMLTemplate', |
718
|
|
|
|
|
|
|
function => { |
719
|
|
|
|
|
|
|
__choise_global_var__ => \&Text::Xslate::Syntax::HTMLTemplate::default_choise_global_var, |
720
|
|
|
|
|
|
|
__has_value__ => \&Text::Xslate::Syntax::HTMLTemplate::default_has_value, |
721
|
|
|
|
|
|
|
} |
722
|
|
|
|
|
|
|
); |
723
|
|
|
|
|
|
|
|
724
|
|
|
|
|
|
|
print $tx->render('hello.tx'); |
725
|
|
|
|
|
|
|
|
726
|
|
|
|
|
|
|
For Migration test: |
727
|
|
|
|
|
|
|
|
728
|
|
|
|
|
|
|
Text::Xslate::Syntax::HTMLTemplate::install_Xslate_as_HTMLTemplate(); |
729
|
|
|
|
|
|
|
my $htp = HTML::Template::Pro->new(...); |
730
|
|
|
|
|
|
|
... |
731
|
|
|
|
|
|
|
my $output = $htp->output(); # generated by xsalte engine; |
732
|
|
|
|
|
|
|
my $output_htp = $htp->output_original_HTMLTemplate(); # generated by HTML::Template::Pro; |
733
|
|
|
|
|
|
|
diff($output, $output_htp); |
734
|
|
|
|
|
|
|
|
735
|
|
|
|
|
|
|
=head1 DESCRIPTION |
736
|
|
|
|
|
|
|
|
737
|
|
|
|
|
|
|
B is a parser for Text::Xslate. |
738
|
|
|
|
|
|
|
It parse HTML::Template syntax template. |
739
|
|
|
|
|
|
|
|
740
|
|
|
|
|
|
|
=head1 OPTIONS |
741
|
|
|
|
|
|
|
|
742
|
|
|
|
|
|
|
=over |
743
|
|
|
|
|
|
|
|
744
|
|
|
|
|
|
|
=item C |
745
|
|
|
|
|
|
|
|
746
|
|
|
|
|
|
|
same as global_vars option of HTML::Template. |
747
|
|
|
|
|
|
|
you have to register function to handle that. |
748
|
|
|
|
|
|
|
|
749
|
|
|
|
|
|
|
=item C |
750
|
|
|
|
|
|
|
|
751
|
|
|
|
|
|
|
same as loop_context_vars option of HTML::Template. |
752
|
|
|
|
|
|
|
|
753
|
|
|
|
|
|
|
=item C |
754
|
|
|
|
|
|
|
|
755
|
|
|
|
|
|
|
HTML::Template treats empty array referense as Flase. |
756
|
|
|
|
|
|
|
But Xslate treats empty array referense as True. |
757
|
|
|
|
|
|
|
when use_has_value is seted, Syntax::HTMLTemplate |
758
|
|
|
|
|
|
|
you have to register function to handle that. |
759
|
|
|
|
|
|
|
|
760
|
|
|
|
|
|
|
=item C |
761
|
|
|
|
|
|
|
|
762
|
|
|
|
|
|
|
Method that determine var is escaped or not. |
763
|
|
|
|
|
|
|
For temporary use while migration. |
764
|
|
|
|
|
|
|
You should use Text::Xslate::mark_raw(). |
765
|
|
|
|
|
|
|
|
766
|
|
|
|
|
|
|
=back |
767
|
|
|
|
|
|
|
|
768
|
|
|
|
|
|
|
=head1 AUTHOR |
769
|
|
|
|
|
|
|
|
770
|
|
|
|
|
|
|
Shigeki Morimoto EShigeki(at)Morimo.toE |
771
|
|
|
|
|
|
|
|
772
|
|
|
|
|
|
|
=head1 LICENSE AND COPYRIGHT |
773
|
|
|
|
|
|
|
|
774
|
|
|
|
|
|
|
Copyright (c) 2011, Shigeki, Morimoto. All rights reserved. |
775
|
|
|
|
|
|
|
|
776
|
|
|
|
|
|
|
This library is free software; you can redistribute it and/or modify |
777
|
|
|
|
|
|
|
it under the same terms as Perl itself. |