File Coverage

blib/lib/Dancer/Plugin/Assets.pm
Criterion Covered Total %
statement 10 12 83.3
branch n/a
condition n/a
subroutine 4 4 100.0
pod n/a
total 14 16 87.5


line stmt bran cond sub pod time code
1             =head1 NAME
2              
3             Dancer::Plugin::Assets - Manage and minify .css and .js assets in a Dancer application
4              
5             =head1 SYNOPSIS
6              
7             =head3 In your Dancer application
8              
9             use Dancer::Plugin::Assets qw( assets add_asset );
10              
11             =head3 Sometime during the request ...
12              
13             get "/index" => sub {
14             ## Include assets by plugin method
15             add_asset "/css/beautiful.css";
16             add_asset "/css/handlebars.js";
17              
18             ## Include assets by assets object
19             assets->include( "/css/main.css" );
20             assets->include( "/js/something.js" );
21             };
22              
23             =head3 Then, in your .tt, print css tags at <head>, print js tags after body
24              
25             <html>
26             <head><title>[% title %]</title>
27             [% css_tags %]
28             </head>
29             <body>
30             </body>
31             [% js_tags %]
32             </html>
33              
34             =head3 Or you want to add css and js and print them all in template file inside <head>
35              
36             <html>
37             <head><title>[% title %]</title>
38             [% add_asset("/js/jquery.js") %]
39             [% add_asset("/js/handlebars.js") %]
40             [% add_asset("/css/beautiful.css") %]
41             [% CALL assets.include("/js/foo.js") %]
42             [% css_and_js_tags || js_and_css_tags %]
43             </head>
44             <body>
45             </body>
46             </html>
47              
48             =head1 DESCRIPTION
49              
50             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.
51              
52             D::P::Assets will also handle .css files of different media types properly.
53              
54             In addition, D::P::Assets includes support for minification via YUI compressor, L<JavaScript::Minifier>, L<CSS::Minifier>, L<JavaScript::Minifier::XS>, and L<CSS::Minifier::XS>
55              
56             Note that Dancer::Plugin::Assets does not serve files directly, it will work with L<Static::Simple> or whatever static-file-serving mechanism you're using.
57              
58             =head1 USEAGE
59              
60             For usage hints and tips, see L<File::Assets>
61              
62             =head1 CONFIGURATION
63              
64             You can configure D::P::Assets by manipulating the environment configration files, e.g.
65              
66             config.yml
67             environments/development.yml
68             environments/production.yml
69              
70             The following settings are available:
71              
72             url # The url to access the asset files default "/"
73              
74             base_dir # A path to automatically look for assets under (e.g. "/public")
75            
76             # This path will be automatically prepended to includes, so that instead of
77             # doing ->include("/public/css/stylesheet.css") you can just do ->include("/css/stylesheet.css")
78            
79            
80             output_dir # The path to output the results of minification under (if any).
81             # For example, if output is "built/" (the trailing slash is important), then minified assets will be
82             # written to "root/<assets-path>/static/..."
83             #
84             # Designates the output path for minified .css and .js assets
85             # The default output path pattern is "%n%-l%-d.%e" (rooted at the dir of <base>)
86            
87            
88             minify # "1" or "best" - Will either use JavaScript::Minifier::XS> & CSS::Minifier::XS or
89             # JavaScript::Minifier> & CSS::Minifier (depending on availability)
90             # for minification
91             # "0" or "" or undef - Don't do any minfication (this is the default)
92             # "./path/to/yuicompressor.jar" - Will use YUI Compressor via the given .jar for minification
93             # "minifier" - Will use JavaScript::Minifier & CSS::Minifier for minification
94              
95              
96             minified_name # The name of the key in the stash that provides the assets object (accessible via config->{plugins}{assets}{minified_name}.
97             # By default, the <minified_name> is "minified".
98              
99             =head1 Example configuration
100              
101             Here is an example configuration: ( All the value are set by default )
102              
103             plugins:
104             Assets:
105             base_dir: "/public"
106             output_dir: "static/%n%-l.%e"
107             minified_name: "minified"
108             minify: 1
109              
110             =head1 METHODS IN ROUTE CODE
111              
112             =head2 assets
113              
114             Return L<File::Assets> object that exists throughout the lifetime of the request
115              
116             =head2 add_asset
117              
118             same as sub { assets->include( shift ); return undef }
119              
120             =head1 METHODS IN TT
121              
122             =head2 [% assets %]
123              
124             Return L<File::Assets> object that exists throughout the lifetime of the request
125              
126             =head2 [% add_asset %]
127              
128             same as [% CALL assets.include( "file..." ) %]
129              
130             =head2 [% css_tags %]
131              
132             return tags of css in html
133              
134             =head2 [% js_tags %]
135              
136             return tags of javascript in html
137              
138             =head2 [% css_and_js_tags %]
139              
140             return tags in this order of css and javascript in html
141              
142             =head2 [% js_and_css_tags %]
143              
144             return tags in this order of javascript and css in html
145              
146             =head1 AUTHOR
147              
148             Michael Vu, C<< <micvu at cpan.org> >>
149              
150             =head1 BUGS
151              
152             Please report any bugs or feature requests to C<bug-dancer-plugin-assets at rt.cpan.org>, or through
153             the web interface at L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Dancer::Plugin::Assets>. I will be notified, and then you'll
154             automatically be notified of progress on your bug as I make changes.
155              
156             =head1 SUPPORT
157              
158             You can find documentation for this module with the perldoc command.
159              
160             perldoc Dancer::Plugin::Assets
161              
162             You can also look for information at:
163              
164             =over 4
165              
166             =item * RT: CPAN's request tracker
167              
168             L<http://rt.cpan.org/NoAuth/Bugs.html?Dist=Dancer-Plugin-Assets>
169              
170             =item * AnnoCPAN: Annotated CPAN documentation
171              
172             L<http://annocpan.org/dist/Dancer-Plugin-Assets>
173              
174             =item * CPAN Ratings
175              
176             L<http://cpanratings.perl.org/d/Dancer-Plugin-Assets>
177              
178             =item * Search CPAN
179              
180             L<http://search.cpan.org/dist/Dancer-Plugin-Assets>
181              
182             =item * GIT Respority
183              
184             L<https://bitbucket.org/mvu8912/p5-dancer-plugin-assets>
185              
186             =back
187              
188             =head1 SEE ALSO
189              
190             L<File::Assets>
191              
192             L<Dancer::Plugin>
193              
194             L<http://developer.yahoo.com/yui/compressor/>
195              
196             L<JavaScript::Minifier::XS>
197              
198             L<CSS::Minifier::XS>
199              
200             L<JavaScript::Minifier>
201              
202             L<CSS::Minifier>
203              
204             =head1 ACKNOWLEDGEMENTS
205              
206             This program is free software; you can redistribute it and/or modify it
207             under the same terms as Perl itself.
208              
209             =cut
210              
211             package Dancer::Plugin::Assets;
212             {
213             $Dancer::Plugin::Assets::VERSION = '1.52';
214             }
215 1     1   417583 use URI;
  1         3  
  1         31  
