=head1 NAME Dancer::Plugin::Assets - Manage and minify .css and .js assets in a Dancer application =head1 SYNOPSIS =head3 In your Dancer application use Dancer::Plugin::Assets qw( assets add_asset ); =head3 Sometime during the request ... get "/index" => sub { ## Include assets by plugin method add_asset "/css/beautiful.css"; add_asset "/css/handlebars.js"; ## Include assets by assets object assets->include( "/css/main.css" ); assets->include( "/js/something.js" ); }; =head3 Then, in your .tt, print css tags at , print js tags after body [% title %] [% css_tags %] [% js_tags %] =head3 Or you want to add css and js and print them all in template file inside [% title %] [% add_asset("/js/jquery.js") %] [% add_asset("/js/handlebars.js") %] [% add_asset("/css/beautiful.css") %] [% CALL assets.include("/js/foo.js") %] [% css_and_js_tags || js_and_css_tags %] =head1 DESCRIPTION Dancer::Plugin::Assets integrates File::Assets into your Dancer application. Essentially, it provides a unified way to include .css and .js assets from different parts of your program. When you're done processing a request, you can use assets->export() or [% css_and_js_tags %] to generate HTML or assets->exports() to get a list of assets. D::P::Assets will also handle .css files of different media types properly. In addition, D::P::Assets includes support for minification via YUI compressor, L, L, L, and L Note that Dancer::Plugin::Assets does not serve files directly, it will work with L or whatever static-file-serving mechanism you're using. =head1 USEAGE For usage hints and tips, see L =head1 CONFIGURATION You can configure D::P::Assets by manipulating the environment configration files, e.g. config.yml environments/development.yml environments/production.yml The following settings are available: url # The url to access the asset files default "/" base_dir # A path to automatically look for assets under (e.g. "/public") # This path will be automatically prepended to includes, so that instead of # doing ->include("/public/css/stylesheet.css") you can just do ->include("/css/stylesheet.css") output_dir # The path to output the results of minification under (if any). # For example, if output is "built/" (the trailing slash is important), then minified assets will be # written to "root//static/..." # # Designates the output path for minified .css and .js assets # The default output path pattern is "%n%-l%-d.%e" (rooted at the dir of ) minify # "1" or "best" - Will either use JavaScript::Minifier::XS> & CSS::Minifier::XS or # JavaScript::Minifier> & CSS::Minifier (depending on availability) # for minification # "0" or "" or undef - Don't do any minfication (this is the default) # "./path/to/yuicompressor.jar" - Will use YUI Compressor via the given .jar for minification # "minifier" - Will use JavaScript::Minifier & CSS::Minifier for minification minified_name # The name of the key in the stash that provides the assets object (accessible via config->{plugins}{assets}{minified_name}. # By default, the is "minified". =head1 Example configuration Here is an example configuration: ( All the value are set by default ) plugins: Assets: base_dir: "/public" output_dir: "static/%n%-l.%e" minified_name: "minified" minify: 1 =head1 METHODS IN ROUTE CODE =head2 assets Return L object that exists throughout the lifetime of the request =head2 add_asset same as sub { assets->include( shift ); return undef } =head1 METHODS IN TT =head2 [% assets %] Return L object that exists throughout the lifetime of the request =head2 [% add_asset %] same as [% CALL assets.include( "file..." ) %] =head2 [% css_tags %] return tags of css in html =head2 [% js_tags %] return tags of javascript in html =head2 [% css_and_js_tags %] return tags in this order of css and javascript in html =head2 [% js_and_css_tags %] return tags in this order of javascript and css in html =head1 AUTHOR Michael Vu, C<< >> =head1 BUGS Please report any bugs or feature requests to C, or through the web interface at L. I will be notified, and then you'll automatically be notified of progress on your bug as I make changes. =head1 SUPPORT You can find documentation for this module with the perldoc command. perldoc Dancer::Plugin::Assets You can also look for information at: =over 4 =item * RT: CPAN's request tracker L =item * AnnoCPAN: Annotated CPAN documentation L =item * CPAN Ratings L =item * Search CPAN L =item * GIT Respority L =back =head1 SEE ALSO L L L L L L L =head1 ACKNOWLEDGEMENTS This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut package Dancer::Plugin::Assets; { $Dancer::Plugin::Assets::VERSION = '1.5'; } use URI; use Dancer::Plugin; use Dancer ":syntax"; use File::Assets; register assets => \&_assets; register add_asset => \&_include; register_plugin for_versions => [ 1, 2 ]; hook before_template_render => sub { my $stash = shift; $stash->{assets} = _assets(); $stash->{add_asset} = \&_include; $stash->{css_tags} = \&_css_tags; $stash->{js_tags} = \&_js_tags; $stash->{css_and_js_tags} = \&_css_and_js_tags; $stash->{js_and_css_tags} = \&_js_and_css_tags; }; sub _assets { return var("assets") || _build_assets(); } sub _include { my $assets = _assets(); $assets->include(@_); return; } sub _js_and_css_tags { return _js_tags() . _css_tags(); } sub _css_and_js_tags { return _css_tags() . _js_tags(); } sub _css_tags { my $assets = _assets(); return $assets->export("css"); } sub _js_tags { my $assets = _assets(); return $assets->export("js"); } sub _build_assets { my $setting = plugin_setting(); my $url = _url( $setting->{url} ); my $base_dir = $setting->{base_dir} || setting "public"; my $output_dir = $setting->{output_dir} || "static/%n%-l.%e"; my $minify = defined $setting->{minify} ? $setting->{minify} : 1; my $minified_name = $setting->{minified_name} || "minified"; ## https://metacpan.org/pod/File::Assets#METHODS my $assets = File::Assets->new( name => $minified_name, minify => $minify, output_path => $output_dir, base => [ $url, $base_dir ], ); return var assets => $assets; } sub _url { my $url = shift or return _site_url(); if ( $url =~ /^\// ) { return _site_url() . $url; } if ( $url !~/^[^\/]+\:\/\//i ) { return _site_url() . $url; } return $url; } sub _site_url { return _scheme() . "://" . _host(); } sub _scheme { return request->env->{"psgi.url_scheme"}; } sub _host { return request->host; } true;