| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
package Mojolicious::Plugin::AssetPack; |
|
2
|
11
|
|
|
11
|
|
119496
|
use Mojo::Base 'Mojolicious::Plugin'; |
|
|
11
|
|
|
|
|
31
|
|
|
|
11
|
|
|
|
|
86
|
|
|
3
|
|
|
|
|
|
|
|
|
4
|
11
|
|
|
11
|
|
1394
|
use Mojo::Util 'trim'; |
|
|
11
|
|
|
|
|
24
|
|
|
|
11
|
|
|
|
|
473
|
|
|
5
|
11
|
|
|
11
|
|
3060
|
use Mojolicious::Plugin::AssetPack::Asset::Null; |
|
|
11
|
|
|
|
|
29
|
|
|
|
11
|
|
|
|
|
98
|
|
|
6
|
11
|
|
|
11
|
|
3548
|
use Mojolicious::Plugin::AssetPack::Store; |
|
|
11
|
|
|
|
|
32
|
|
|
|
11
|
|
|
|
|
80
|
|
|
7
|
11
|
|
|
11
|
|
387
|
use Mojolicious::Plugin::AssetPack::Util qw(diag has_ro load_module DEBUG); |
|
|
11
|
|
|
|
|
24
|
|
|
|
11
|
|
|
|
|
23288
|
|
|
8
|
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
our $VERSION = '1.48'; |
|
10
|
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
my %TAG_TEMPLATE; |
|
12
|
|
|
|
|
|
|
$TAG_TEMPLATE{css} = [qw(link rel stylesheet href)]; |
|
13
|
|
|
|
|
|
|
$TAG_TEMPLATE{ico} = [qw(link rel icon href)]; |
|
14
|
|
|
|
|
|
|
$TAG_TEMPLATE{js} = [qw(script src)]; |
|
15
|
|
|
|
|
|
|
$TAG_TEMPLATE{$_} = [qw(img src)] for qw(gif jpg jpeg png svg); |
|
16
|
|
|
|
|
|
|
$TAG_TEMPLATE{$_} = [qw(source src)] for qw(mp3 mp4 ogg ogv webm); |
|
17
|
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
has minify => sub { shift->_app->mode eq 'development' ? 0 : 1 }; |
|
19
|
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
has route => sub { |
|
21
|
|
|
|
|
|
|
shift->_app->routes->route('/asset/:checksum/*name')->via(qw(HEAD GET)) |
|
22
|
|
|
|
|
|
|
->name('assetpack')->to(cb => \&_serve); |
|
23
|
|
|
|
|
|
|
}; |
|
24
|
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
has store => sub { |
|
26
|
|
|
|
|
|
|
my $self = shift; |
|
27
|
|
|
|
|
|
|
Mojolicious::Plugin::AssetPack::Store->new( |
|
28
|
|
|
|
|
|
|
classes => [@{$self->_app->static->classes}], |
|
29
|
|
|
|
|
|
|
paths => [$self->_app->home->rel_file('assets')], |
|
30
|
|
|
|
|
|
|
ua => $self->ua, |
|
31
|
|
|
|
|
|
|
); |
|
32
|
|
|
|
|
|
|
}; |
|
33
|
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
has tag_for => sub { |
|
35
|
|
|
|
|
|
|
my $self = shift; |
|
36
|
|
|
|
|
|
|
my $favicon = $self->pipe('Favicon') ? 1 : 0; |
|
37
|
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
Scalar::Util::weaken($self); |
|
39
|
|
|
|
|
|
|
return sub { |
|
40
|
|
|
|
|
|
|
my ($asset, $c, $args, @attrs) = @_; |
|
41
|
|
|
|
|
|
|
return $self->pipe('Favicon')->render($c) |
|
42
|
|
|
|
|
|
|
if $args->{topic} eq 'favicon.ico' and $favicon; |
|
43
|
|
|
|
|
|
|
my $url = $asset->url_for($c); |
|
44
|
|
|
|
|
|
|
my @template = @{$TAG_TEMPLATE{$_->format} || $TAG_TEMPLATE{css}}; |
|
45
|
|
|
|
|
|
|
splice @template, 1, 0, type => $c->app->types->type($asset->format) |
|
46
|
|
|
|
|
|
|
if $template[0] eq 'source'; |
|
47
|
|
|
|
|
|
|
return $c->tag(@template, Mojo::URL->new("$args->{base_url}$url"), @attrs); |
|
48
|
|
|
|
|
|
|
}; |
|
49
|
|
|
|
|
|
|
}; |
|
50
|
|
|
|
|
|
|
|
|
51
|
|
|
|
|
|
|
has_ro ua => sub { Mojo::UserAgent->new->max_redirects(3) }; |
|
52
|
|
|
|
|
|
|
|
|
53
|
|
|
|
|
|
|
sub pipe { |
|
54
|
9
|
|
|
9
|
1
|
33
|
my ($self, $needle) = @_; |
|
55
|
9
|
|
|
|
|
21
|
return +(grep { $_ =~ /::$needle\b/ } @{$self->{pipes}})[0]; |
|
|
14
|
|
|
|
|
200
|
|
|
|
9
|
|
|
|
|
27
|
|
|
56
|
|
|
|
|
|
|
} |
|
57
|
|
|
|
|
|
|
|
|
58
|
|
|
|
|
|
|
sub process { |
|
59
|
15
|
|
|
15
|
1
|
46
|
my ($self, $topic, @input) = @_; |
|
60
|
|
|
|
|
|
|
|
|
61
|
15
|
100
|
|
|
|
85
|
$self->route unless $self->{route_added}++; |
|
62
|
15
|
100
|
|
|
|
3837
|
return $self->_process_from_def($topic) unless @input; |
|
63
|
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
# TODO: The idea with blessed($_) is that maybe the user can pass inn |
|
65
|
|
|
|
|
|
|
# Mojolicious::Plugin::AssetPack::Sprites object, with images to generate |
|
66
|
|
|
|
|
|
|
# CSS from? |
|
67
|
11
|
|
|
|
|
109
|
my $assets = Mojo::Collection->new; |
|
68
|
11
|
|
|
|
|
83
|
for my $url (@input) { |
|
69
|
11
|
100
|
|
|
|
56
|
my $asset = Scalar::Util::blessed($url) ? $url : $self->store->asset($url); |
|
70
|
11
|
100
|
|
|
|
142
|
die qq(Could not find input asset "$url".) unless Scalar::Util::blessed($asset); |
|
71
|
10
|
|
|
|
|
52
|
push @$assets, $asset; |
|
72
|
|
|
|
|
|
|
} |
|
73
|
|
|
|
|
|
|
|
|
74
|
10
|
50
|
|
0
|
|
35
|
return $self->tap(sub { $_->{input}{$topic} = $assets }) if $self->{lazy}; |
|
|
0
|
|
|
|
|
0
|
|
|
75
|
10
|
|
|
|
|
36
|
return $self->_process($topic => $assets); |
|
76
|
|
|
|
|
|
|
} |
|
77
|
|
|
|
|
|
|
|
|
78
|
0
|
|
|
0
|
1
|
0
|
sub processed { $_[0]->{by_topic}{$_[1]} } |
|
79
|
|
|
|
|
|
|
|
|
80
|
|
|
|
|
|
|
sub register { |
|
81
|
13
|
|
|
13
|
1
|
5181
|
my ($self, $app, $config) = @_; |
|
82
|
13
|
|
100
|
|
|
88
|
my $helper = $config->{helper} || 'asset'; |
|
83
|
|
|
|
|
|
|
|
|
84
|
13
|
50
|
|
|
|
47
|
if ($app->renderer->helpers->{$helper}) { |
|
85
|
0
|
|
|
|
|
0
|
return $app->log->debug("AssetPack: Helper $helper() is already registered."); |
|
86
|
|
|
|
|
|
|
} |
|
87
|
|
|
|
|
|
|
|
|
88
|
13
|
|
|
|
|
187
|
$self->{input} = {}; |
|
89
|
13
|
|
50
|
|
|
136
|
$self->{lazy} ||= $ENV{MOJO_ASSETPACK_LAZY} // $config->{lazy} || 0; |
|
|
|
|
33
|
|
|
|
|
|
90
|
13
|
|
|
|
|
61
|
$app->defaults('assetpack.helper' => $helper); |
|
91
|
13
|
|
|
|
|
505
|
$self->ua->server->app($app); |
|
92
|
13
|
|
|
|
|
745
|
Scalar::Util::weaken($self->ua->server->{app}); |
|
93
|
|
|
|
|
|
|
|
|
94
|
13
|
100
|
100
|
|
|
128
|
if (my $proxy = $config->{proxy} // {}) { |
|
95
|
|
|
|
|
|
|
local $ENV{NO_PROXY} = $proxy->{no_proxy} || join ',', grep {$_} $ENV{NO_PROXY}, |
|
96
|
12
|
|
33
|
|
|
75
|
$ENV{no_proxy}, '127.0.0.1', '::1', 'localhost'; |
|
97
|
12
|
|
|
|
|
22
|
diag 'Detecting proxy settings. (NO_PROXY=%s)', $ENV{NO_PROXY} if DEBUG; |
|
98
|
12
|
|
|
|
|
35
|
$self->ua->proxy->detect; |
|
99
|
|
|
|
|
|
|
} |
|
100
|
|
|
|
|
|
|
|
|
101
|
13
|
50
|
|
|
|
665
|
if ($config->{pipes}) { |
|
102
|
13
|
|
|
|
|
47
|
$self->_pipes($config->{pipes}); |
|
103
|
13
|
100
|
|
111
|
|
92
|
$app->helper($helper => sub { @_ == 1 ? $self : $self->_render_tags(@_) }); |
|
|
111
|
|
|
|
|
291468
|
|
|
104
|
|
|
|
|
|
|
} |
|
105
|
|
|
|
|
|
|
else { |
|
106
|
0
|
|
|
|
|
0
|
$app->log->warn( |
|
107
|
|
|
|
|
|
|
'https://metacpan.org/release/Mojolicious-Plugin-AssetPack-Backcompat is required'); |
|
108
|
|
|
|
|
|
|
Test::More::diag("Loading DEPRECATED Mojolicious::Plugin::AssetPack::Backcompat.") |
|
109
|
0
|
0
|
0
|
|
|
0
|
if $ENV{HARNESS_ACTIVE} and UNIVERSAL::can(qw(Test::More diag)); |
|
110
|
0
|
|
|
|
|
0
|
require Mojolicious::Plugin::AssetPack::Backcompat; |
|
111
|
0
|
|
|
|
|
0
|
@Mojolicious::Plugin::AssetPack::ISA = ('Mojolicious::Plugin::AssetPack::Backcompat'); |
|
112
|
0
|
|
|
|
|
0
|
return $self->SUPER::register($app, $config); |
|
113
|
|
|
|
|
|
|
} |
|
114
|
|
|
|
|
|
|
} |
|
115
|
|
|
|
|
|
|
|
|
116
|
45
|
|
|
45
|
|
400
|
sub _app { shift->ua->server->app } |
|
117
|
|
|
|
|
|
|
|
|
118
|
|
|
|
|
|
|
sub _correct_mode { |
|
119
|
4
|
|
|
4
|
|
11
|
my ($self, $args) = @_; |
|
120
|
|
|
|
|
|
|
|
|
121
|
4
|
|
|
|
|
20
|
while ($args =~ /\[(\w+)([!=]+)([^\]]+)/g) { |
|
122
|
0
|
0
|
|
|
|
0
|
my $v = $1 eq 'minify' ? $self->minify : $self->_app->$1; |
|
123
|
0
|
|
|
|
|
0
|
diag "Checking $1: $v $2 $3" if DEBUG == 2; |
|
124
|
0
|
0
|
0
|
|
|
0
|
return 0 if $2 eq '!=' and $v eq $3; |
|
125
|
0
|
0
|
0
|
|
|
0
|
return 0 if $2 ne '!=' and $v ne $3; # default to testing equality |
|
126
|
|
|
|
|
|
|
} |
|
127
|
|
|
|
|
|
|
|
|
128
|
4
|
|
|
|
|
11
|
return 1; |
|
129
|
|
|
|
|
|
|
} |
|
130
|
|
|
|
|
|
|
|
|
131
|
|
|
|
|
|
|
sub _pipes { |
|
132
|
13
|
|
|
13
|
|
32
|
my ($self, $names) = @_; |
|
133
|
|
|
|
|
|
|
|
|
134
|
|
|
|
|
|
|
$self->{pipes} = [ |
|
135
|
|
|
|
|
|
|
map { |
|
136
|
13
|
50
|
|
|
|
29
|
my $class = load_module /::/ ? $_ : "Mojolicious::Plugin::AssetPack::Pipe::$_"; |
|
|
18
|
|
|
|
|
114
|
|
|
137
|
18
|
|
|
|
|
41
|
diag 'Loading pipe "%s".', $class if DEBUG; |
|
138
|
18
|
|
|
|
|
179
|
my $pipe = $class->new(assetpack => $self); |
|
139
|
18
|
|
|
|
|
234
|
Scalar::Util::weaken($pipe->{assetpack}); |
|
140
|
18
|
|
|
|
|
65
|
$pipe; |
|
141
|
|
|
|
|
|
|
} @$names |
|
142
|
|
|
|
|
|
|
]; |
|
143
|
|
|
|
|
|
|
} |
|
144
|
|
|
|
|
|
|
|
|
145
|
|
|
|
|
|
|
sub _process { |
|
146
|
10
|
|
|
10
|
|
30
|
my ($self, $topic, $input) = @_; |
|
147
|
10
|
|
|
|
|
46
|
my $assets = Mojo::Collection->new(@$input); # Do not mess up input |
|
148
|
|
|
|
|
|
|
|
|
149
|
10
|
|
|
|
|
63
|
local $Mojolicious::Plugin::AssetPack::Util::TOPIC = $topic; # Used by diag() |
|
150
|
|
|
|
|
|
|
|
|
151
|
10
|
|
|
|
|
23
|
for my $asset (@$assets) { |
|
152
|
10
|
50
|
|
|
|
53
|
if (my $prev = $self->{by_topic}{$topic}) { |
|
153
|
0
|
|
|
|
|
0
|
delete $asset->{$_} for qw(checksum format); |
|
154
|
0
|
|
|
|
|
0
|
$asset->content($self->store->asset($asset->url)); |
|
155
|
|
|
|
|
|
|
} |
|
156
|
10
|
|
|
|
|
39
|
$asset->checksum; |
|
157
|
|
|
|
|
|
|
} |
|
158
|
|
|
|
|
|
|
|
|
159
|
10
|
|
|
|
|
30
|
for my $method (qw(before_process process after_process)) { |
|
160
|
30
|
|
|
|
|
234
|
for my $pipe (@{$self->{pipes}}) { |
|
|
30
|
|
|
|
|
63
|
|
|
161
|
45
|
100
|
|
|
|
461
|
next unless $pipe->can($method); |
|
162
|
15
|
|
|
|
|
58
|
local $pipe->{topic} = $topic; |
|
163
|
15
|
|
|
|
|
24
|
diag '%s->%s("%s")', ref $pipe, $method, $topic if DEBUG; |
|
164
|
15
|
|
|
|
|
50
|
$pipe->$method($assets); |
|
165
|
|
|
|
|
|
|
} |
|
166
|
|
|
|
|
|
|
} |
|
167
|
|
|
|
|
|
|
|
|
168
|
10
|
|
|
|
|
28
|
my @checksum = map { $_->checksum } @$assets; |
|
|
10
|
|
|
|
|
29
|
|
|
169
|
10
|
|
|
|
|
61
|
$self->_app->log->debug(qq(Processed asset "$topic". [@checksum])) if DEBUG; |
|
170
|
10
|
|
|
|
|
39
|
$self->{by_checksum}{$_->checksum} = $_ for @$assets; |
|
171
|
10
|
|
|
|
|
56
|
$self->{by_topic}{$topic} = $assets; |
|
172
|
10
|
|
|
|
|
26
|
$self->store->persist; |
|
173
|
10
|
|
|
|
|
55
|
$self; |
|
174
|
|
|
|
|
|
|
} |
|
175
|
|
|
|
|
|
|
|
|
176
|
|
|
|
|
|
|
sub _process_from_def { |
|
177
|
4
|
|
|
4
|
|
10
|
my $self = shift; |
|
178
|
4
|
|
50
|
|
|
28
|
my $file = shift || 'assetpack.def'; |
|
179
|
4
|
|
|
|
|
13
|
my $asset = $self->store->file($file); |
|
180
|
4
|
|
|
|
|
1086
|
my $topic = ''; |
|
181
|
4
|
|
|
|
|
10
|
my %process; |
|
182
|
|
|
|
|
|
|
|
|
183
|
4
|
50
|
|
|
|
12
|
die qq(Unable to load "$file".) unless $asset; |
|
184
|
4
|
|
|
|
|
8
|
diag qq(Loading asset definitions from "$file".) if DEBUG; |
|
185
|
|
|
|
|
|
|
|
|
186
|
4
|
|
|
|
|
14
|
for (split /\r?\n/, $asset->slurp) { |
|
187
|
8
|
|
|
|
|
110
|
s/\s*\#.*//; |
|
188
|
8
|
100
|
|
|
|
46
|
if (/^\<(\S*)\s+(\S+)\s*(.*)/) { |
|
|
|
50
|
|
|
|
|
|
|
189
|
4
|
|
|
|
|
19
|
my ($class, $url, $args) = ($1, $2, $3); |
|
190
|
4
|
50
|
|
|
|
15
|
next unless $self->_correct_mode($args); |
|
191
|
4
|
|
|
|
|
14
|
my $asset = $self->store->asset($url); |
|
192
|
4
|
100
|
|
|
|
83
|
die qq(Could not find input asset "$url".) unless Scalar::Util::blessed($asset); |
|
193
|
3
|
50
|
|
|
|
11
|
bless $asset, 'Mojolicious::Plugin::AssetPack::Asset::Null' if $class eq '<'; |
|
194
|
3
|
|
|
|
|
6
|
push @{$process{$topic}}, $asset; |
|
|
3
|
|
|
|
|
18
|
|
|
195
|
|
|
|
|
|
|
} |
|
196
|
4
|
|
|
|
|
19
|
elsif (/^\!\s*(.+)/) { $topic = trim $1; } |
|
197
|
|
|
|
|
|
|
} |
|
198
|
|
|
|
|
|
|
|
|
199
|
3
|
|
|
|
|
13
|
$self->process($_ => @{$process{$_}}) for keys %process; |
|
|
3
|
|
|
|
|
25
|
|
|
200
|
3
|
|
|
|
|
26
|
$self; |
|
201
|
|
|
|
|
|
|
} |
|
202
|
|
|
|
|
|
|
|
|
203
|
|
|
|
|
|
|
sub _render_tags { |
|
204
|
72
|
|
|
72
|
|
224
|
my ($self, $c, $topic, @attrs) = @_; |
|
205
|
72
|
|
|
|
|
209
|
my $route = $self->route; |
|
206
|
|
|
|
|
|
|
|
|
207
|
72
|
50
|
|
|
|
800
|
$self->_process($topic => $self->{input}{$topic}) if $self->{lazy}; |
|
208
|
|
|
|
|
|
|
|
|
209
|
72
|
|
66
|
|
|
251
|
my $assets = $self->{by_topic}{$topic} ||= $self->_static_asset($topic); |
|
210
|
72
|
|
100
|
|
|
242
|
my %args = (base_url => $route->pattern->defaults->{base_url} || '', topic => $topic); |
|
211
|
72
|
|
|
|
|
899
|
$args{base_url} =~ s!/+$!!; |
|
212
|
|
|
|
|
|
|
|
|
213
|
72
|
|
|
72
|
|
1207
|
return $assets->grep(sub { !$_->isa('Mojolicious::Plugin::AssetPack::Asset::Null') }) |
|
214
|
72
|
|
|
|
|
435
|
->map($self->tag_for, $c, \%args, @attrs)->join("\n"); |
|
215
|
|
|
|
|
|
|
} |
|
216
|
|
|
|
|
|
|
|
|
217
|
|
|
|
|
|
|
sub _serve { |
|
218
|
20
|
|
|
20
|
|
196417
|
my $c = shift; |
|
219
|
20
|
|
|
|
|
80
|
my $checksum = $c->stash('checksum'); |
|
220
|
20
|
|
|
|
|
237
|
my $helper = $c->stash('assetpack.helper'); |
|
221
|
20
|
|
|
|
|
304
|
my $self = $c->$helper; |
|
222
|
|
|
|
|
|
|
|
|
223
|
20
|
100
|
|
|
|
128
|
if (my $f = $self->{by_checksum}{$checksum}) { |
|
224
|
18
|
|
|
|
|
81
|
$self->store->serve_asset($c, $f); |
|
225
|
18
|
|
|
|
|
75
|
return $c->rendered; |
|
226
|
|
|
|
|
|
|
} |
|
227
|
|
|
|
|
|
|
|
|
228
|
2
|
|
|
|
|
5
|
my $topic = $c->stash('name'); |
|
229
|
2
|
100
|
|
|
|
21
|
if ($self->{by_topic}{$topic}) { |
|
230
|
1
|
|
|
|
|
8
|
return $c->render(text => "// Invalid checksum for topic '$topic'\n", status => 404); |
|
231
|
|
|
|
|
|
|
} |
|
232
|
|
|
|
|
|
|
|
|
233
|
1
|
|
|
|
|
6
|
$c->render(text => "// No such asset '$topic'\n", status => 404); |
|
234
|
|
|
|
|
|
|
} |
|
235
|
|
|
|
|
|
|
|
|
236
|
|
|
|
|
|
|
sub _static_asset { |
|
237
|
8
|
|
|
8
|
|
16
|
my ($self, $topic) = @_; |
|
238
|
8
|
50
|
|
|
|
20
|
my $asset = $self->store->asset($topic) |
|
239
|
|
|
|
|
|
|
or die qq(No assets registered by topic "$topic".); |
|
240
|
8
|
|
|
|
|
151
|
my $assets = Mojo::Collection->new($asset); |
|
241
|
8
|
|
|
|
|
65
|
$self->{by_checksum}{$_->checksum} = $_ for @$assets; |
|
242
|
8
|
|
|
|
|
37
|
return $assets; |
|
243
|
|
|
|
|
|
|
} |
|
244
|
|
|
|
|
|
|
|
|
245
|
|
|
|
|
|
|
1; |
|
246
|
|
|
|
|
|
|
|
|
247
|
|
|
|
|
|
|
=encoding utf8 |
|
248
|
|
|
|
|
|
|
|
|
249
|
|
|
|
|
|
|
=head1 NAME |
|
250
|
|
|
|
|
|
|
|
|
251
|
|
|
|
|
|
|
Mojolicious::Plugin::AssetPack - Compress and convert css, less, sass, javascript and coffeescript files |
|
252
|
|
|
|
|
|
|
|
|
253
|
|
|
|
|
|
|
=head1 VERSION |
|
254
|
|
|
|
|
|
|
|
|
255
|
|
|
|
|
|
|
1.48 |
|
256
|
|
|
|
|
|
|
|
|
257
|
|
|
|
|
|
|
=head1 SYNOPSIS |
|
258
|
|
|
|
|
|
|
|
|
259
|
|
|
|
|
|
|
=head2 Application |
|
260
|
|
|
|
|
|
|
|
|
261
|
|
|
|
|
|
|
use Mojolicious::Lite; |
|
262
|
|
|
|
|
|
|
|
|
263
|
|
|
|
|
|
|
# Load plugin and pipes in the right order |
|
264
|
|
|
|
|
|
|
plugin AssetPack => { |
|
265
|
|
|
|
|
|
|
pipes => [qw(Less Sass Css CoffeeScript Riotjs JavaScript Combine)] |
|
266
|
|
|
|
|
|
|
}; |
|
267
|
|
|
|
|
|
|
|
|
268
|
|
|
|
|
|
|
# define asset |
|
269
|
|
|
|
|
|
|
app->asset->process( |
|
270
|
|
|
|
|
|
|
# virtual name of the asset |
|
271
|
|
|
|
|
|
|
"app.css" => ( |
|
272
|
|
|
|
|
|
|
|
|
273
|
|
|
|
|
|
|
# source files used to create the asset |
|
274
|
|
|
|
|
|
|
"sass/bar.scss", |
|
275
|
|
|
|
|
|
|
"https://github.com/Dogfalo/materialize/blob/master/sass/materialize.scss", |
|
276
|
|
|
|
|
|
|
) |
|
277
|
|
|
|
|
|
|
); |
|
278
|
|
|
|
|
|
|
|
|
279
|
|
|
|
|
|
|
=head2 Template |
|
280
|
|
|
|
|
|
|
|
|
281
|
|
|
|
|
|
|
|
|
282
|
|
|
|
|
|
|
|
|
283
|
|
|
|
|
|
|
%= asset "app.css" |
|
284
|
|
|
|
|
|
|
|
|
285
|
|
|
|
|
|
|
<%= content %> |
|
286
|
|
|
|
|
|
|
|
|
287
|
|
|
|
|
|
|
|
|
288
|
|
|
|
|
|
|
=head1 DESCRIPTION |
|
289
|
|
|
|
|
|
|
|
|
290
|
|
|
|
|
|
|
L is L |
|
291
|
|
|
|
|
|
|
for processing static assets. The idea is that JavaScript and CSS files should |
|
292
|
|
|
|
|
|
|
be served as one minified file to save bandwidth and roundtrip time to the |
|
293
|
|
|
|
|
|
|
server. |
|
294
|
|
|
|
|
|
|
|
|
295
|
|
|
|
|
|
|
There are many external tools for doing this, but integrating them with |
|
296
|
|
|
|
|
|
|
L can be a struggle: You want to serve the source files directly |
|
297
|
|
|
|
|
|
|
while developing, but a minified version in production. This assetpack plugin |
|
298
|
|
|
|
|
|
|
will handle all of that automatically for you. |
|
299
|
|
|
|
|
|
|
|
|
300
|
|
|
|
|
|
|
Your application creates and refers to an asset by its topic (virtual asset |
|
301
|
|
|
|
|
|
|
name). The process of building actual assets from their components is |
|
302
|
|
|
|
|
|
|
delegated to "pipe objects". Please see |
|
303
|
|
|
|
|
|
|
L for a complete list. |
|
304
|
|
|
|
|
|
|
|
|
305
|
|
|
|
|
|
|
=head1 BREAKING CHANGES |
|
306
|
|
|
|
|
|
|
|
|
307
|
|
|
|
|
|
|
=head2 assetpack.db (v1.47) |
|
308
|
|
|
|
|
|
|
|
|
309
|
|
|
|
|
|
|
C no longer track files downloaded from the internet. It will |
|
310
|
|
|
|
|
|
|
mostly "just work", but in some cases version 1.47 might download assets that |
|
311
|
|
|
|
|
|
|
have already been downloaded with AssetPack version 1.46 and earlier. |
|
312
|
|
|
|
|
|
|
|
|
313
|
|
|
|
|
|
|
The goal is to remove C completely. |
|
314
|
|
|
|
|
|
|
|
|
315
|
|
|
|
|
|
|
=head1 GUIDES |
|
316
|
|
|
|
|
|
|
|
|
317
|
|
|
|
|
|
|
=over 2 |
|
318
|
|
|
|
|
|
|
|
|
319
|
|
|
|
|
|
|
=item * L |
|
320
|
|
|
|
|
|
|
|
|
321
|
|
|
|
|
|
|
The tutorial will give an introduction to how AssetPack can be used. |
|
322
|
|
|
|
|
|
|
|
|
323
|
|
|
|
|
|
|
=item * L |
|
324
|
|
|
|
|
|
|
|
|
325
|
|
|
|
|
|
|
The "developing" guide will give insight on how to do effective development with |
|
326
|
|
|
|
|
|
|
AssetPack and more details about the internals in this plugin. |
|
327
|
|
|
|
|
|
|
|
|
328
|
|
|
|
|
|
|
=item * L |
|
329
|
|
|
|
|
|
|
|
|
330
|
|
|
|
|
|
|
The cookbook has various receipes on how to cook with AssetPack. |
|
331
|
|
|
|
|
|
|
|
|
332
|
|
|
|
|
|
|
=back |
|
333
|
|
|
|
|
|
|
|
|
334
|
|
|
|
|
|
|
=head1 HELPERS |
|
335
|
|
|
|
|
|
|
|
|
336
|
|
|
|
|
|
|
=head2 asset |
|
337
|
|
|
|
|
|
|
|
|
338
|
|
|
|
|
|
|
$self = $app->asset; |
|
339
|
|
|
|
|
|
|
$self = $c->asset; |
|
340
|
|
|
|
|
|
|
$bytestream = $c->asset($topic, @args); |
|
341
|
|
|
|
|
|
|
$bytestream = $c->asset("app.css", media => "print"); |
|
342
|
|
|
|
|
|
|
|
|
343
|
|
|
|
|
|
|
C is the main entry point to this plugin. It can either be used to |
|
344
|
|
|
|
|
|
|
access the L instance or as a tag helper. |
|
345
|
|
|
|
|
|
|
|
|
346
|
|
|
|
|
|
|
The helper name "asset" can be customized by specifying "helper" when |
|
347
|
|
|
|
|
|
|
L the plugin. |
|
348
|
|
|
|
|
|
|
|
|
349
|
|
|
|
|
|
|
See L for more details. |
|
350
|
|
|
|
|
|
|
|
|
351
|
|
|
|
|
|
|
=head1 ATTRIBUTES |
|
352
|
|
|
|
|
|
|
|
|
353
|
|
|
|
|
|
|
=head2 minify |
|
354
|
|
|
|
|
|
|
|
|
355
|
|
|
|
|
|
|
$bool = $self->minify; |
|
356
|
|
|
|
|
|
|
$self = $self->minify($bool); |
|
357
|
|
|
|
|
|
|
|
|
358
|
|
|
|
|
|
|
Set this to true to combine and minify the assets. Defaults to false if |
|
359
|
|
|
|
|
|
|
L is "development" and true otherwise. |
|
360
|
|
|
|
|
|
|
|
|
361
|
|
|
|
|
|
|
See L |
|
362
|
|
|
|
|
|
|
for more details. |
|
363
|
|
|
|
|
|
|
|
|
364
|
|
|
|
|
|
|
=head2 route |
|
365
|
|
|
|
|
|
|
|
|
366
|
|
|
|
|
|
|
$route = $self->route; |
|
367
|
|
|
|
|
|
|
$self = $self->route($route); |
|
368
|
|
|
|
|
|
|
|
|
369
|
|
|
|
|
|
|
A L object used to serve assets. The default route |
|
370
|
|
|
|
|
|
|
responds to HEAD and GET requests and calls |
|
371
|
|
|
|
|
|
|
L on L |
|
372
|
|
|
|
|
|
|
to serve the asset. |
|
373
|
|
|
|
|
|
|
|
|
374
|
|
|
|
|
|
|
The default route will be built and added to the L |
|
375
|
|
|
|
|
|
|
when L is called the first time. |
|
376
|
|
|
|
|
|
|
|
|
377
|
|
|
|
|
|
|
See L |
|
378
|
|
|
|
|
|
|
for an example on how to customize this route. |
|
379
|
|
|
|
|
|
|
|
|
380
|
|
|
|
|
|
|
=head2 store |
|
381
|
|
|
|
|
|
|
|
|
382
|
|
|
|
|
|
|
$obj = $self->store; |
|
383
|
|
|
|
|
|
|
$self = $self->store(Mojolicious::Plugin::AssetPack::Store->new); |
|
384
|
|
|
|
|
|
|
|
|
385
|
|
|
|
|
|
|
Holds a L object used to locate, store |
|
386
|
|
|
|
|
|
|
and serve assets. |
|
387
|
|
|
|
|
|
|
|
|
388
|
|
|
|
|
|
|
=head2 tag_for |
|
389
|
|
|
|
|
|
|
|
|
390
|
|
|
|
|
|
|
$self = $self->tag_for(sub { my ($asset, $c, \%args, @attrs) = @_; }); |
|
391
|
|
|
|
|
|
|
$code = $self->tag_for; |
|
392
|
|
|
|
|
|
|
|
|
393
|
|
|
|
|
|
|
Holds a sub reference that returns a L object containing the |
|
394
|
|
|
|
|
|
|
markup required to render an asset. |
|
395
|
|
|
|
|
|
|
|
|
396
|
|
|
|
|
|
|
C<$asset> is a L object, C<$c> is an |
|
397
|
|
|
|
|
|
|
L object and C<@attrs> can contain a list of |
|
398
|
|
|
|
|
|
|
HTML attributes. C<%args> currently contains: |
|
399
|
|
|
|
|
|
|
|
|
400
|
|
|
|
|
|
|
=over 4 |
|
401
|
|
|
|
|
|
|
|
|
402
|
|
|
|
|
|
|
=item * base_url |
|
403
|
|
|
|
|
|
|
|
|
404
|
|
|
|
|
|
|
See L. |
|
405
|
|
|
|
|
|
|
|
|
406
|
|
|
|
|
|
|
=item * topic |
|
407
|
|
|
|
|
|
|
|
|
408
|
|
|
|
|
|
|
Name of the current topic. |
|
409
|
|
|
|
|
|
|
|
|
410
|
|
|
|
|
|
|
=back |
|
411
|
|
|
|
|
|
|
|
|
412
|
|
|
|
|
|
|
=head2 ua |
|
413
|
|
|
|
|
|
|
|
|
414
|
|
|
|
|
|
|
$ua = $self->ua; |
|
415
|
|
|
|
|
|
|
|
|
416
|
|
|
|
|
|
|
Holds a L which can be used to fetch assets either from local |
|
417
|
|
|
|
|
|
|
application or from remote web servers. |
|
418
|
|
|
|
|
|
|
|
|
419
|
|
|
|
|
|
|
=head1 METHODS |
|
420
|
|
|
|
|
|
|
|
|
421
|
|
|
|
|
|
|
=head2 pipe |
|
422
|
|
|
|
|
|
|
|
|
423
|
|
|
|
|
|
|
$obj = $self->pipe($name); |
|
424
|
|
|
|
|
|
|
$obj = $self->pipe("Css"); |
|
425
|
|
|
|
|
|
|
|
|
426
|
|
|
|
|
|
|
Will return a registered pipe by C<$name> or C if none could be found. |
|
427
|
|
|
|
|
|
|
|
|
428
|
|
|
|
|
|
|
=head2 process |
|
429
|
|
|
|
|
|
|
|
|
430
|
|
|
|
|
|
|
$self = $self->process($topic => @assets); |
|
431
|
|
|
|
|
|
|
$self = $self->process($definition_file); |
|
432
|
|
|
|
|
|
|
|
|
433
|
|
|
|
|
|
|
Used to process assets. A C<$definition_file> can be used to define C<$topic> |
|
434
|
|
|
|
|
|
|
and C<@assets> in a separate file. See |
|
435
|
|
|
|
|
|
|
L for more |
|
436
|
|
|
|
|
|
|
details. |
|
437
|
|
|
|
|
|
|
|
|
438
|
|
|
|
|
|
|
C<$definition_file> defaults to "assetpack.def". |
|
439
|
|
|
|
|
|
|
|
|
440
|
|
|
|
|
|
|
=head2 processed |
|
441
|
|
|
|
|
|
|
|
|
442
|
|
|
|
|
|
|
$collection = $self->processed($topic); |
|
443
|
|
|
|
|
|
|
|
|
444
|
|
|
|
|
|
|
Can be used to retrieve a L object, with zero or more |
|
445
|
|
|
|
|
|
|
L objects. Returns undef if C<$topic> is |
|
446
|
|
|
|
|
|
|
not defined with L. |
|
447
|
|
|
|
|
|
|
|
|
448
|
|
|
|
|
|
|
=head2 register |
|
449
|
|
|
|
|
|
|
|
|
450
|
|
|
|
|
|
|
$self->register($app, \%config); |
|
451
|
|
|
|
|
|
|
|
|
452
|
|
|
|
|
|
|
Used to register the plugin in the application. C<%config> can contain: |
|
453
|
|
|
|
|
|
|
|
|
454
|
|
|
|
|
|
|
=over 2 |
|
455
|
|
|
|
|
|
|
|
|
456
|
|
|
|
|
|
|
=item * helper |
|
457
|
|
|
|
|
|
|
|
|
458
|
|
|
|
|
|
|
Name of the helper to add to the application. Default is "asset". |
|
459
|
|
|
|
|
|
|
|
|
460
|
|
|
|
|
|
|
=item * pipes |
|
461
|
|
|
|
|
|
|
|
|
462
|
|
|
|
|
|
|
This argument is mandatory and need to contain a complete list of pipes that is |
|
463
|
|
|
|
|
|
|
needed. Example: |
|
464
|
|
|
|
|
|
|
|
|
465
|
|
|
|
|
|
|
$app->plugin(AssetPack => {pipes => [qw(Sass Css Combine)]); |
|
466
|
|
|
|
|
|
|
|
|
467
|
|
|
|
|
|
|
See L for a complete |
|
468
|
|
|
|
|
|
|
list of available pipes. |
|
469
|
|
|
|
|
|
|
|
|
470
|
|
|
|
|
|
|
=item * proxy |
|
471
|
|
|
|
|
|
|
|
|
472
|
|
|
|
|
|
|
A hash of proxy settings. Set this to C<0> to disable proxy detection. |
|
473
|
|
|
|
|
|
|
Currently only "no_proxy" is supported, which will set which requests that |
|
474
|
|
|
|
|
|
|
should bypass the proxy (if any proxy is detected). Default is to bypass all |
|
475
|
|
|
|
|
|
|
requests to localhost. |
|
476
|
|
|
|
|
|
|
|
|
477
|
|
|
|
|
|
|
See L for more information. |
|
478
|
|
|
|
|
|
|
|
|
479
|
|
|
|
|
|
|
=back |
|
480
|
|
|
|
|
|
|
|
|
481
|
|
|
|
|
|
|
=head1 SEE ALSO |
|
482
|
|
|
|
|
|
|
|
|
483
|
|
|
|
|
|
|
L, |
|
484
|
|
|
|
|
|
|
L, |
|
485
|
|
|
|
|
|
|
L and |
|
486
|
|
|
|
|
|
|
L. |
|
487
|
|
|
|
|
|
|
|
|
488
|
|
|
|
|
|
|
=head1 COPYRIGHT AND LICENSE |
|
489
|
|
|
|
|
|
|
|
|
490
|
|
|
|
|
|
|
Copyright (C) 2014, Jan Henning Thorsen |
|
491
|
|
|
|
|
|
|
|
|
492
|
|
|
|
|
|
|
This program is free software, you can redistribute it and/or modify it under |
|
493
|
|
|
|
|
|
|
the terms of the Artistic License version 2.0. |
|
494
|
|
|
|
|
|
|
|
|
495
|
|
|
|
|
|
|
=head1 AUTHOR |
|
496
|
|
|
|
|
|
|
|
|
497
|
|
|
|
|
|
|
Jan Henning Thorsen - C |
|
498
|
|
|
|
|
|
|
|
|
499
|
|
|
|
|
|
|
Alexander Rymasheusky |
|
500
|
|
|
|
|
|
|
|
|
501
|
|
|
|
|
|
|
Mark Grimes - C |
|
502
|
|
|
|
|
|
|
|
|
503
|
|
|
|
|
|
|
Per Edin - C |
|
504
|
|
|
|
|
|
|
|
|
505
|
|
|
|
|
|
|
Viktor Turskyi |
|
506
|
|
|
|
|
|
|
|
|
507
|
|
|
|
|
|
|
=cut |