File Coverage

blib/lib/Riji/Model/Article.pm
Criterion Covered Total %
statement 27 56 48.2
branch 0 10 0.0
condition 0 2 0.0
subroutine 9 16 56.2
pod 1 3 33.3
total 37 87 42.5


line stmt bran cond sub pod time code
1             package Riji::Model::Article;
2 1     1   424 use feature ':5.10';
  1         3  
  1         79  
3 1     1   7 use strict;
  1         2  
  1         18  
4 1     1   5 use warnings;
  1         2  
  1         37  
5              
6 1     1   6 use Path::Tiny;
  1         2  
  1         45  
7 1     1   21 use YAML::Tiny ();
  1         2  
  1         28  
8 1     1   580 use Text::Markup::Any ();
  1         1016  
  1         31  
9 1     1   534 use Text::Xslate;
  1         9922  
  1         52  
10              
11 1     1   8 use Mouse;
  1         2  
  1         5  
12              
13             has file => (
14             is => 'rw',
15             required => 1,
16             );
17              
18             has blog => (
19             is => 'ro',
20             isa => 'Riji::Model::Blog',
21             required => 1,
22             handles => [qw/base_dir fqdn author article_dir site_url repo/],
23             );
24              
25             has page => (
26             is => 'ro',
27             isa => 'Int',
28             );
29              
30             has markupper => (
31             is => 'ro',
32             isa => 'Text::Markup::Any',
33             default => sub {
34             my $markupper = Riji->config->{markup} || 'Text::Markdown::Discount';
35             my $obj = Text::Markup::Any->new($markupper);
36             Text::Markdown::Discount::with_html5_tags() if $markupper eq 'Text::Markdown::Discount';
37             $obj;
38             },
39             handles => [qw/markup/],
40             );
41              
42             has article_ext => (is => 'ro', default => 'md');
43              
44             has file_path => (
45             is => 'ro',
46             lazy => 1,
47             default => sub {
48             my $self = shift;
49             path($self->base_dir, $self->article_dir, $self->file);
50             },
51             );
52              
53             has content_raw => (
54             is => 'ro',
55             lazy => 1,
56             default => sub {
57             shift->file_path->slurp_utf8;
58             },
59             );
60              
61             has body => (is => 'rw');
62              
63             has html_body => (
64             is => 'ro',
65             lazy => 1,
66             default => sub {
67             my $self = shift;
68              
69             my $key = $self->isa('Riji::Model::Entry') ? 'entry' : 'article';
70             my $body = $self->_pre_proccessor->render_string($self->body, {
71             $key => $self,
72             blog => $self->blog,
73             page => $self->page,
74             });
75             $self->markup($body);
76             },
77             );
78              
79             has html_body_without_title => (
80             is => 'ro',
81             lazy => 1,
82             default => sub {
83             my $html = shift->html_body;
84             $html =~ s!\A\s*!!ms;
85             $html;
86             },
87             );
88              
89             has site_path => (
90             is => 'ro',
91             lazy => 1,
92             default => sub {
93             my $self = shift;
94              
95             my $path = '/' . $self->file_path->relative(path($self->base_dir, $self->article_dir));
96             my $ext = quotemeta $self->article_ext;
97             $path =~ s/\.$ext$//;
98             $path .= '.' . $self->page if $self->page;
99             $path . '.html';
100             },
101             );
102              
103             has url => (
104             is => 'ro',
105             lazy => 1,
106             default => sub {
107             my $self = shift;
108             my $root = $self->site_url;
109             $root =~ s!/+$!!;
110             $root . $self->site_path;
111             },
112             );
113 0     0 0   sub permalink { goto \&url }
114              
115             #############
116             # Meta datas:
117             has title => (
118             is => 'ro',
119             lazy => 1,
120             default => sub {
121             my $self = shift;
122             $self->header('title') // sub {
123             my $prev;
124             for my $line ( split /\r?\n/, $self->body ){
125             if ( $line =~ /^#/ ){
126             $line =~ s/^[#\s]+//;
127             $line =~ s/[#\s]+$//;
128             return $line;
129             }
130             if ( $line =~ /^(?:(?:-+)|(?:=+))$/ ) {
131             return $prev if $prev && $prev =~ /[^\s]/;
132             }
133             $prev = $line;
134             }
135             my $ext = quotemeta $self->article_ext;
136             my $title = $self->file_path->basename;
137             $title =~ s/\.$ext$//;
138             $title =~ s/-/ /g;
139             $title;
140             }->() // 'unknown';
141             },
142             );
143              
144             has is_draft => (
145             is => 'ro',
146             lazy => 1,
147             default => sub {
148             shift->header('draft');
149             },
150             );
151              
152             has raw_tags => (
153             is => 'ro',
154             lazy => 1,
155             default => sub {
156             my $tags = shift->header('tags');
157             return [] unless $tags;
158             $tags = [split /[,\s]+/, $tags] unless ref $tags;
159             $tags;
160             },
161             );
162              
163             has tags => (
164             is => 'ro',
165             isa => 'ArrayRef[Riji::Model::Tag]',
166             lazy => 1,
167             default => sub {
168             my $self = shift;
169             [map {$self->blog->tag($_)} @{ $self->raw_tags }];
170             },
171             );
172              
173             has template => (
174             is => 'ro',
175             lazy => 1,
176             default => sub {
177             shift->header('template');
178             },
179             );
180              
181             has paginate => (
182             is => 'ro',
183             lazy => 1,
184             default => sub {
185             shift->header('paginate');
186             },
187             );
188              
189 1     1   1743 no Mouse;
  1         2  
  1         5  
190              
191             sub BUILD {
192 0     0 1   my $self = shift;
193              
194 0           my $ext = $self->article_ext;
195 0 0         unless ($self->file =~ /\.\Q$ext\E$/) {
196 0           $self->file($self->file . ".$ext");
197             }
198 0 0         return unless -f -r $self->file_path;
199 0           $self->_parse_content;
200             }
201              
202             sub header {
203 0     0 0   my ($self, $key) = @_;
204 0 0         if (defined $key){
205 0           return $self->{headers}{$key};
206             }
207             else{
208 0           return $self->{headers};
209             }
210             }
211              
212             sub _parse_content {
213 0     0     my $self = shift;
214 0           my $content_raw = $self->content_raw;
215 0           $content_raw =~ s/\A---\r?\n//ms;
216 0           my ($header_raw, $body) = split /^---\n/ms, $content_raw, 2;
217              
218 0           my $headers = {};
219 0 0         if (defined $body) {
220 0           local $@;
221 0   0       $headers = eval {
222             YAML::Tiny::Load($header_raw);
223             } || {};
224 0 0         if ($@) {
225 0           ($header_raw, $body) = ('', $self->content_raw);
226             }
227             }
228             else {
229 0           ($header_raw, $body) = ('', $header_raw);
230             }
231              
232 0           $self->body($body);
233 0           $self->{header_raw} = $header_raw;
234 0           $self->{headers} = $headers;
235 0           $self;
236             }
237              
238             sub _pre_proccessor {
239             state $xslate = Text::Xslate->new(
240             type => 'text',
241             path => Riji->template_dir,
242             function => {
243 0     0     uri_for => sub { Riji->context->uri_for(@_) },
244 0     0     config => sub { Riji->config },
245 0     0     Riji->get_functions,
246             }
247             );
248             }
249              
250             1;