1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104
|
package Mojolicious::Plugin::AssetPack::Pipe::Fetch;
use Mojo::Base 'Mojolicious::Plugin::AssetPack::Pipe';
use Mojolicious::Plugin::AssetPack::Util qw(diag DEBUG);
use Mojo::URL;
# Only made public for quick fixes. Subject for change
our %FORMATS = (
css => {
re => qr{url\((['"]{0,1})(.*?)\1\)},
pos => sub {
my ($start, $url, $quotes) = @_;
my $len = length $url;
return $start - length($quotes) - $len - 1, $len;
},
},
js => {
re => qr{(//\W*sourceMappingURL=)(\S+)}m,
pos => sub {
my ($start, $url) = @_;
my $len = length $url;
return $start - $len, $len;
},
},
);
sub process {
my ($self, $assets) = @_;
my $store = $self->assetpack->store;
my $route = $self->assetpack->route;
my %related;
return $assets->each(sub {
my ($asset, $index) = @_;
return unless $asset->url =~ /^https?:/;
return unless my $format = $FORMATS{$asset->format};
my $base = Mojo::URL->new($asset->url);
my $content = $asset->content;
my $re = $format->{re};
while ($content =~ /$re/g) {
my @matches = ($2, $1);
my $url = $matches[0];
next if $url =~ /^(?:\#|data:)/; # Avoid "data:image/svg+xml..." and "#foo"
$url = Mojo::URL->new($url);
$url = $url->base($base)->to_abs->fragment(undef) unless $url->is_abs;
unless ($related{$url}) {
diag "Fetch resource $url" if DEBUG;
my $related = $store->asset($url) or die "AssetPack was unable to fetch related asset $url";
$self->assetpack->process($related->name, $related);
my $path = $route->render($related->TO_JSON);
$path =~ s!^/!!;
my $up = join '', map {'../'} $path =~ m!\/!g;
$related{$url} = "$up$path";
}
my ($start, $len) = $format->{pos}->(pos($content), @matches);
substr $content, $start, $len, Mojo::URL->new($related{$url})->query(Mojo::Parameters->new);
pos($content) = $start + $len;
}
$asset->content($content);
});
}
1;
=encoding utf8
=head1 NAME
Mojolicious::Plugin::AssetPack::Pipe::Fetch - Fetch related assets
=head1 SYNOPSIS
use Mojolicious::Lite;
plugin AssetPack => {pipes => [qw(Css Fetch)]};
app->asset->process(
"app.css" =>
"https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css"
);
=head1 DESCRIPTION
L<Mojolicious::Plugin::AssetPack::Pipe::Fetch> will look for "url()" in a CSS
file and fetch the resource from the remote location.
Note that this pipe is EXPERIMENTAL and subject for change.
=head1 METHODS
=head2 process
See L<Mojolicious::Plugin::AssetPack::Pipe/process>.
=head1 SEE ALSO
L<Mojolicious::Plugin::AssetPack>.
=cut
|