216 1     1   1092 use Dancer::Plugin;
  1         1419  
  1         81  
217 1     1   7 use Dancer ":syntax";
  1         7  
  1         6  
218 1     1   191184 use File::Assets;
  0            
  0            
219              
220             register assets => \&_assets;
221             register add_asset => \&_include;
222             register_plugin for_versions => [ 1, 2 ];
223              
224             hook before_template_render => sub {
225             my $stash = shift;
226             $stash->{assets} = _assets();
227             $stash->{add_asset} = \&_include;
228             $stash->{css_tags} = \&_css_tags;
229             $stash->{js_tags} = \&_js_tags;
230             $stash->{css_and_js_tags} = \&_css_and_js_tags;
231             $stash->{js_and_css_tags} = \&_js_and_css_tags;
232             };
233              
234             sub _assets {
235             return var("assets")
236             || _build_assets();
237             }
238              
239             sub _include {
240             my $assets = _assets();
241             $assets->include(@_);
242             return;
243             }
244              
245             sub _js_and_css_tags {
246             return _js_tags() . _css_tags();
247             }
248              
249             sub _css_and_js_tags {
250             return _css_tags() . _js_tags();
251             }
252              
253             sub _css_tags {
254             my $assets = _assets();
255             return $assets->export("css");
256             }
257              
258             sub _js_tags {
259             my $assets = _assets();
260             return $assets->export("js");
261             }
262              
263             sub _build_assets {
264             my $setting = plugin_setting();
265              
266             my $url = _url( $setting->{url} );
267             my $base_dir = $setting->{base_dir} || setting "public";
268             my $output_dir = $setting->{output_dir} || "static/%n%-l.%e";
269             my $minify = defined $setting->{minify} ? $setting->{minify} : 1;
270             my $minified_name = $setting->{minified_name} || "minified";
271              
272             ## https://metacpan.org/pod/File::Assets#METHODS
273             my $assets = File::Assets->new(
274             name => $minified_name,
275             minify => $minify,
276             output_path => $output_dir,
277             base => [ $url, $base_dir ],
278             );
279              
280             return var assets => $assets;
281             }
282              
283             sub _url {
284             my $url = shift
285             or return _site_url();
286             if ( $url =~ /^\// ) {
287             return _site_url() . $url;
288             }
289             if ( $url !~/^[^\/]+\:\/\//i ) {
290             return _site_url() . $url;
291             }
292             return $url;
293             }
294              
295             sub _site_url {
296             return _scheme() . "://" . _host();
297             }
298              
299             sub _scheme {
300             return request->env->{"psgi.url_scheme"};
301             }
302              
303             sub _host {
304             return request->host;
305             }
306              
307             true;