line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Mojolicious::Renderer; |
2
|
51
|
|
|
1519
|
|
421
|
use Mojo::Base -base; |
|
51
|
|
|
|
|
160
|
|
|
51
|
|
|
|
|
399
|
|
3
|
|
|
|
|
|
|
|
4
|
51
|
|
|
984
|
|
468
|
use Carp qw(croak); |
|
51
|
|
|
|
|
179
|
|
|
51
|
|
|
|
|
2839
|
|
5
|
51
|
|
|
984
|
|
23871
|
use Mojo::Cache; |
|
51
|
|
|
|
|
173
|
|
|
51
|
|
|
|
|
481
|
|
6
|
51
|
|
|
482
|
|
474
|
use Mojo::DynamicMethods; |
|
51
|
|
|
|
|
158
|
|
|
51
|
|
|
|
|
348
|
|
7
|
51
|
|
|
482
|
|
371
|
use Mojo::File qw(curfile path); |
|
51
|
|
|
|
|
218
|
|
|
51
|
|
|
|
|
2749
|
|
8
|
51
|
|
|
482
|
|
360
|
use Mojo::JSON qw(encode_json); |
|
51
|
|
|
|
|
139
|
|
|
51
|
|
|
|
|
2234
|
|
9
|
51
|
|
|
482
|
|
389
|
use Mojo::Loader qw(data_section); |
|
51
|
|
|
|
|
182
|
|
|
51
|
|
|
|
|
2418
|
|
10
|
51
|
|
|
482
|
|
418
|
use Mojo::Util qw(decamelize deprecated encode gzip md5_sum monkey_patch); |
|
51
|
|
|
|
|
182
|
|
|
51
|
|
|
|
|
166808
|
|
11
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
has cache => sub { Mojo::Cache->new }; |
13
|
|
|
|
|
|
|
has classes => sub { ['main'] }; |
14
|
|
|
|
|
|
|
has compress => 1; |
15
|
|
|
|
|
|
|
has default_format => 'html'; |
16
|
|
|
|
|
|
|
has 'default_handler'; |
17
|
|
|
|
|
|
|
has encoding => 'UTF-8'; |
18
|
|
|
|
|
|
|
has [qw(handlers helpers)] => sub { {} }; |
19
|
|
|
|
|
|
|
has min_compress_size => 860; |
20
|
|
|
|
|
|
|
has paths => sub { [] }; |
21
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
# Bundled templates |
23
|
|
|
|
|
|
|
my $TEMPLATES = curfile->sibling('resources', 'templates'); |
24
|
|
|
|
|
|
|
|
25
|
38
|
|
|
38
|
|
20168
|
sub DESTROY { Mojo::Util::_teardown($_) for @{shift->{namespaces}} } |
|
38
|
|
|
|
|
305
|
|
26
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
sub accepts { |
28
|
112
|
|
|
112
|
1
|
228
|
my ($self, $c) = (shift, shift); |
29
|
|
|
|
|
|
|
|
30
|
|
|
|
|
|
|
# DEPRECATED! |
31
|
112
|
|
|
|
|
279
|
my $req = $c->req; |
32
|
112
|
|
|
|
|
435
|
my $param = $req->param('format'); |
33
|
112
|
50
|
|
|
|
313
|
deprecated 'The ?format=* parameter is deprecated in favor of ?_format=* for content negotiation' if defined $param; |
34
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
# List representations |
36
|
112
|
|
100
|
|
|
376
|
my $fmt = $param // $req->param('_format') || $c->stash->{format}; |
37
|
112
|
100
|
|
|
|
343
|
my @exts = $fmt ? ($fmt) : (); |
38
|
112
|
|
|
|
|
181
|
push @exts, @{$c->app->types->detect($req->headers->accept)}; |
|
112
|
|
|
|
|
350
|
|
39
|
112
|
100
|
|
|
|
634
|
return \@exts unless @_; |
40
|
|
|
|
|
|
|
|
41
|
|
|
|
|
|
|
# Find best representation |
42
|
29
|
|
100
|
|
|
94
|
for my $ext (@exts) { $ext eq $_ and return $ext for @_ } |
|
13
|
|
|
|
|
102
|
|
43
|
22
|
100
|
|
|
|
161
|
return @exts ? undef : shift; |
44
|
|
|
|
|
|
|
} |
45
|
|
|
|
|
|
|
|
46
|
233
|
50
|
|
233
|
1
|
900
|
sub add_handler { $_[0]->handlers->{$_[1]} = $_[2] and return $_[0] } |
47
|
|
|
|
|
|
|
|
48
|
|
|
|
|
|
|
sub add_helper { |
49
|
9188
|
|
|
9188
|
1
|
18419
|
my ($self, $name, $cb) = @_; |
50
|
|
|
|
|
|
|
|
51
|
9188
|
|
|
|
|
18430
|
$self->helpers->{$name} = $cb; |
52
|
9188
|
|
|
|
|
17209
|
delete $self->{proxy}; |
53
|
9188
|
100
|
|
|
|
29596
|
$cb = $self->get_helper($name) if $name =~ s/\..*$//; |
54
|
9188
|
|
|
|
|
24326
|
Mojo::DynamicMethods::register $_, $self, $name, $cb for qw(Mojolicious Mojolicious::Controller); |
55
|
|
|
|
|
|
|
|
56
|
9188
|
|
|
|
|
30561
|
return $self; |
57
|
|
|
|
|
|
|
} |
58
|
|
|
|
|
|
|
|
59
|
|
|
|
|
|
|
sub get_data_template { |
60
|
342
|
|
|
342
|
1
|
988
|
my ($self, $options) = @_; |
61
|
342
|
50
|
|
|
|
923
|
return undef unless my $template = $self->template_name($options); |
62
|
342
|
|
|
|
|
2529
|
return data_section $self->{index}{$template}, $template; |
63
|
|
|
|
|
|
|
} |
64
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
sub get_helper { |
66
|
24691
|
|
|
24691
|
1
|
55407
|
my ($self, $name) = @_; |
67
|
|
|
|
|
|
|
|
68
|
24691
|
100
|
100
|
|
|
81698
|
if (my $h = $self->{proxy}{$name} || $self->helpers->{$name}) { return $h } |
|
22341
|
|
|
|
|
47604
|
|
69
|
|
|
|
|
|
|
|
70
|
2350
|
|
|
|
|
7528
|
my $found; |
71
|
2350
|
|
|
|
|
13280
|
my $class = 'Mojolicious::Renderer::Helpers::' . md5_sum "$name:$self"; |
72
|
2350
|
100
|
|
|
|
25117
|
my $re = length $name ? qr/^(\Q$name\E\.([^.]+))/ : qr/^(([^.]+))/; |
73
|
2350
|
|
|
|
|
4645
|
for my $key (keys %{$self->helpers}) { |
|
2350
|
|
|
|
|
5322
|
|
74
|
106919
|
100
|
|
|
|
307507
|
$key =~ $re ? ($found, my $method) = (1, $2) : next; |
75
|
17898
|
|
|
|
|
39640
|
my $sub = $self->get_helper($1); |
76
|
17898
|
|
|
5887
|
|
73435
|
monkey_patch $class, $method => sub { ${shift()}->$sub(@_) }; |
|
5887
|
|
|
5541
|
|
8743
|
|
|
5887
|
|
|
5541
|
|
19356
|
|
|
|
|
|
6130
|
|
|
|
|
|
|
|
6043
|
|
|
|
|
|
|
|
6553
|
|
|
|
|
|
|
|
7088
|
|
|
|
|
|
|
|
7565
|
|
|
|
|
|
|
|
7478
|
|
|
|
|
|
|
|
7917
|
|
|
|
|
|
|
|
8381
|
|
|
|
|
|
|
|
8804
|
|
|
|
|
|
|
|
9306
|
|
|
|
|
|
|
|
9737
|
|
|
|
|
|
|
|
10168
|
|
|
|
|
|
|
|
10168
|
|
|
|
|
|
|
|
10599
|
|
|
|
|
|
|
|
11030
|
|
|
|
|
|
|
|
11030
|
|
|
|
|
|
|
|
11030
|
|
|
|
|
|
|
|
11461
|
|
|
|
|
|
|
|
11892
|
|
|
|
|
|
|
|
11461
|
|
|
|
|
|
|
|
13032
|
|
|
|
|
|
|
|
11515
|
|
|
|
|
|
|
|
10926
|
|
|
|
|
|
|
|
10503
|
|
|
|
|
|
|
|
10590
|
|
|
|
|
|
|
|
9993
|
|
|
|
|
|
|
|
10072
|
|
|
|
|
|
|
|
10105
|
|
|
|
|
|
|
|
10097
|
|
|
|
|
|
|
|
10222
|
|
|
|
|
|
|
|
9633
|
|
|
|
|
|
|
|
9641
|
|
|
|
|
|
|
|
9674
|
|
|
|
|
|
|
|
9666
|
|
|
|
|
|
|
|
10222
|
|
|
|
|
|
|
|
10064
|
|
|
|
|
|
|
|
11635
|
|
|
|
|
|
|
|
10590
|
|
|
|
|
|
|
|
10424
|
|
|
|
|
|
|
|
10557
|
|
|
|
|
|
|
|
9570
|
|
|
|
|
|
|
|
9624
|
|
|
|
|
|
|
|
9570
|
|
|
|
|
|
|
|
9624
|
|
|
|
|
|
|
|
9139
|
|
|
|
|
|
|
|
9139
|
|
|
|
|
|
|
|
9243
|
|
|
|
|
|
|
|
9666
|
|
|
|
|
|
|
|
9737
|
|
|
|
|
|
|
|
9737
|
|
|
|
|
|
|
|
10168
|
|
|
|
|
|
|
|
10653
|
|
|
|
|
|
|
|
10495
|
|
|
|
|
|
|
|
10557
|
|
|
|
|
|
|
|
10432
|
|
|
|
|
|
|
|
10863
|
|
|
|
|
|
|
|
10967
|
|
|
|
|
|
|
|
11390
|
|
|
|
|
|
|
|
11030
|
|
|
|
|
|
|
|
11030
|
|
|
|
|
|
|
|
10653
|
|
|
|
|
|
|
|
10064
|
|
|
|
|
|
|
|
9641
|
|
|
|
|
|
|
|
9674
|
|
|
|
|
|
|
|
10097
|
|
|
|
|
|
|
|
10653
|
|
|
|
|
|
|
|
10495
|
|
|
|
|
|
|
|
10934
|
|
|
|
|
|
|
|
10967
|
|
|
|
|
|
|
|
10959
|
|
|
|
|
|
|
|
10599
|
|
|
|
|
|
|
|
10599
|
|
|
|
|
|
|
|
10599
|
|
|
|
|
|
|
|
11084
|
|
|
|
|
|
|
|
10495
|
|
|
|
|
|
|
|
10503
|
|
|
|
|
|
|
|
10536
|
|
|
|
|
|
|
|
10582
|
|
|
|
|
|
|
|
10495
|
|
|
|
|
|
|
|
10503
|
|
|
|
|
|
|
|
10590
|
|
|
|
|
|
|
|
9993
|
|
|
|
|
|
|
|
10072
|
|
|
|
|
|
|
|
10159
|
|
|
|
|
|
|
|
9131
|
|
|
|
|
|
|
|
9210
|
|
|
|
|
|
|
|
9674
|
|
|
|
|
|
|
|
10097
|
|
|
|
|
|
|
|
10168
|
|
|
|
|
|
|
|
10168
|
|
|
|
|
|
|
|
10599
|
|
|
|
|
|
|
|
12593
|
|
|
|
|
|
|
|
12618
|
|
|
|
|
|
|
|
13049
|
|
|
|
|
|
|
|
13455
|
|
|
|
|
|
|
|
11892
|
|
|
|
|
|
|
|
11946
|
|
|
|
|
|
|
|
11788
|
|
|
|
|
|
|
|
11850
|
|
|
|
|
|
|
|
10432
|
|
|
|
|
|
|
|
10432
|
|
|
|
|
|
|
|
10536
|
|
|
|
|
|
|
|
10097
|
|
|
|
|
|
|
|
10168
|
|
|
|
|
|
|
|
10168
|
|
|
|
|
|
|
|
10168
|
|
|
|
|
|
|
|
10168
|
|
|
|
|
|
|
|
10168
|
|
|
|
|
|
|
|
2021
|
|
|
|
77
|
|
|
|
|
|
|
} |
78
|
|
|
|
|
|
|
|
79
|
2350
|
50
|
|
|
|
9733
|
$found ? push @{$self->{namespaces}}, $class : return undef; |
|
2350
|
|
|
|
|
6295
|
|
80
|
2350
|
|
|
10259
|
|
12473
|
return $self->{proxy}{$name} = sub { bless \(my $dummy = shift), $class }; |
|
5632
|
|
|
|
|
26162
|
|
81
|
|
|
|
|
|
|
} |
82
|
|
|
|
|
|
|
|
83
|
|
|
|
|
|
|
sub render { |
84
|
973
|
|
|
5496
|
1
|
2223
|
my ($self, $c) = @_; |
85
|
|
|
|
|
|
|
|
86
|
973
|
|
|
|
|
2309
|
my $stash = $c->stash; |
87
|
|
|
|
|
|
|
my $options = { |
88
|
|
|
|
|
|
|
encoding => $self->encoding, |
89
|
|
|
|
|
|
|
handler => $stash->{handler}, |
90
|
|
|
|
|
|
|
template => delete $stash->{template}, |
91
|
|
|
|
|
|
|
variant => $stash->{variant} |
92
|
973
|
|
|
|
|
3391
|
}; |
93
|
973
|
|
|
|
|
2674
|
my $inline = $options->{inline} = delete $stash->{inline}; |
94
|
973
|
100
|
66
|
|
|
2610
|
$options->{handler} //= $self->default_handler if defined $inline; |
95
|
973
|
|
66
|
|
|
3894
|
$options->{format} = $stash->{format} || $self->default_format; |
96
|
|
|
|
|
|
|
|
97
|
|
|
|
|
|
|
# Data |
98
|
973
|
100
|
|
|
|
2823
|
return delete $stash->{data}, $options->{format} if defined $stash->{data}; |
99
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
# Text |
101
|
904
|
100
|
|
|
|
2903
|
return _maybe($options->{encoding}, delete $stash->{text}), $options->{format} if defined $stash->{text}; |
102
|
|
|
|
|
|
|
|
103
|
|
|
|
|
|
|
# JSON |
104
|
597
|
100
|
|
|
|
1765
|
return encode_json(delete $stash->{json}), 'json' if exists $stash->{json}; |
105
|
|
|
|
|
|
|
|
106
|
|
|
|
|
|
|
# Template or templateless handler |
107
|
546
|
|
100
|
|
|
1970
|
$options->{template} //= $self->template_for($c); |
108
|
546
|
100
|
|
|
|
1949
|
return () unless $self->_render_template($c, \my $output, $options); |
109
|
|
|
|
|
|
|
|
110
|
|
|
|
|
|
|
# Inheritance |
111
|
337
|
|
100
|
|
|
1957
|
my $content = $stash->{'mojo.content'} //= {}; |
112
|
337
|
100
|
100
|
|
|
2059
|
local $content->{content} = $output =~ /\S/ ? $output : undef if $stash->{extends} || $stash->{layout}; |
|
|
100
|
|
|
|
|
|
113
|
337
|
|
100
|
|
|
1129
|
while ((my $next = _next($stash)) && !defined $inline) { |
114
|
44
|
|
|
|
|
153
|
@$options{qw(handler template)} = ($stash->{handler}, $next); |
115
|
44
|
|
66
|
|
|
173
|
$options->{format} = $stash->{format} || $self->default_format; |
116
|
44
|
50
|
|
|
|
184
|
if ($self->_render_template($c, \my $tmp, $options)) { $output = $tmp } |
|
44
|
|
|
|
|
122
|
|
117
|
44
|
100
|
66
|
|
|
360
|
$content->{content} //= $output if $output =~ /\S/; |
118
|
|
|
|
|
|
|
} |
119
|
|
|
|
|
|
|
|
120
|
337
|
100
|
|
|
|
1032
|
return $output if $stash->{'mojo.string'}; |
121
|
312
|
|
|
|
|
959
|
return _maybe($options->{encoding}, $output), $options->{format}; |
122
|
|
|
|
|
|
|
} |
123
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
sub respond { |
125
|
739
|
|
|
5191
|
1
|
3510
|
my ($self, $c, $output, $format, $status) = @_; |
126
|
|
|
|
|
|
|
|
127
|
739
|
50
|
|
|
|
2104
|
croak 'A response has already been rendered' if $c->stash->{'mojo.respond'}++; |
128
|
|
|
|
|
|
|
|
129
|
|
|
|
|
|
|
# Gzip compression |
130
|
739
|
|
|
|
|
2449
|
my $res = $c->res; |
131
|
739
|
100
|
66
|
|
|
2558
|
if ($self->compress && length($output) >= $self->min_compress_size) { |
132
|
52
|
|
|
|
|
291
|
my $headers = $res->headers; |
133
|
52
|
|
|
|
|
427
|
$headers->append(Vary => 'Accept-Encoding'); |
134
|
52
|
|
100
|
|
|
235
|
my $gzip = ($c->req->headers->accept_encoding // '') =~ /gzip/i; |
135
|
52
|
100
|
66
|
|
|
345
|
if ($gzip && !$headers->content_encoding) { |
136
|
49
|
|
|
|
|
212
|
$headers->content_encoding('gzip'); |
137
|
49
|
|
|
|
|
314
|
$output = gzip $output; |
138
|
|
|
|
|
|
|
} |
139
|
|
|
|
|
|
|
} |
140
|
|
|
|
|
|
|
|
141
|
739
|
|
|
|
|
3545
|
$res->body($output); |
142
|
739
|
|
|
|
|
2255
|
$c->app->types->content_type($c, {ext => $format}); |
143
|
739
|
|
|
|
|
3268
|
return !!$c->rendered($status); |
144
|
|
|
|
|
|
|
} |
145
|
|
|
|
|
|
|
|
146
|
|
|
|
|
|
|
sub template_for { |
147
|
209
|
|
|
4590
|
1
|
541
|
my ($self, $c) = @_; |
148
|
|
|
|
|
|
|
|
149
|
|
|
|
|
|
|
# Normal default template |
150
|
209
|
|
|
|
|
640
|
my $stash = $c->stash; |
151
|
209
|
|
|
|
|
770
|
my ($controller, $action) = @$stash{qw(controller action)}; |
152
|
209
|
100
|
100
|
|
|
725
|
return join '/', split(/-/, decamelize $controller), $action if $controller && $action; |
153
|
|
|
|
|
|
|
|
154
|
|
|
|
|
|
|
# Try the route name if we don't have controller and action |
155
|
205
|
100
|
|
|
|
631
|
return undef unless my $route = $c->match->endpoint; |
156
|
202
|
|
|
|
|
840
|
return $route->name; |
157
|
|
|
|
|
|
|
} |
158
|
|
|
|
|
|
|
|
159
|
|
|
|
|
|
|
sub template_handler { |
160
|
464
|
|
|
4774
|
1
|
982
|
my ($self, $options) = @_; |
161
|
464
|
100
|
|
|
|
1290
|
return undef unless my $file = $self->template_name($options); |
162
|
463
|
100
|
|
|
|
2227
|
return $self->default_handler unless my $handlers = $self->{templates}{$file}; |
163
|
275
|
|
|
|
|
1186
|
return $handlers->[0]; |
164
|
|
|
|
|
|
|
} |
165
|
|
|
|
|
|
|
|
166
|
|
|
|
|
|
|
sub template_name { |
167
|
2061
|
|
|
5940
|
1
|
3581
|
my ($self, $options) = @_; |
168
|
|
|
|
|
|
|
|
169
|
2061
|
100
|
|
|
|
5073
|
return undef unless defined(my $template = $options->{template}); |
170
|
2060
|
50
|
|
|
|
4354
|
return undef unless my $format = $options->{format}; |
171
|
2060
|
|
|
|
|
3924
|
$template .= ".$format"; |
172
|
|
|
|
|
|
|
|
173
|
2060
|
100
|
|
|
|
4443
|
$self->warmup unless $self->{templates}; |
174
|
|
|
|
|
|
|
|
175
|
|
|
|
|
|
|
# Variants |
176
|
2060
|
|
|
|
|
3469
|
my $handler = $options->{handler}; |
177
|
2060
|
100
|
|
|
|
4258
|
if (defined(my $variant = $options->{variant})) { |
178
|
21
|
|
|
|
|
55
|
$variant = "$template+$variant"; |
179
|
21
|
|
100
|
|
|
80
|
my $handlers = $self->{templates}{$variant} // []; |
180
|
21
|
100
|
100
|
|
|
104
|
$template = $variant if @$handlers && !defined $handler || grep { $_ eq $handler } @$handlers; |
|
10
|
|
100
|
|
|
42
|
|
181
|
|
|
|
|
|
|
} |
182
|
|
|
|
|
|
|
|
183
|
2060
|
100
|
|
|
|
9526
|
return defined $handler ? "$template.$handler" : $template; |
184
|
|
|
|
|
|
|
} |
185
|
|
|
|
|
|
|
|
186
|
|
|
|
|
|
|
sub template_path { |
187
|
394
|
|
|
3842
|
1
|
939
|
my ($self, $options) = @_; |
188
|
394
|
50
|
|
|
|
883
|
return undef unless my $name = $self->template_name($options); |
189
|
394
|
|
|
|
|
1797
|
my @parts = split /\//, $name; |
190
|
394
|
|
100
|
|
|
881
|
-r and return $_ for map { path($_, @parts)->to_string } @{$self->paths}, $TEMPLATES; |
|
792
|
|
|
|
|
2260
|
|
|
394
|
|
|
|
|
1390
|
|
191
|
342
|
|
|
|
|
3621
|
return undef; |
192
|
|
|
|
|
|
|
} |
193
|
|
|
|
|
|
|
|
194
|
|
|
|
|
|
|
sub warmup { |
195
|
56
|
|
|
2642
|
1
|
196
|
my $self = shift; |
196
|
|
|
|
|
|
|
|
197
|
56
|
|
|
|
|
519
|
my ($index, $templates) = @$self{qw(index templates)} = ({}, {}); |
198
|
|
|
|
|
|
|
|
199
|
|
|
|
|
|
|
# Handlers for templates |
200
|
56
|
|
|
|
|
159
|
for my $path (@{$self->paths}, $TEMPLATES) { |
|
56
|
|
|
|
|
261
|
|
201
|
783
|
|
|
|
|
6191
|
s/\.(\w+)$// and push @{$templates->{$_}}, $1 |
202
|
113
|
|
33
|
2938
|
|
491
|
for path($path)->list_tree->map(sub { join '/', @{$_->to_rel($path)} })->each; |
|
783
|
|
|
|
|
1165
|
|
|
783
|
|
|
|
|
1736
|
|
203
|
|
|
|
|
|
|
} |
204
|
|
|
|
|
|
|
|
205
|
|
|
|
|
|
|
# Handlers and classes for DATA templates |
206
|
56
|
|
|
|
|
189
|
for my $class (reverse @{$self->classes}) { |
|
56
|
|
|
|
|
349
|
|
207
|
82
|
|
|
|
|
224
|
$index->{$_} = $class for my @keys = sort keys %{data_section $class}; |
|
82
|
|
|
|
|
335
|
|
208
|
82
|
|
66
|
|
|
921
|
s/\.(\w+)$// and unshift @{$templates->{$_}}, $1 for reverse @keys; |
|
206
|
|
|
|
|
1559
|
|
209
|
|
|
|
|
|
|
} |
210
|
|
|
|
|
|
|
} |
211
|
|
|
|
|
|
|
|
212
|
619
|
100
|
|
1912
|
|
2561
|
sub _maybe { $_[0] ? encode @_ : $_[1] } |
213
|
|
|
|
|
|
|
|
214
|
|
|
|
|
|
|
sub _next { |
215
|
381
|
|
|
1243
|
|
695
|
my $stash = shift; |
216
|
381
|
100
|
|
|
|
1027
|
return delete $stash->{extends} if $stash->{extends}; |
217
|
368
|
100
|
|
|
|
1829
|
return undef unless my $layout = delete $stash->{layout}; |
218
|
33
|
|
|
|
|
217
|
return join '/', 'layouts', $layout; |
219
|
|
|
|
|
|
|
} |
220
|
|
|
|
|
|
|
|
221
|
|
|
|
|
|
|
sub _render_template { |
222
|
590
|
|
|
1021
|
|
1482
|
my ($self, $c, $output, $options) = @_; |
223
|
|
|
|
|
|
|
|
224
|
590
|
|
100
|
|
|
2318
|
my $handler = $options->{handler} ||= $self->template_handler($options); |
225
|
590
|
100
|
|
|
|
1491
|
return undef unless $handler; |
226
|
|
|
|
|
|
|
$c->helpers->log->error(qq{No handler for "$handler" found}) and return undef |
227
|
589
|
50
|
0
|
|
|
1598
|
unless my $renderer = $self->handlers->{$handler}; |
228
|
|
|
|
|
|
|
|
229
|
589
|
|
|
|
|
2567
|
$renderer->($self, $c, $output, $options); |
230
|
569
|
100
|
|
|
|
3570
|
return 1 if defined $$output; |
231
|
|
|
|
|
|
|
} |
232
|
|
|
|
|
|
|
|
233
|
|
|
|
|
|
|
1; |
234
|
|
|
|
|
|
|
|
235
|
|
|
|
|
|
|
=encoding utf8 |
236
|
|
|
|
|
|
|
|
237
|
|
|
|
|
|
|
=head1 NAME |
238
|
|
|
|
|
|
|
|
239
|
|
|
|
|
|
|
Mojolicious::Renderer - Generate dynamic content |
240
|
|
|
|
|
|
|
|
241
|
|
|
|
|
|
|
=head1 SYNOPSIS |
242
|
|
|
|
|
|
|
|
243
|
|
|
|
|
|
|
use Mojolicious::Renderer; |
244
|
|
|
|
|
|
|
|
245
|
|
|
|
|
|
|
my $renderer = Mojolicious::Renderer->new; |
246
|
|
|
|
|
|
|
push @{$renderer->classes}, 'MyApp::Controller::Foo'; |
247
|
|
|
|
|
|
|
push @{$renderer->paths}, '/home/sri/templates'; |
248
|
|
|
|
|
|
|
|
249
|
|
|
|
|
|
|
=head1 DESCRIPTION |
250
|
|
|
|
|
|
|
|
251
|
|
|
|
|
|
|
L is the standard L renderer. |
252
|
|
|
|
|
|
|
|
253
|
|
|
|
|
|
|
See L for more. |
254
|
|
|
|
|
|
|
|
255
|
|
|
|
|
|
|
=head1 ATTRIBUTES |
256
|
|
|
|
|
|
|
|
257
|
|
|
|
|
|
|
L implements the following attributes. |
258
|
|
|
|
|
|
|
|
259
|
|
|
|
|
|
|
=head2 cache |
260
|
|
|
|
|
|
|
|
261
|
|
|
|
|
|
|
my $cache = $renderer->cache; |
262
|
|
|
|
|
|
|
$renderer = $renderer->cache(Mojo::Cache->new); |
263
|
|
|
|
|
|
|
|
264
|
|
|
|
|
|
|
Renderer cache, defaults to a L object. |
265
|
|
|
|
|
|
|
|
266
|
|
|
|
|
|
|
=head2 classes |
267
|
|
|
|
|
|
|
|
268
|
|
|
|
|
|
|
my $classes = $renderer->classes; |
269
|
|
|
|
|
|
|
$renderer = $renderer->classes(['main']); |
270
|
|
|
|
|
|
|
|
271
|
|
|
|
|
|
|
Classes to use for finding templates in C sections with L, first one has the highest precedence, |
272
|
|
|
|
|
|
|
defaults to C. Only files with exactly two extensions will be used, like C. Note that for |
273
|
|
|
|
|
|
|
templates to be detected, these classes need to have already been loaded and added before L"warmup"> is called, which |
274
|
|
|
|
|
|
|
usually happens automatically during application startup. |
275
|
|
|
|
|
|
|
|
276
|
|
|
|
|
|
|
# Add another class with templates in DATA section |
277
|
|
|
|
|
|
|
push @{$renderer->classes}, 'Mojolicious::Plugin::Fun'; |
278
|
|
|
|
|
|
|
|
279
|
|
|
|
|
|
|
# Add another class with templates in DATA section and higher precedence |
280
|
|
|
|
|
|
|
unshift @{$renderer->classes}, 'Mojolicious::Plugin::MoreFun'; |
281
|
|
|
|
|
|
|
|
282
|
|
|
|
|
|
|
=head2 compress |
283
|
|
|
|
|
|
|
|
284
|
|
|
|
|
|
|
my $bool = $renderer->compress; |
285
|
|
|
|
|
|
|
$renderer = $renderer->compress($bool); |
286
|
|
|
|
|
|
|
|
287
|
|
|
|
|
|
|
Try to negotiate compression for dynamically generated response content and C compress it automatically, defaults |
288
|
|
|
|
|
|
|
to true. |
289
|
|
|
|
|
|
|
|
290
|
|
|
|
|
|
|
=head2 default_format |
291
|
|
|
|
|
|
|
|
292
|
|
|
|
|
|
|
my $default = $renderer->default_format; |
293
|
|
|
|
|
|
|
$renderer = $renderer->default_format('html'); |
294
|
|
|
|
|
|
|
|
295
|
|
|
|
|
|
|
The default format to render if C is not set in the stash, defaults to C. Note that changing the default |
296
|
|
|
|
|
|
|
away from C is not recommended, as it has the potential to break, for example, plugins with bundled templates. |
297
|
|
|
|
|
|
|
|
298
|
|
|
|
|
|
|
=head2 default_handler |
299
|
|
|
|
|
|
|
|
300
|
|
|
|
|
|
|
my $default = $renderer->default_handler; |
301
|
|
|
|
|
|
|
$renderer = $renderer->default_handler('ep'); |
302
|
|
|
|
|
|
|
|
303
|
|
|
|
|
|
|
The default template handler to use for rendering in cases where auto-detection doesn't work, like for C |
304
|
|
|
|
|
|
|
templates. |
305
|
|
|
|
|
|
|
|
306
|
|
|
|
|
|
|
=head2 encoding |
307
|
|
|
|
|
|
|
|
308
|
|
|
|
|
|
|
my $encoding = $renderer->encoding; |
309
|
|
|
|
|
|
|
$renderer = $renderer->encoding('koi8-r'); |
310
|
|
|
|
|
|
|
|
311
|
|
|
|
|
|
|
Will encode generated content if set, defaults to C. Note that many renderers such as |
312
|
|
|
|
|
|
|
L also use this value to determine if template files should be decoded before |
313
|
|
|
|
|
|
|
processing. |
314
|
|
|
|
|
|
|
|
315
|
|
|
|
|
|
|
=head2 handlers |
316
|
|
|
|
|
|
|
|
317
|
|
|
|
|
|
|
my $handlers = $renderer->handlers; |
318
|
|
|
|
|
|
|
$renderer = $renderer->handlers({epl => sub {...}}); |
319
|
|
|
|
|
|
|
|
320
|
|
|
|
|
|
|
Registered handlers. |
321
|
|
|
|
|
|
|
|
322
|
|
|
|
|
|
|
=head2 helpers |
323
|
|
|
|
|
|
|
|
324
|
|
|
|
|
|
|
my $helpers = $renderer->helpers; |
325
|
|
|
|
|
|
|
$renderer = $renderer->helpers({url_for => sub {...}}); |
326
|
|
|
|
|
|
|
|
327
|
|
|
|
|
|
|
Registered helpers. |
328
|
|
|
|
|
|
|
|
329
|
|
|
|
|
|
|
=head2 min_compress_size |
330
|
|
|
|
|
|
|
|
331
|
|
|
|
|
|
|
my $size = $renderer->min_compress_size; |
332
|
|
|
|
|
|
|
$renderer = $renderer->min_compress_size(1024); |
333
|
|
|
|
|
|
|
|
334
|
|
|
|
|
|
|
Minimum output size in bytes required for compression to be used if enabled, defaults to C<860>. |
335
|
|
|
|
|
|
|
|
336
|
|
|
|
|
|
|
=head2 paths |
337
|
|
|
|
|
|
|
|
338
|
|
|
|
|
|
|
my $paths = $renderer->paths; |
339
|
|
|
|
|
|
|
$renderer = $renderer->paths(['/home/sri/templates']); |
340
|
|
|
|
|
|
|
|
341
|
|
|
|
|
|
|
Directories to look for templates in, first one has the highest precedence. |
342
|
|
|
|
|
|
|
|
343
|
|
|
|
|
|
|
# Add another "templates" directory |
344
|
|
|
|
|
|
|
push @{$renderer->paths}, '/home/sri/templates'; |
345
|
|
|
|
|
|
|
|
346
|
|
|
|
|
|
|
# Add another "templates" directory with higher precedence |
347
|
|
|
|
|
|
|
unshift @{$renderer->paths}, '/home/sri/themes/blue/templates'; |
348
|
|
|
|
|
|
|
|
349
|
|
|
|
|
|
|
=head1 METHODS |
350
|
|
|
|
|
|
|
|
351
|
|
|
|
|
|
|
L inherits all methods from L and implements the following new ones. |
352
|
|
|
|
|
|
|
|
353
|
|
|
|
|
|
|
=head2 accepts |
354
|
|
|
|
|
|
|
|
355
|
|
|
|
|
|
|
my $all = $renderer->accepts(Mojolicious::Controller->new); |
356
|
|
|
|
|
|
|
my $best = $renderer->accepts(Mojolicious::Controller->new, 'html', 'json'); |
357
|
|
|
|
|
|
|
|
358
|
|
|
|
|
|
|
Select best possible representation for L object from C C/C parameter, |
359
|
|
|
|
|
|
|
C stash value, or C request header, defaults to returning the first extension if no preference could be |
360
|
|
|
|
|
|
|
detected. |
361
|
|
|
|
|
|
|
|
362
|
|
|
|
|
|
|
=head2 add_handler |
363
|
|
|
|
|
|
|
|
364
|
|
|
|
|
|
|
$renderer = $renderer->add_handler(epl => sub {...}); |
365
|
|
|
|
|
|
|
|
366
|
|
|
|
|
|
|
Register a handler. |
367
|
|
|
|
|
|
|
|
368
|
|
|
|
|
|
|
$renderer->add_handler(foo => sub ($renderer, $c, $output, $options) { |
369
|
|
|
|
|
|
|
... |
370
|
|
|
|
|
|
|
$$output = 'Hello World!'; |
371
|
|
|
|
|
|
|
}); |
372
|
|
|
|
|
|
|
|
373
|
|
|
|
|
|
|
=head2 add_helper |
374
|
|
|
|
|
|
|
|
375
|
|
|
|
|
|
|
$renderer = $renderer->add_helper(url_for => sub {...}); |
376
|
|
|
|
|
|
|
|
377
|
|
|
|
|
|
|
Register a helper. |
378
|
|
|
|
|
|
|
|
379
|
|
|
|
|
|
|
$renderer->add_helper(foo => sub ($c, @args) { |
380
|
|
|
|
|
|
|
... |
381
|
|
|
|
|
|
|
}); |
382
|
|
|
|
|
|
|
|
383
|
|
|
|
|
|
|
=head2 get_data_template |
384
|
|
|
|
|
|
|
|
385
|
|
|
|
|
|
|
my $template = $renderer->get_data_template({ |
386
|
|
|
|
|
|
|
template => 'foo/bar', |
387
|
|
|
|
|
|
|
format => 'html', |
388
|
|
|
|
|
|
|
handler => 'epl' |
389
|
|
|
|
|
|
|
}); |
390
|
|
|
|
|
|
|
|
391
|
|
|
|
|
|
|
Return a C section template from L"classes"> for an options hash reference with C, C, |
392
|
|
|
|
|
|
|
C and C values, or C if no template could be found, usually used by handlers. |
393
|
|
|
|
|
|
|
|
394
|
|
|
|
|
|
|
=head2 get_helper |
395
|
|
|
|
|
|
|
|
396
|
|
|
|
|
|
|
my $helper = $renderer->get_helper('url_for'); |
397
|
|
|
|
|
|
|
|
398
|
|
|
|
|
|
|
Get a helper by full name, generate a helper dynamically for a prefix, or return C if no helper or prefix could |
399
|
|
|
|
|
|
|
be found. Generated helpers return a proxy object containing the current controller object and on which nested helpers |
400
|
|
|
|
|
|
|
can be called. |
401
|
|
|
|
|
|
|
|
402
|
|
|
|
|
|
|
=head2 render |
403
|
|
|
|
|
|
|
|
404
|
|
|
|
|
|
|
my ($output, $format) = $renderer->render(Mojolicious::Controller->new); |
405
|
|
|
|
|
|
|
|
406
|
|
|
|
|
|
|
Render output through one of the renderers. See L for a more user-friendly interface. |
407
|
|
|
|
|
|
|
|
408
|
|
|
|
|
|
|
=head2 respond |
409
|
|
|
|
|
|
|
|
410
|
|
|
|
|
|
|
my $bool = $renderer->respond(Mojolicious::Controller->new, $output, $format); |
411
|
|
|
|
|
|
|
my $bool = $renderer->respond( |
412
|
|
|
|
|
|
|
Mojolicious::Controller->new, $output, $format, $status); |
413
|
|
|
|
|
|
|
|
414
|
|
|
|
|
|
|
Finalize dynamically generated response content and L"compress"> it if possible. |
415
|
|
|
|
|
|
|
|
416
|
|
|
|
|
|
|
=head2 template_for |
417
|
|
|
|
|
|
|
|
418
|
|
|
|
|
|
|
my $name = $renderer->template_for(Mojolicious::Controller->new); |
419
|
|
|
|
|
|
|
|
420
|
|
|
|
|
|
|
Return default template name for L object, or C if no name could be generated. |
421
|
|
|
|
|
|
|
|
422
|
|
|
|
|
|
|
=head2 template_handler |
423
|
|
|
|
|
|
|
|
424
|
|
|
|
|
|
|
my $handler = $renderer->template_handler({ |
425
|
|
|
|
|
|
|
template => 'foo/bar', |
426
|
|
|
|
|
|
|
format => 'html' |
427
|
|
|
|
|
|
|
}); |
428
|
|
|
|
|
|
|
|
429
|
|
|
|
|
|
|
Return handler for an options hash reference with C, C and C values, or C if no |
430
|
|
|
|
|
|
|
handler could be found. |
431
|
|
|
|
|
|
|
|
432
|
|
|
|
|
|
|
=head2 template_name |
433
|
|
|
|
|
|
|
|
434
|
|
|
|
|
|
|
my $template = $renderer->template_name({ |
435
|
|
|
|
|
|
|
template => 'foo/bar', |
436
|
|
|
|
|
|
|
format => 'html', |
437
|
|
|
|
|
|
|
handler => 'epl' |
438
|
|
|
|
|
|
|
}); |
439
|
|
|
|
|
|
|
|
440
|
|
|
|
|
|
|
Return a template name for an options hash reference with C, C, C and C values, or |
441
|
|
|
|
|
|
|
C if no template could be found, usually used by handlers. |
442
|
|
|
|
|
|
|
|
443
|
|
|
|
|
|
|
=head2 template_path |
444
|
|
|
|
|
|
|
|
445
|
|
|
|
|
|
|
my $path = $renderer->template_path({ |
446
|
|
|
|
|
|
|
template => 'foo/bar', |
447
|
|
|
|
|
|
|
format => 'html', |
448
|
|
|
|
|
|
|
handler => 'epl' |
449
|
|
|
|
|
|
|
}); |
450
|
|
|
|
|
|
|
|
451
|
|
|
|
|
|
|
Return the full template path for an options hash reference with C, C, C and C |
452
|
|
|
|
|
|
|
values, or C if the file does not exist in L"paths">, usually used by handlers. |
453
|
|
|
|
|
|
|
|
454
|
|
|
|
|
|
|
=head2 warmup |
455
|
|
|
|
|
|
|
|
456
|
|
|
|
|
|
|
$renderer->warmup; |
457
|
|
|
|
|
|
|
|
458
|
|
|
|
|
|
|
Prepare templates from L"classes"> for future use. |
459
|
|
|
|
|
|
|
|
460
|
|
|
|
|
|
|
=head1 SEE ALSO |
461
|
|
|
|
|
|
|
|
462
|
|
|
|
|
|
|
L, L, L. |
463
|
|
|
|
|
|
|
|
464
|
|
|
|
|
|
|
=cut |