Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 18 additions & 2 deletions lib/MetaCPAN/Middleware/Static.pm
Original file line number Diff line number Diff line change
Expand Up @@ -71,12 +71,28 @@ sub wrap {
);
}
else {
my @assets = (@js_files);
if ( `lessc --version` =~ /lessc/ ) {
enable 'Assets::Dev' => (
files => [ map "root$_", @css_files, @less_files ],
extension => 'css',
read_file => sub {
my $file = shift;
my ($root_path) = $file =~ m{^root/(.*)/};
scalar
`lessc -s --source-map-map-inline --source-map-rootpath="/$root_path/" "$file"`;
},
);
}
else {
push @assets, @css_files, @less_files;
}

enable sub {
my ($app) = @_;
sub {
my ($env) = @_;
push @{ $env->{'psgix.assets'} ||= [] },
( @js_files, @css_files, @less_files, );
push @{ $env->{'psgix.assets'} ||= [] }, @assets;
$app->($env);
};
};
Expand Down
86 changes: 86 additions & 0 deletions lib/Plack/Middleware/Assets/Core.pm
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
package Plack::Middleware::Assets::Core;
use Moo::Role;
use Plack::App::File;

sub wrap {
my ( $self, $app, @args ) = @_;
if ( ref $self ) {
$self = $self->clone( app => $app );
}
else {
$self = $self->new( { app => $app, @args } );
}
$self->to_app;
}

sub clone {
my $self = shift;
( ref $self )->new( %$self, @_ );
}

has app => ( is => 'ro', required => 1 );
has wrapped => ( is => 'lazy', init_arg => 0, reader => 'to_app' );

has files => ( is => 'ro', required => 1 );
has read_file => (
is => 'ro',
default => sub {
sub {
my ($file) = @_;
open my $fh, '<', $file
or die "can't open $file: $!";
my $content = do { local $/; <$fh> };
close $fh;
$content;
};
}
);
has filter => ( is => 'ro' );
has mount => ( is => 'ro', default => '_assets' );

has extension => (
is => 'lazy',
default => sub {
my %uniq;
my @ext = grep { !$uniq{$_}++ }
map { /([^.]+)$/; $1 } @{ $_[0]->files };

if ( @ext > 1 ) {
die "extension must be specified if not all matching: @ext";
}
$ext[0];
},
);

has _asset_files => ( is => 'lazy' );
has _static_app => ( is => 'lazy' );

sub _build_wrapped {
my $self = shift;

my $mount = $self->mount;

my $app = \&{ $self->app };
my $mount_re = qr{^(/\Q$mount\E)(/.*)};

my @asset_files = @{ $self->_asset_files };

my $static_app = $self->_static_app;

sub {
my ($env) = @_;

if ( $env->{PATH_INFO} =~ $mount_re ) {
local $env->{SCRIPT_NAME} = $env->{SCRIPT_NAME} . $1;
local $env->{PATH_INFO} = $2;
my $res = $static_app->($env);
return $res
unless $res->[0] == 404;
}

push @{ $env->{'psgix.assets'} ||= [] }, @asset_files;
$app->(@_);
};
}

1;
60 changes: 60 additions & 0 deletions lib/Plack/Middleware/Assets/Dev.pm
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package Plack::Middleware::Assets::Dev;
use Digest::SHA qw(sha1_hex);
use Moo;

with 'Plack::Middleware::Assets::Core';

has _file_map => ( is => 'lazy' );

sub _build__file_map {
my $self = shift;
my @files = @{ $self->files };
return { map +( sha1_hex($_) => $_ ), @files };
}

sub _build__static_app {
my $self = shift;

my $file_map = $self->_file_map;
my $read_file = $self->read_file;
my $ext = $self->extension;
my $type
= Plack::MIME->mime_type( '.' . $ext ) || 'application/octet-stream';
my $filter = $self->filter;

sub {
my ($env) = @_;
my $path = $env->{PATH_INFO};

if ( $path
and $path =~ m{^/(.*)\.\Q$ext\E$}
and my $file = $file_map->{$1} )
{
my $content = $read_file->($file);
$content = $filter->($content)
if $filter;
return [
200,
[
'Content-Type' => $type,
'Cache-Control', 'no-cache',
],
[$content]
];
}
return [ 404, [], [] ];
};
}

sub _build__asset_files {
my $self = shift;
my $extension = $self->extension;
my $mount = $self->mount;
my $file_map = $self->_file_map;
return [
map "/$mount/$_.$extension",
sort { $file_map->{$a} cmp $file_map->{$b} } keys %$file_map
];
}

1;
98 changes: 12 additions & 86 deletions lib/Plack/Middleware/Assets/FileCached.pm
Original file line number Diff line number Diff line change
@@ -1,59 +1,10 @@
package Plack::Middleware::Assets::FileCached;
use Moo;
use File::Temp ();
use Plack::App::File;
use Digest::SHA qw(sha1_hex);
use File::Path ();
use Moo;

sub wrap {
my ( $self, $app, @args ) = @_;
if ( ref $self ) {
$self = $self->clone( app => $app );
}
else {
$self = $self->new( { app => $app, @args } );
}
$self->to_app;
}

sub clone {
my $self = shift;
( ref $self )->new( %$self, @_ );
}

has app => ( is => 'ro', required => 1 );
has wrapped => ( is => 'lazy', init_arg => 0, reader => 'to_app' );

has files => ( is => 'ro', required => 1 );
has read_file => (
is => 'ro',
default => sub {
sub {
my ($file) = @_;
open my $fh, '<', $file
or die "can't open $file: $!";
my $content = do { local $/; <$fh> };
close $fh;
$content;
};
}
);
has filter => ( is => 'ro' );
has mount => ( is => 'ro', default => '_assets' );

has extension => (
is => 'lazy',
default => sub {
my %uniq;
my @ext = grep { !$uniq{$_}++ }
map { /([^.]+)$/; $1 } @{ $_[0]->files };

if ( @ext > 1 ) {
die "extension must be specified if not all matching: @ext";
}
$ext[0];
}
);
with 'Plack::Middleware::Assets::Core';

has cache_dir => (
is => 'ro',
Expand All @@ -69,62 +20,37 @@ has cache_dir => (
},
);

has _asset_files => ( is => 'lazy' );

sub _build_wrapped {
my $self = shift;

sub _build__static_app {
my $self = shift;
my $cache_dir = $self->cache_dir;
my $mount = $self->mount;

my $file_app = Plack::App::File->new( root => "$cache_dir" )->to_app;
my $static_app = sub {
my $file_app = Plack::App::File->new( root => "$cache_dir" )->to_app;
sub {
my $res = &$file_app;
push @{ $res->[1] }, 'Cache-Control', 'max-age=31556926';
return $res;
};

my $app = \&{ $self->app };
my $mount_re = qr{^(/\Q$mount\E)(/.*)};

my @asset_files = @{ $self->_asset_files };

sub {
my ($env) = @_;

if ( $env->{PATH_INFO} =~ $mount_re ) {
local $env->{SCRIPT_NAME} = $env->{SCRIPT_NAME} . $1;
local $env->{PATH_INFO} = $2;
my $res = $static_app->($env);
return $res
unless $res->[0] == 404;
}

push @{ $env->{'psgix.assets'} ||= [] }, @asset_files;
$app->(@_);
};
}

sub _build__asset_files {
my $self = shift;
my $read_file = $self->read_file;
my @files = @{ $self->files };
my @assets;
my $content = join "\n", map { $read_file->($_) } @files;
my $extension = $self->extension;
my $mount = $self->mount;
my $read_file = $self->read_file;
my $content = join "\n", map { $read_file->($_) } @files;
if ( my $filter = $self->filter ) {
$content = $filter->($content);
}
my $key = sha1_hex($content);
my $file = "$key." . $self->extension;
my $file = "$key." . $extension;
my $disk_file = $self->cache_dir . "/$file";
if ( !-e $disk_file ) {
open my $fh, '>', $disk_file
or die "can't open $disk_file: $!";
print {$fh} $content;
close $fh;
}
push @assets, '/' . $self->mount . "/$file";
\@assets;
["/$mount/$file"];
}

1;