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   4008 use strict;
  5         8  
  5         195  
4 5     5   22 use warnings;
  5         8  
  5         156  
5              
6 5     5   23 use base 'Mojolicious::Plugin';
  5         5  
  5         505  
7              
8 5     5   27 use Mojo::ByteStream 'b';
  5         8  
  5         14833  
9              
10             sub register {
11 6     6 1 302 my ($self, $app) = @_;
12              
13 6         35 my $config = $app->config;
14              
15             $app->helper(
16             render_smart => sub {
17 11     11   458 my $self = shift;
18              
19 11         43 $app->plugins->emit_hook(before_render => $self);
20              
21 11 50       244 $self->render(@_) unless $self->res->code;
22             }
23 6         179 );
24              
25             $app->helper(
26             render_article_or_preview => sub {
27 3     3   1380 my $self = shift;
28 3         10 my $article = shift;
29              
30 3         37 my $parser = $self->parsers->{$article->format};
31 3   50     51 $parser ||= sub { $_[0] };
  3         56  
32              
33 3         32 my $cuttag = quotemeta $self->config->{cuttag};
34              
35 3         29 my $content = $article->content;
36              
37 3         6 my ($preview, $preview_link);
38 3 50       364 if ($content =~ s{^(.*?)\n$cuttag(?: (.*?))?(?:\n|\r|\n\r)}{}s) {
39 3         13 $preview = $1;
40 3   33     15 $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         183 '→ '
48             . $self->link_to_full_content($article,
49             $preview_link);
50             }
51             )
52 3 50       20 ) if $preview;
53              
54 0         0 return Mojo::ByteStream->new($parser->($content));
55             }
56 6         193 );
57              
58             $app->helper(
59             render_article => sub {
60 1     1   147 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         11 my $head = $article->content;
69 1         3 my $tail = '';
70 1 50       44 if ($head =~ s{(.*?)\n$cuttag.*?\n(.*)}{$1}s) {
71 1         3 $tail = $2;
72             }
73              
74 1         3 my $cuttag_anchor = '';
75              
76 1         1 my $string;
77 1         4 $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         129 );
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         108 );
101              
102             $app->helper(
103             article_author => sub {
104 7     7   22508 my $self = shift;
105 7         16 my $article = shift;
106              
107 7   33     97 return $article->author || $config->{author};
108             }
109 6         111 );
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         128 );
121              
122             $app->helper(
123             render_page => sub {
124 1     1   23 my $self = shift;
125 1         2 my $page = shift;
126              
127 1         11 my $parser = $self->parsers->{$page->format};
128 1   50     11 $parser ||= sub { $_[0] };
  1         3  
129              
130 1         7 my $string = $parser->($page->content);
131 1         10 return Mojo::ByteStream->new($string);
132             }
133 6         116 );
134              
135             $app->helper(
136             date => sub {
137 7     7   44 my $self = shift;
138 7         14 my $date = shift;
139 7         19 my $fmt = shift;
140              
141 7 50       61 return '' unless $date;
142              
143 7   33     51 $fmt ||= $config->{'datefmt'};
144              
145 7         57 return b($date->strftime($fmt))->decode('utf-8');
146             }
147 6         116 );
148 2     2   26 $app->helper(date_rss => sub { Mojo::Date->new($_[1]->epoch)->to_string }
149 6         112 );
150             $app->helper(
151             href_to_article => sub {
152 15     15   723 my $self = shift;
153 15         27 my $article = shift;
154              
155 15         121 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         110 );
165             $app->helper(
166             link_to_article => sub {
167 7     7   8687 my $self = shift;
168 7         15 my $article = shift;
169              
170 7         92 my $href = $self->href_to_article($article);
171              
172 7 50       5030 my $cb = ref $_[-1] eq 'CODE' ? pop : undef;
173              
174 7 50       48 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     170 return $self->link_to($href => $cb || sub { $article->title });
186             }
187 6         107 );
188             $app->helper(
189             link_to_full_content => sub {
190 3     3   102 my $self = shift;
191 3         9 my ($article, $preview_link) = @_;
192              
193 3         31 my $href = $self->href_to_article($article);
194 3         1808 $href->fragment('cut');
195              
196 3         56 return $self->link_to($href => sub {$preview_link});
  3         325  
197             }
198 6         109 );
199             $app->helper(
200             link_to_tag => sub {
201 25     25   1145 my $self = shift;
202 25         48 my $tag = shift;
203              
204 25 100       75 my $name = ref $tag ? $tag->name : $tag;
205              
206 25 100       207 my $cb = ref $_[-1] eq 'CODE' ? $_[-1] : sub {$name};
  24         13704  
207 25 100       88 my $args = ref $_[0] eq 'HASH' ? $_[0] : {};
208              
209 25         260 return $self->link_to(
210             tag => {tag => $name, format => 'html', %$args} => $cb);
211             }
212 6         105 );
213             $app->helper(
214             tags_links => sub {
215 7     7   1753 my $self = shift;
216 7         20 my $article = shift;
217              
218 7         14 my @links = map { $self->link_to_tag($_) } @{$article->tags};
  21         6798  
  7         55  
219              
220 7         2475 my $string = '';
221 7         38 $string .= join ', ' => @links;
222              
223 7         96 return Mojo::ByteStream->new($string);
224             }
225 6         103 );
226             $app->helper(
227             link_to_page => sub {
228 6     6   64 my $self = shift;
229 6         13 my $name = shift;
230              
231 6 100       28 my %args = ref $_[0] eq 'HASH' ? %{shift @_} : ();
  2         9  
232              
233 6         12 my $timestamp = shift;
234              
235 6   50     53 my $query = delete $args{query} || {};
236              
237 6 50       18 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         72 return $self->tag('span' => @_);
244             }
245             }
246 6         110 );
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         102 );
264              
265             $app->helper(
266             strings => sub {
267 27     27   122998 my $self = shift;
268              
269 27         147 my $string = $config->{'strings'}->{$_[0]};
270              
271 27         114 for (my $i = 0; $i < @_; $i++) {
272 28         388 $string =~ s/\[_$i\]/$_[$i]/;
273             }
274              
275 27         161 return $string;
276             }
277 6         157 );
278              
279 6         94 foreach my $name (qw/articles pages drafts/) {
280 18   100     256 my $option = $config->{"${name}_directory"} || '';
281             $app->helper(
282             "${name}_root" => sub {
283 16 50   16   472 ($option =~ m/^\//) ? $option : $app->home->rel_dir($option);
284             }
285 18         73 );
286             }
287              
288 6     0   110 $app->helper(page_limit => sub { $config->{pagelimit} });
  0         0  
289              
290             $app->helper(
291             meta => sub {
292 16     16   413 my $self = shift;
293              
294 16         41 my $string = '';
295              
296 16 100       84 if (my $description = $self->stash('description')) {
297 12         337 $string .= $self->tag(
298             'meta',
299             name => 'description',
300             content => $description
301             );
302             }
303              
304 16         1579 my $meta_from_config = $self->config('meta');
305 16 50       80 $meta_from_config = [$meta_from_config]
306             unless ref $meta_from_config eq 'ARRAY';
307              
308 16         56 foreach my $meta (@$meta_from_config) {
309 0         0 $string .= $self->tag('meta' => %$meta);
310             }
311              
312 16         71 return Mojo::ByteStream->new($string);
313             }
314 6         109 );
315              
316             $app->helper(
317             css => sub {
318 16     16   392 my $self = shift;
319              
320 16         39 my $string = '';
321              
322 16         89 my $css_from_config = $self->config('css');
323 16 50       85 $css_from_config = [$css_from_config]
324             unless ref $css_from_config eq 'ARRAY';
325              
326 16         60 foreach my $css (@$css_from_config) {
327 0         0 $string .= $self->stylesheet($css);
328             }
329              
330 16         73 return Mojo::ByteStream->new($string);
331             }
332 6         204 );
333              
334             $app->helper(
335             js => sub {
336 16     16   415 my $self = shift;
337              
338 16         33 my $string = '';
339              
340 16         85 my $js_from_config = $self->config('js');
341 16 50       87 $js_from_config = [$js_from_config]
342             unless ref $js_from_config eq 'ARRAY';
343              
344 16         50 foreach my $js (@$js_from_config) {
345 0         0 $string .= $self->javascript($js);
346             }
347              
348 16         72 return Mojo::ByteStream->new($string);
349             }
350 6         111 );
351              
352             $app->helper(
353             href_to_rss => sub {
354 35     35   572 my $self = shift;
355              
356 35         184 return $self->url_for('index', format => 'rss')->to_abs;
357             }
358 6         105 );
359              
360             $app->helper(
361             link_to_rss => sub {
362 1     1   18 my $self = shift;
363              
364 1         11 return $self->link_to($self->href_to_rss => @_);
365             }
366 6         103 );
367              
368             $app->helper(
369             href_to_comments_rss => sub {
370 18     18   336 my $self = shift;
371              
372 18         116 return $self->url_for('comments', format => 'rss')->to_abs;
373             }
374 6         98 );
375              
376             $app->helper(
377             link_to_comments_rss => sub {
378 1     1   1555 my $self = shift;
379              
380 1         17 return $self->link_to($self->href_to_comments_rss => @_);
381             }
382 6         104 );
383              
384             $app->helper(
385             menu => sub {
386 16     16   253 my $self = shift;
387              
388 16         30 my @links;
389              
390 16         137 my $menu = $self->config('menu');
391              
392 16         92 for (my $i = 0; $i < @$menu; $i += 2) {
393 48         9821 my $title = $menu->[$i];
394 48         114 my $href = $menu->[$i + 1];
395              
396 48         560 push @links, $self->link_to($href => sub {$title});
  48         14953  
397             }
398              
399 16         5186 return Mojo::ByteStream->new(join ' ' => @links);
400             }
401 6         118 );
402              
403             $app->helper(
404             link_to_home => sub {
405 17     17   1682 my $self = shift;
406              
407             return $self->link_to(
408             'root' => {format => undef},
409             title => $self->config('title'),
410 17         7266 rel => 'home' => sub { $self->config('title') }
411 17         158 );
412             }
413 6         96 );
414              
415             $app->helper(
416             link_to_bootylicious => sub {
417 1     1   1231 my $self = shift;
418              
419 1         131 return $self->link_to('https://github.com/vti/bootylicious' => title =>
420 1         17 'Powered by Bootylicious!' => sub {'Bootylicious'});
421             }
422 6         108 );
423              
424             $app->helper(
425             powered_by => sub {
426 1     1   397 my $self = shift;
427              
428 1         158 return $self->link_to('https://github.com/vti/bootylicious' =>
429 1         13 sub {'Powered by Bootylicious'});
430              
431             }
432 6         104 );
433              
434             $app->helper(
435             generator => sub {
436 18     18   12985 my $self = shift;
437              
438 18         156 return Mojo::ByteStream->new('Bootylicious ' . $Bootylicious::VERSION);
439             }
440 6         115 );
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 0         0 return $self->link_to(
452             'articles',
453             { year => $year,
454             month => $month
455             } => sub {$title}
456 0         0 );
457             }
458 6         106 );
459              
460             $app->helper(
461             gravatar => sub {
462 2     2   12607 my $self = shift;
463 2         3 my $email = shift;
464              
465 2         23 my %attrs = (
466             class => 'gravatar',
467             width => 40,
468             height => 40
469             );
470              
471 2 100       16 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         3 $email =~ s/^\s+//;
480 1         3 $email =~ s/\s+$//;
481              
482 1         3 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         8 return $self->tag(
487             'img',
488             src => $url,
489             %attrs,
490             @_
491             );
492             }
493 6         114 );
494              
495             $app->helper(
496             href_to_comments => sub {
497 1     1   11 my $self = shift;
498 1         1 my $article = shift;
499              
500 1         5 return $self->href_to_article($article)->fragment('comments');
501             }
502 6         112 );
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         99 );
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         102 );
523              
524             $app->helper(
525             link_to_comments => sub {
526 2     2   35 my $self = shift;
527 2         4 my $article = shift;
528              
529 2         15 my $href = $self->href_to_article($article);
530              
531 2         188 return $self->link_to(
532             $href->fragment('comment-form') => sub {'No comments'})
533 2 50       1106 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         118 );
539              
540             $app->helper(
541             comments_enabled => sub {
542 21 50   21   16988 shift->config('comments_enabled') ? 1 : 0;
543             }
544 6         108 );
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;