File Coverage

blib/lib/Bootylicious/Plugin/BootyHelpers.pm
Criterion Covered Total %
statement 215 268 80.2
branch 27 44 61.3
condition 10 29 34.4
subroutine 36 45 80.0
pod 1 1 100.0
total 289 387 74.6


line stmt bran cond sub pod time code
1             package Bootylicious::Plugin::BootyHelpers;
2              
3 5     5   3814 use strict;
  5         12  
  5         135  
4 5     5   25 use warnings;
  5         12  
  5         165  
5              
6 5     5   28 use base 'Mojolicious::Plugin';
  5         12  
  5         416  
7              
8 5     5   34 use Mojo::ByteStream 'b';
  5         11  
  5         11023  
9              
10             sub register {
11 6     6 1 256 my ($self, $app) = @_;
12              
13 6         30 my $config = $app->config;
14              
15             $app->helper(
16             render_smart => sub {
17 11     11   380 my $self = shift;
18              
19 11         29 $app->plugins->emit_hook(before_render => $self);
20              
21 11 50       172 $self->render(@_) unless $self->res->code;
22             }
23 6         98 );
24              
25             $app->helper(
26             render_article_or_preview => sub {
27 3     3   1290 my $self = shift;
28 3         6 my $article = shift;
29              
30 3         23 my $parser = $self->parsers->{$article->format};
31 3   50     27 $parser ||= sub { $_[0] };
  3         38  
32              
33 3         16 my $cuttag = quotemeta $self->config->{cuttag};
34              
35 3         15 my $content = $article->content;
36              
37 3         9 my ($preview, $preview_link);
38 3 50       61 if ($content =~ s{^(.*?)\n$cuttag(?: (.*?))?(?:\n|\r|\n\r)}{}s) {
39 3         11 $preview = $1;
40 3   33     14 $preview_link = $2 || $self->config->{cuttext};
41 3         8 $content = $3;
42             }
43              
44             return Mojo::ByteStream->new(
45             $parser->($preview) . $self->tag(
46             div => class => 'more' => sub {
47 3         148 '→ '
48             . $self->link_to_full_content($article,
49             $preview_link);
50             }
51             )
52 3 50       16 ) if $preview;
53              
54 0         0 return Mojo::ByteStream->new($parser->($content));
55             }
56 6         141 );
57              
58             $app->helper(
59             render_article => sub {
60 1     1   99 my $self = shift;
61 1         3 my $article = shift;
62              
63 1         7 my $parser = $self->parsers->{$article->format};
64 1   50     11 $parser ||= sub { $_[0] };
  2         5  
65              
66 1         6 my $cuttag = quotemeta $self->config->{cuttag};
67              
68 1         7 my $head = $article->content;
69 1         4 my $tail = '';
70 1 50       24 if ($head =~ s{(.*?)\n$cuttag.*?\n(.*)}{$1}s) {
71 1         4 $tail = $2;
72             }
73              
74 1         3 my $cuttag_anchor = '';
75              
76 1         2 my $string;
77 1         3 $string = $parser->($head);
78 1 50       5 $string .= $cuttag_anchor . $parser->($tail) if $tail;
79              
80 1         7 return Mojo::ByteStream->new($string);
81             }
82 6         107 );
83              
84             $app->helper(
85             render_comment => sub {
86 0     0   0 my $self = shift;
87 0         0 my $comment = shift;
88              
89 0         0 my $content = $comment->content;
90              
91 0         0 $content = Mojo::ByteStream->new($content)->xml_escape;
92              
93 0         0 _parse_tag(\$content, 'quote' => 'blockquote');
94 0         0 _parse_tag(\$content, 'code');
95              
96 0         0 $content =~ s{\n}{
}xmsg;
97              
98 0         0 return Mojo::ByteStream->new($content);
99             }
100 6         105 );
101              
102             $app->helper(
103             article_author => sub {
104 7     7   7146 my $self = shift;
105 7         16 my $article = shift;
106              
107 7   33     45 return $article->author || $config->{author};
108             }
109 6         109 );
110              
111             $app->helper(
112             comment_author => sub {
113 0     0   0 my $self = shift;
114 0         0 my $comment = shift;
115              
116 0 0       0 return $comment->author unless $comment->url;
117              
118 0         0 return $self->link_to($comment->url => sub { $comment->author });
  0         0  
119             }
120 6         97 );
121              
122             $app->helper(
123             render_page => sub {
124 1     1   22 my $self = shift;
125 1         3 my $page = shift;
126              
127 1         9 my $parser = $self->parsers->{$page->format};
128 1   50     12 $parser ||= sub { $_[0] };
  1         3  
129              
130 1         6 my $string = $parser->($page->content);
131 1         7 return Mojo::ByteStream->new($string);
132             }
133 6         104 );
134              
135             $app->helper(
136             date => sub {
137 7     7   43 my $self = shift;
138 7         14 my $date = shift;
139 7         14 my $fmt = shift;
140              
141 7 50       19 return '' unless $date;
142              
143 7   33     43 $fmt ||= $config->{'datefmt'};
144              
145 7         29 return b($date->strftime($fmt))->decode('utf-8');
146             }
147 6         103 );
148 2     2   22 $app->helper(date_rss => sub { Mojo::Date->new($_[1]->epoch)->to_string }
149 6         108 );
150             $app->helper(
151             href_to_article => sub {
152 15     15   498 my $self = shift;
153 15         26 my $article = shift;
154              
155 15         71 return $self->url_for(
156             article => (
157             year => $article->created->year,
158             month => $article->created->month,
159             alias => $article->name,
160             format => 'html'
161             )
162             );
163             }
164 6         104 );
165             $app->helper(
166             link_to_article => sub {
167 7     7   2972 my $self = shift;
168 7         16 my $article = shift;
169              
170 7         53 my $href = $self->href_to_article($article);
171              
172 7 50       3361 my $cb = ref $_[-1] eq 'CODE' ? pop : undef;
173              
174 7 50       33 if ($article->link) {
175 0         0 my $string = '';
176              
177             $string
178 0   0     0 .= $self->link_to($href => $cb || sub { $article->title });
179 0         0 $string .= ' ';
180 0         0 $string .= $self->link_to($article->link => sub {"»"});
  0         0  
181              
182 0         0 return Mojo::ByteStream->new($string);
183             }
184              
185 7   50     99 return $self->link_to($href => $cb || sub { $article->title });
186             }
187 6         106 );
188             $app->helper(
189             link_to_full_content => sub {
190 3     3   84 my $self = shift;
191 3         8 my ($article, $preview_link) = @_;
192              
193 3         18 my $href = $self->href_to_article($article);
194 3         1306 $href->fragment('cut');
195              
196 3         42 return $self->link_to($href => sub {$preview_link});
  3         172  
197             }
198 6         106 );
199             $app->helper(
200             link_to_tag => sub {
201 25     25   748 my $self = shift;
202 25         44 my $tag = shift;
203              
204 25 100       69 my $name = ref $tag ? $tag->name : $tag;
205              
206 25 100       162 my $cb = ref $_[-1] eq 'CODE' ? $_[-1] : sub {$name};
  24         9490  
207 25 100       72 my $args = ref $_[0] eq 'HASH' ? $_[0] : {};
208              
209 25         163 return $self->link_to(
210             tag => {tag => $name, format => 'html', %$args} => $cb);
211             }
212 6         104 );
213             $app->helper(
214             tags_links => sub {
215 7     7   1065 my $self = shift;
216 7         16 my $article = shift;
217              
218 7         13 my @links = map { $self->link_to_tag($_) } @{$article->tags};
  21         5179  
  7         29  
219              
220 7         2445 my $string = '';
221 7         26 $string .= join ', ' => @links;
222              
223 7         87 return Mojo::ByteStream->new($string);
224             }
225 6         109 );
226             $app->helper(
227             link_to_page => sub {
228 6     6   45 my $self = shift;
229 6         11 my $name = shift;
230              
231 6 100       24 my %args = ref $_[0] eq 'HASH' ? %{shift @_} : ();
  2         8  
232              
233 6         13 my $timestamp = shift;
234              
235 6   50     30 my $query = delete $args{query} || {};
236              
237 6 50       20 if ($timestamp) {
238 0         0 return $self->link_to(
239             $self->url_for($name, %args, format => 'html')
240             ->query(timestamp => $timestamp, %$query) => @_);
241             }
242             else {
243 6         37 return $self->tag('span' => @_);
244             }
245             }
246 6         101 );
247             $app->helper(
248             link_to_author => sub {
249 0     0   0 my $self = shift;
250 0         0 my $author = shift;
251              
252 0   0     0 return $author || $self->config('author');
253             }
254 6         99 );
255              
256             $app->helper(
257             permalink_to => sub {
258 0     0   0 my $self = shift;
259 0         0 my $link = shift;
260              
261 0         0 return $self->link_to($link => sub {'★'});
  0         0  
262             }
263 6         114 );
264              
265             $app->helper(
266             strings => sub {
267 27     27   59058 my $self = shift;
268              
269 27         87 my $string = $config->{'strings'}->{$_[0]};
270              
271 27         80 for (my $i = 0; $i < @_; $i++) {
272 28         171 $string =~ s/\[_$i\]/$_[$i]/;
273             }
274              
275 27         96 return $string;
276             }
277 6         105 );
278              
279 6         87 foreach my $name (qw/articles pages drafts/) {
280 18   100     232 my $option = $config->{"${name}_directory"} || '';
281             $app->helper(
282             "${name}_root" => sub {
283 16 50   16   488 ($option =~ m/^\//) ? $option : $app->home->rel_file($option);
284             }
285 18         86 );
286             }
287              
288 6     0   100 $app->helper(page_limit => sub { $config->{pagelimit} });
  0         0  
289              
290             $app->helper(
291             meta => sub {
292 16     16   352 my $self = shift;
293              
294 16         33 my $string = '';
295              
296 16 100       59 if (my $description = $self->stash('description')) {
297 12         188 $string .= $self->tag(
298             'meta',
299             name => 'description',
300             content => $description
301             );
302             }
303              
304 16         1304 my $meta_from_config = $self->config('meta');
305 16 50       55 $meta_from_config = [$meta_from_config]
306             unless ref $meta_from_config eq 'ARRAY';
307              
308 16         48 foreach my $meta (@$meta_from_config) {
309 0         0 $string .= $self->tag('meta' => %$meta);
310             }
311              
312 16         58 return Mojo::ByteStream->new($string);
313             }
314 6         93 );
315              
316             $app->helper(
317             css => sub {
318 16     16   326 my $self = shift;
319              
320 16         33 my $string = '';
321              
322 16         61 my $css_from_config = $self->config('css');
323 16 50       53 $css_from_config = [$css_from_config]
324             unless ref $css_from_config eq 'ARRAY';
325              
326 16         38 foreach my $css (@$css_from_config) {
327 0         0 $string .= $self->stylesheet($css);
328             }
329              
330 16         52 return Mojo::ByteStream->new($string);
331             }
332 6         91 );
333              
334             $app->helper(
335             js => sub {
336 16     16   417 my $self = shift;
337              
338 16         31 my $string = '';
339              
340 16         65 my $js_from_config = $self->config('js');
341 16 50       54 $js_from_config = [$js_from_config]
342             unless ref $js_from_config eq 'ARRAY';
343              
344 16         40 foreach my $js (@$js_from_config) {
345 0         0 $string .= $self->javascript($js);
346             }
347              
348 16         47 return Mojo::ByteStream->new($string);
349             }
350 6         92 );
351              
352             $app->helper(
353             href_to_rss => sub {
354 35     35   456 my $self = shift;
355              
356 35         128 return $self->url_for('index', format => 'rss')->to_abs;
357             }
358 6         87 );
359              
360             $app->helper(
361             link_to_rss => sub {
362 1     1   16 my $self = shift;
363              
364 1         9 return $self->link_to($self->href_to_rss => @_);
365             }
366 6         90 );
367              
368             $app->helper(
369             href_to_comments_rss => sub {
370 18     18   280 my $self = shift;
371              
372 18         60 return $self->url_for('comments', format => 'rss')->to_abs;
373             }
374 6         89 );
375              
376             $app->helper(
377             link_to_comments_rss => sub {
378 1     1   1230 my $self = shift;
379              
380 1         10 return $self->link_to($self->href_to_comments_rss => @_);
381             }
382 6         92 );
383              
384             $app->helper(
385             menu => sub {
386 16     16   244 my $self = shift;
387              
388 16         31 my @links;
389              
390 16         84 my $menu = $self->config('menu');
391              
392 16         65 for (my $i = 0; $i < @$menu; $i += 2) {
393 48         9262 my $title = $menu->[$i];
394 48         102 my $href = $menu->[$i + 1];
395              
396 48         344 push @links, $self->link_to($href => sub {$title});
  48         13270  
397             }
398              
399 16         4918 return Mojo::ByteStream->new(join ' ' => @links);
400             }
401 6         124 );
402              
403             $app->helper(
404             link_to_home => sub {
405 17     17   814 my $self = shift;
406              
407             return $self->link_to(
408             'root' => {format => undef},
409             title => $self->config('title'),
410 17         6167 rel => 'home' => sub { $self->config('title') }
411 17         92 );
412             }
413 6         110 );
414              
415             $app->helper(
416             link_to_bootylicious => sub {
417 1     1   1189 my $self = shift;
418              
419             return $self->link_to('https://github.com/vti/bootylicious' => title =>
420 1         11 'Powered by Bootylicious!' => sub {'Bootylicious'});
  1         127  
421             }
422 6         148 );
423              
424             $app->helper(
425             powered_by => sub {
426 1     1   368 my $self = shift;
427              
428             return $self->link_to('https://github.com/vti/bootylicious' =>
429 1         8 sub {'Powered by Bootylicious'});
  1         124  
430              
431             }
432 6         98 );
433              
434             $app->helper(
435             generator => sub {
436 18     18   15318 my $self = shift;
437              
438 18         94 return Mojo::ByteStream->new('Bootylicious ' . $Bootylicious::VERSION);
439             }
440 6         145 );
441              
442             $app->helper(
443             link_to_archive => sub {
444 0     0   0 my $self = shift;
445 0         0 my ($year, $month) = @_;
446              
447 0         0 my @months = (
448             qw/January February March April May July June August September October November December/
449             );
450 0         0 my $title = $months[$month - 1] . ' ' . $year;
451             return $self->link_to(
452             'articles',
453             { year => $year,
454             month => $month
455 0         0 } => sub {$title}
456 0         0 );
457             }
458 6         104 );
459              
460             $app->helper(
461             gravatar => sub {
462 2     2   16856 my $self = shift;
463 2         6 my $email = shift;
464              
465 2         25 my %attrs = (
466             class => 'gravatar',
467             width => 40,
468             height => 40
469             );
470              
471 2 100       25 return $self->tag(
472             'img',
473             src =>
474             'http://www.gravatar.com/avatar/00000000000000000000000000000000?s=40',
475             %attrs
476             ) unless $email;
477              
478 1         2 $email = lc $email;
479 1         4 $email =~ s/^\s+//;
480 1         4 $email =~ s/\s+$//;
481              
482 1         4 my $hash = Mojo::ByteStream->new($email)->md5_sum;
483              
484 1         17 my $url = "http://www.gravatar.com/avatar/$hash?s=40";
485              
486 1         11 return $self->tag(
487             'img',
488             src => $url,
489             %attrs,
490             @_
491             );
492             }
493 6         96 );
494              
495             $app->helper(
496             href_to_comments => sub {
497 1     1   12 my $self = shift;
498 1         2 my $article = shift;
499              
500 1         7 return $self->href_to_article($article)->fragment('comments');
501             }
502 6         92 );
503              
504             $app->helper(
505             href_to_comment => sub {
506 0     0   0 my $self = shift;
507 0         0 my $comment = shift;
508              
509 0         0 return $self->href_to_article($comment->article)
510             ->fragment('comment-' . $comment->number);
511             }
512 6         92 );
513              
514             $app->helper(
515             link_to_comment => sub {
516 0     0   0 my $self = shift;
517 0         0 my $comment = shift;
518              
519             return $self->link_to($self->href_to_comment($comment) =>
520 0         0 sub { $comment->article->title });
  0         0  
521             }
522 6         132 );
523              
524             $app->helper(
525             link_to_comments => sub {
526 2     2   26 my $self = shift;
527 2         5 my $article = shift;
528              
529 2         9 my $href = $self->href_to_article($article);
530              
531             return $self->link_to(
532 2         128 $href->fragment('comment-form') => sub {'No comments'})
533 2 50       804 unless $article->comments->size;
534              
535             return $self->link_to($href->fragment('comments') =>
536 0         0 sub { 'Comments (' . $article->comments->size . ') '; });
  0         0  
537             }
538 6         97 );
539              
540             $app->helper(
541             comments_enabled => sub {
542 21 50   21   15691 shift->config('comments_enabled') ? 1 : 0;
543             }
544 6         116 );
545             }
546              
547             sub _parse_tag {
548 0     0     my $content_ref = shift;
549 0           my ($tag, $html) = @_;
550              
551 0   0       $html ||= $tag;
552              
553 0           my $tags = $$content_ref =~ s{\s*\[$tag\]\s*}{<$html>}xmsg;
554 0           $tags -= $$content_ref =~ s{\s*\[/$tag\]\s*}{}xmsg;
555 0           $$content_ref .= "" while $tags--;
556             }
557              
558             1;