File Coverage

blib/lib/Mojolicious/Plugin/LinkedContent/v9.pm
Criterion Covered Total %
statement 121 130 93.0
branch 25 44 56.8
condition 5 5 100.0
subroutine 21 21 100.0
pod 4 6 66.6
total 176 206 85.4


line stmt bran cond sub pod time code
1 2     2   1853 use strict;
  2         6  
  2         69  
2 2     2   11 use warnings;
  2         5  
  2         99  
3             package Mojolicious::Plugin::LinkedContent::v9;
4             $Mojolicious::Plugin::LinkedContent::v9::VERSION = '0.10';
5 2     2   11 use warnings;
  2         5  
  2         50  
6 2     2   9 use strict;
  2         6  
  2         59  
7             require Mojo::URL;
8 2     2   1130 use Mojolicious::Plugin::Config;
  2         2438  
  2         25  
9 2     2   1521 use LWP::Simple;
  2         106254  
  2         20  
10 2     2   800 use File::Temp;
  2         6  
  2         176  
11              
12 2     2   13 use base 'Mojolicious::Plugin';
  2         4  
  2         3504  
13              
14             my %defaults = (
15             'js_base' => '/js',
16             'css_base' => '/css',
17             'reg_config' => 'https://raw.githubusercontent.com/EmilianoBruni/MPLConfig/main/linked_content.cfg',
18             );
19              
20             our $reverse = 0;
21              
22             my $stashkey = '$linked_store';
23              
24             sub register {
25 2     2 1 125 my ($self, $app, $params) = @_;
26 2         8 for (qw/js_base css_base reg_config/) {
27             $self->{$_} =
28 6 50       29 defined($params->{$_}) ? delete($params->{$_}) : $defaults{$_};
29             }
30              
31 2         10 $self->loaded_reg_items($app);
32              
33 2         586 push @{$app->renderer->classes}, __PACKAGE__;
  2         20  
34              
35             $app->renderer->add_helper(
36             require_js => sub {
37 3     3   57048 $self->store_items('js', @_);
38             }
39 2         52 );
40             $app->renderer->add_helper(
41             require_css => sub {
42 3     3   45508 $self->store_items('css', @_);
43             }
44 2         338 );
45             $app->renderer->add_helper(
46             require_reg => sub {
47 1     1   24299 $self->store_items_reg(@_);
48             }
49 2         173 );
50             $app->renderer->add_helper(
51             include_css => sub {
52 4     4   141 $self->include_css(@_);
53             }
54 2         208 );
55             $app->renderer->add_helper(
56             include_js => sub {
57 4     4   139 $self->include_js(@_);
58             }
59 2         164 );
60              
61 2         165 $app->log->debug("Plugin " . __PACKAGE__ . " registred!");
62             }
63              
64             sub loaded_reg_items {
65 2     2 0 4 my $s = shift;
66 2         9 my $app = shift;
67 2         6 $s->{reg_items} = {};
68 2 50       46 return unless ($s->{reg_config});
69              
70 2         8 my $file = $s->{reg_config};
71              
72 2         5 my $tmp;
73 2 50       7 if ($s->_is_remote($file)) {
74             # download
75 2         12 my $content = get($file);
76 2         755643 $tmp = File::Temp->new(SUFFIX => '.cfg' );
77 2         1736 print $tmp $content;
78 2         13 $file = $tmp->filename;
79 2         141 close($tmp);
80             }
81              
82 2         69 my $cfg = new Mojolicious::Plugin::Config->new->load($file);
83              
84 2 50       3300 $s->{reg_items} = $cfg->{linkedcontent} if (exists $cfg->{linkedcontent});
85 2         32 $app->log->debug("Registry library loaded at " . $s->{reg_config});
86             }
87              
88             sub store_items_reg {
89 2     2 0 8 my ($s, $c, @items) = @_;
90 2         7 foreach my $item (@items) {
91 2 50       12 if (exists $s->{reg_items}->{$item}) {
92 2         6 my $item_info = $s->{reg_items}->{$item};
93 2 100       10 if (exists $item_info->{deps}) {
94 1         3 $s->store_items_reg($c,@{$item_info->{deps}});
  1         8  
95             }
96 2         8 foreach (qw/js css/) {
97 3         14 $s->store_items($_,$c,@{$item_info->{$_}})
98 4 100       53 if exists $item_info->{$_};
99             }
100             }
101             }
102             }
103              
104             sub store_items {
105 9     9 1 45 my ($self, $target, $c, @items) = @_;
106              
107 9         19 my $upd;
108 9   100     49 my $store = $c->stash($stashkey) || {};
109 9 50       211 for ($reverse ? reverse(@items) : @items) {
110 10 50       54 if (exists $store->{'garage'}{$target}{$_}) {
111 0 0       0 next unless $reverse;
112 0         0 my $x = $_;
113 0         0 @{$store->{'box'}{$target}} = grep $_ ne $x,
114 0         0 @{$store->{'box'}{$target}};
  0         0  
115             }
116 10         39 $store->{'garage'}{$target}{$_} = 1;
117 10 50       36 if (!$reverse) { push(@{$store->{'box'}{$target}}, $_) }
  10         23  
  10         50  
118 0         0 else { unshift(@{$store->{'box'}{$target}}, $_); }
  0         0  
119             }
120 9         35 $c->stash($stashkey => $store);
121             }
122              
123             sub include_js {
124 4     4 1 12 my $self = shift;
125 4         13 my $c = shift;
126 4         11 local $reverse = 1;
127 4 50       19 $self->store_items('js', $c, @_) if @_;
128 4         20 my $store = $c->stash($stashkey);
129 4 50       50 return '' unless $store->{'box'}{'js'};
130 4         10 my @ct;
131 4         10 for (@{$store->{'box'}{'js'}}) {
  4         21  
132              
133 5 100       2091 $_ .= '.js' unless (/\.js$/);
134              
135 5         43 $c->stash('$linked_item' => $self->_prepend_path($_, 'js_base'));
136              
137 5         599 push @ct, $c->render_to_string(
138             template => 'LinkedContent/js',
139             format => 'html',
140             handler => 'ep',
141              
142             # template_class is deprecated since Mojolicious 2.62
143             # was removed at some point which broke my code.
144             # But it'll live here for a while
145             template_class => __PACKAGE__
146             );
147             }
148 4         3333 $c->stash('$linked_item', undef);
149 4         221 return join '', @ct;
150             }
151              
152             sub include_css {
153 4     4 1 15 my $self = shift;
154 4         11 my $c = shift;
155 4         22 local $reverse = 1;
156 4 50       23 $self->store_items('css', $c, @_) if @_;
157 4         20 my $store = $c->stash($stashkey);
158 4 50       49 return '' unless $store->{'box'}{'css'};
159 4         11 my @ct;
160 4         10 for (@{$store->{'box'}{'css'}}) {
  4         18  
161              
162 5         2051 my $stash = {
163             '$linked_media' => 'screen'
164             };
165              
166 5 50       23 if (ref($_) eq 'HASH') {
167 0         0 $stash->{'$linked_item'} = $_->{href};
168 0 0       0 $stash->{'$linked_media'} = $_->{media} if (exists $_->{media});
169             } else {
170 5         16 $stash->{'$linked_item'} = $_;
171             }
172              
173 5 100       39 $stash->{'$linked_item'} .= '.css' unless ($stash->{'$linked_item'} =~/\.css$/);
174 5         23 $stash->{'$linked_item'} = $self->_prepend_path($stash->{'$linked_item'}, 'css_base');
175              
176 5         290 $c->stash($stash);
177              
178 5         123 push @ct, $c->render_to_string(
179             template => 'LinkedContent/css',
180             format => 'html',
181             handler => 'ep',
182              
183             # template_class is deprecated since Mojolicious 2.62
184             # was removed at some point which broke my code.
185             # But it'll live here for a while
186             template_class => __PACKAGE__
187             );
188             }
189 4         3522 $c->stash('$linked_item', undef);
190 4         216 return join '', @ct;
191             }
192              
193             sub _prepend_path {
194 10     10   35 my ($self, $path, $base) = @_;
195              
196 10         99 my $url = Mojo::URL->new($path);
197 10 100 100     1530 if ($url->is_abs || $url->path->leading_slash) {
198              
199             # Absolute path or absolute url returned as is
200 8         323 return $path;
201             }
202              
203             # Basepath not defined
204 2 50       71 return unless $self->{$base};
205              
206             # Prepend path with base
207 2         10 my $basepath = Mojo::Path->new($self->{$base});
208 2         29 unshift @{$url->path->parts}, @{$basepath->parts};
  2         7  
  2         34  
209              
210             # Inherit leading slash from basepath
211 2         96 $url->path->leading_slash($basepath->leading_slash);
212              
213 2         54 return $url->to_string;
214             }
215              
216             sub _is_remote {
217 2     2   20 my ($s, $file) = (shift, shift);
218              
219 2 50       18 return 1 if ($file =~ /^http/);
220             }
221             1;
222              
223             =pod
224              
225             =head1 NAME
226              
227             Mojolicious::Plugin::LinkedContent::v9 - manage linked css and js
228              
229             =head1 VERSION
230              
231             version 0.10
232              
233             =head1 AUTHOR
234              
235             Emiliano Bruni
236              
237             =head1 COPYRIGHT AND LICENSE
238              
239             This software is copyright (c) 2021 by Emiliano Bruni.
240              
241             This is free software; you can redistribute it and/or modify it under
242             the same terms as the Perl 5 programming language system itself.
243              
244             =cut
245              
246             __DATA__