package Web::Library;
use MooseX::Singleton;
use Params::Validate qw(:all);
use Web::Library::Item;
our $VERSION = '0.06';
has 'libraries' => (
traits => ['Array'],
is => 'ro',
isa => 'ArrayRef[Web::Library::Item]',
default => sub { [] },
handles => {
all_libraries => 'elements',
push_library => 'push',
reset => 'clear',
},
);
sub mount_library {
my $self = shift;
my %args = validate(@_, { name => 1, version => 0 });
$self->push_library(Web::Library::Item->new(%args));
}
sub include_paths {
my $self = shift;
my @paths = map { $_->include_path } $self->all_libraries;
wantarray ? @paths : \@paths;
}
sub library_map {
my ($self, $code, @libs) = @_;
my %lib_by_name = map { $_->name => $_ } $self->all_libraries;
my @result;
for my $lib (@libs) {
my $item = $lib_by_name{$lib} // die "unknown library [$lib]";
local $_ = $item; # so you can use $_ as well as $_[0] in $code
push @result, $code->($item);
}
@result;
}
sub css_assets_for {
my ($self, @libs) = @_;
$self->library_map(sub { $_->css_assets }, @libs);
}
sub javascript_assets_for {
my ($self, @libs) = @_;
$self->library_map(sub { $_->javascript_assets }, @libs);
}
sub css_link_tags_for {
my ($self, @libs) = @_;
join "\n",
map { qq!! }
$self->css_assets_for(@libs);
}
sub script_tags_for {
my ($self, @libs) = @_;
join "\n",
map { qq!! }
$self->javascript_assets_for(@libs);
}
1;
=pod
=head1 NAME
Web::Library - Manager for wrappers around client-side libraries
=head1 SYNOPSIS
# in your Catalyst application:
my $library_manager = Web::Library->instance;
$library_manager->mount_library({ name => 'jQuery' });
$library_manager->mount_library(
{ name => 'Bootstrap', version => '2.3.0' });
__PACKAGE__->config(
'Plugin::Static::Simple' => {
include_path => [ $library_manager->include_paths ] },
...
);
# in an HTML template
...
[% web_library.css_link_tags_for('Bootstrap', 'jQuery') %]
...
[% web_library.script_tags_for('Bootstrap', 'jQuery') %]
=head1 DESCRIPTION
There are well-established ways for web applications to manage server-side
dependencies, like C or C - but what about client-side
dependencies?
So you develop and maintain a number of web applications, and all of them use
some client-side libraries like jQuery or Twitter Bootstrap or Underscore.js.
You have to copy the relevant JavaScript, CSS and image files to a directory
containing static files for each web application. This involves quite a bit of
copying around and version maintenance. Web::Library can help you.
The idea behind Web::Library and its related distributions is that client-side
libraries are installed as shared files of standard CPAN distributions.
Web::Library itself is a manager for those libraries. A web application that
wishes to use one or more client-side libraries can tell Web::Library to
include either the latest or a specific version of those libraries. These
managed libraries can then be used as static files with web application
frameworks. In the case of L you might use
L as shown in the synopsis.
Web::Library is a singleton object, so you can add client-side libraries in
different parts of your application. For example, you might have common
librares that are included in all of your web applications, but then also want
to manage application-specific libraries.
Only client-side libraries whose license permits redistribution can be managed
this way. Forunately, most, if not all, popular client-side libraries have such
permissive licenses.
=head1 METHODS
=over 4
=item instance
Returns the singleton Web::Library object that manages all client-side libraries.
=item mount_library
Adds a specific version of a client-side library to the list of managed
libraries. Takes a hashref of named parameters. Valid parameters are:
=over 4
=item name
The name of the client-side library. The manager will try to load the
C class. For example, L is a
distribution wrapper for Twitter Bootstrap.
=item version
A distribution wrapper will contain various versions of the wrapped client-side
library. Using this parameter you can specify the version you want. Refer to
the relevant distribution's documentation to see which versions are available.
This parameter is optional; if omitted, the latest version is used.
=back
=item include_paths
Client-side library files are installed as shared files as described in
L. The C method returns the absolute paths to
shared directories for all managed libraries.
Returns a list in list context and an array reference in scalar context.
=item reset
Clears all mounted libraries.
=back
=head2 ASSET-RELATED METHODS
Web::Library can also help you with including a library's CSS and JavaScript
files in the web page templates.
If you expose an instance of Web::Library to your templates, you can add the
relevant C<< >> and C<<