3 SGN::Controller::JavaScript - controller for serving minified
8 package SGN
::Controller
::JavaScript
;
10 use namespace
::autoclean
;
11 use Moose
::Util
::TypeConstraints
;
16 use Fcntl
qw( S_ISREG S_ISLNK );
19 use List
::MoreUtils qw
/ uniq first_index /;
25 BEGIN { extends
'Catalyst::Controller' }
29 js_path
=> SGN
->path_to('js/build'),
30 dependency_json_path
=> SGN
->path_to('js/build/mapping.json'),
31 js_legacy_path
=> SGN
->path_to('js/source/legacy')
35 my $inc = subtype as
'ArrayRef';
36 coerce
$inc, from
'Defined', via
{ [$_] };
43 has
'dependency_json_path' => (
48 has
'js_legacy_path' => (
59 Serve a single (minified) javascript file from our js path.
63 sub default :Path
('build') {
64 my ( $self, $c, @args ) = @_;
66 my $rel_file = File
::Spec
->catfile( @args );
68 # support caching with If-Modified-Since requests
69 my $full_file = File
::Spec
->catfile( $self->js_path->[0], $rel_file );
70 my ( $modtime ) = (stat( $full_file ))[9];
71 $c->throw_404 unless $modtime && -f _
;
73 my $ims = $c->req->headers->if_modified_since;
74 if( $ims && $modtime && $ims >= $modtime ) {
75 $c->res->status( RC_NOT_MODIFIED
);
78 #include sourcemap header if a sourcemap exists
79 my $sourcemap_name = $rel_file.".map";
80 if( -f File
::Spec
->catfile( $self->js_path->[0], $sourcemap_name )){
81 $c->res->headers->header('SourceMap' => $sourcemap_name);
83 $c->res->headers->last_modified( $modtime );
84 $c->res->headers->content_type( "application/javascript" );
85 $c->res->body(join("",read_file
($full_file)));
86 $c->res->headers->remove_header('content-length');
92 Serve a single (minified) javascript file from our js path.
96 sub legacy
:Path
('legacy') {
97 my ( $self, $c, @args ) = @_;
99 my $rel_file = File
::Spec
->catfile( @args );
101 # support caching with If-Modified-Since requests
102 my $full_file = File
::Spec
->catfile( $self->js_legacy_path->[0], $rel_file );
103 my ( $modtime ) = (stat( $full_file ))[9];
104 $c->throw_404 unless $modtime && -f _
;
106 my $ims = $c->req->headers->if_modified_since;
107 if( $ims && $modtime && $ims >= $modtime ) {
108 $c->res->status( RC_NOT_MODIFIED
);
111 $c->stash->{js
} = [ $rel_file ];
112 $c->forward('View::JavaScript::Legacy');
117 =head1 PRIVATE ACTIONS
119 =head2 get_js_module_dependencies
123 my $js_module_dependencies = {};
124 my $js_module_dependencies_modtime = 0;
125 sub get_js_module_dependencies
:Private
{
126 my ( $self, $names ) = @_;
128 my ( $modtime ) = (stat( $self->dependency_json_path->[0] ))[9];
129 if( ! $js_module_dependencies_modtime || $js_module_dependencies_modtime < $modtime) {
130 $js_module_dependencies = decode_json
(read_file
($self->dependency_json_path->[0]));
131 $js_module_dependencies_modtime = $modtime;
139 # print Dumper $names;
140 # print Dumper $js_module_dependencies;
142 for my $n (@
$names) {
143 if (exists $js_module_dependencies->{$n}){
144 push @
{$result->{files
}}, @
{$js_module_dependencies->{$n}->{files
}};
145 push @
{$result->{legacy
}}, @
{$js_module_dependencies->{$n}->{legacy
}};
149 # print Dumper $result;
154 =head2 resolve_javascript_classes
158 sub resolve_javascript_classes
:Private
{
159 my ( $self, $c ) = @_;
161 my $jsan_classes = $c->stash->{jsan_classes
};
162 my $js_modules = $c->stash->{js_modules
};
164 my $module_deps = $self->get_js_module_dependencies($js_modules);
165 push @
{ $jsan_classes }, @
{$module_deps->{legacy
}};
167 my @jsan_deps = uniq @
$jsan_classes; #< do not sort, load order might be important
172 # if prototype is present, move it to the front to prevent it
173 # conflicting with jquery
174 my $prototype_idx = first_index
{ /Prototype$/i } @jsan_deps;
175 if( $prototype_idx > -1 ) {
176 my ($p) = splice @jsan_deps, $prototype_idx, 1;
177 unshift @jsan_deps, $p;
180 # add in JSAN.use dependencies
181 my @deps = $self->_resolve_jsan_dependencies( \
@jsan_deps );
183 for my $dep (@
{$module_deps->{files
}}) {
184 push @deps, File
::Spec
->catfile( "/js/build/", $dep )
187 $c->stash->{js_uris
} = \
@deps;
190 ########## helpers #########
192 sub _resolve_jsan_dependencies
{
193 my ( $self, $files ) = @_;
194 local $_; #< stupid JSAN writes to $_
196 # resolve JSAN dependencies of these files
197 my $jsan = $self->new_jsan;
198 for my $f (@
$files) {
205 has _jsan_params
=> ( is
=> 'ro', isa
=> 'HashRef', lazy_build
=> 1 );
206 sub _build__jsan_params
{
208 my $inc_path = $self->js_legacy_path;
209 die "multi-dir js_legacy_path not yet supported" if @
$inc_path > 1;
210 my $js_dir = $inc_path->[0];
211 -d
$js_dir or die "configured js_legacy_path '$js_dir' does not exist!\n";
214 uri_prefix
=> '/js/legacy',
218 JSAN
::ServerSide
->new( %{ shift->_jsan_params } );