File Coverage

blib/lib/Blio.pm
Criterion Covered Total %
statement 4 6 66.6
branch n/a
condition n/a
subroutine 2 2 100.0
pod n/a
total 6 8 75.0


line stmt bran cond sub pod time code
1             package Blio;
2 9     9   880837 use 5.010;
  9         28  
  9         456  
3              
4             # ABSTRACT: domms blogging "engine"
5              
6             our $VERSION = 2.003;
7              
8 9     9   10921 use Moose;
  0            
  0            
9             use MooseX::Types::Path::Class;
10             use Path::Class;
11             use Path::Class::Iterator;
12             use Template;
13             use File::ShareDir qw(dist_dir);
14             use DateTime;
15              
16             use Blio::Node;
17              
18             with 'MooseX::Getopt';
19             with 'MooseX::SimpleConfig';
20              
21             has '+configfile' => ( default => 'blio.ini' );
22             has 'source_dir' => (
23             is => 'ro',
24             isa => 'Path::Class::Dir',
25             required => 1,
26             coerce => 1,
27             lazy_build => 1
28             );
29             sub _build_source_dir {
30             my $self = shift;
31             return Path::Class::Dir->new->subdir('src');
32             }
33              
34             has 'output_dir' => (
35             is => 'ro',
36             isa => 'Path::Class::Dir',
37             required => 1,
38             coerce => 1,
39             lazy_build => 1
40             );
41             sub _build_output_dir {
42             my $self = shift;
43             return Path::Class::Dir->new->subdir('out');
44             }
45              
46             has 'template_dir' => (
47             is => 'ro',
48             isa => 'Path::Class::Dir',
49             required => 1,
50             coerce => 1,
51             lazy_build => 1
52             );
53             sub _build_template_dir {
54             my $self = shift;
55             return Path::Class::Dir->new->subdir('templates');
56             }
57              
58             has 'name' => (is=>'ro',isa=>'Str',default=>'Blio',required=>1);
59             has 'site_url' => (is=>'ro',isa=>'Str',required=>0);
60             has 'site_author' => (is=>'ro',isa=>'Str',required=>0);
61             has 'language' => (is=>'ro',isa=>'Str',default=>'en',required=>1);
62             has 'converter' => (is=>'ro',isa=>'Maybe[Str]',default=>undef,required=>1);
63             has 'thumbnail' => (is=>'ro',isa=>'Int',default=>300,required=>1);
64             has 'tags' => (is=>'ro',isa=>'Bool',default=>0);
65             has 'schedule' => (is=>'ro',isa=>'Bool',default=>0);
66              
67             has 'force' => (is=>'ro',isa=>'Bool',default=>0);
68             has 'quiet' => (is=>'ro',isa=>'Bool',default=>0);
69              
70             has 'nodes_by_url' => ( is => 'ro', isa => 'HashRef', default => sub { {} } ,traits => [ 'NoGetopt' ]);
71             has 'tree' => (
72             is => 'ro',
73             isa => 'ArrayRef[Blio::Node]',
74             default => sub { [] },
75             traits => ['Array', 'NoGetopt'],
76             handles => { add_top_node => 'push', },
77             );
78             has 'tt' => (
79             is=>'ro',
80             isa=>'Template',
81             lazy_build => 1,
82             traits => [ 'NoGetopt' ],
83             );
84             sub _build_tt {
85             my $self = shift;
86             return Template->new({
87             OUTPUT_PATH=>$self->output_dir->stringify,
88             INCLUDE_PATH=>[$self->template_dir->stringify, dir(dist_dir('Blio'),'templates')->stringify],
89             WRAPPER=>'wrapper.tt',
90             ENCODING => 'UTF8',
91             });
92             }
93              
94             has 'nodes_by_date' => (is=>'ro', isa=>'ArrayRef',lazy_build=>1,traits => [ 'NoGetopt' ]);
95             sub _build_nodes_by_date {
96             my $self = shift;
97              
98             my @sorted =
99             map { $_->[0] }
100             sort { $b->[1] <=> $a->[1] }
101             map { [$_ => $_->date->epoch] }
102             values %{$self->nodes_by_url};
103             return \@sorted;
104             }
105             has 'stash' => (is=>'ro',isa=>'HashRef',default=>sub {{}},traits => [ 'NoGetopt' ]);
106              
107             has 'tagindex' => (
108             is=>'rw',
109             isa=>'Blio::Node',
110             lazy_build=>1,
111             traits => [ 'NoGetopt' ],
112             );
113             sub _build_tagindex {
114             my $self = shift;
115             my $tagindex = Blio::Node->new(
116             base_dir => $self->source_dir,
117             source_file => $0,
118             id=>'tags.html',
119             url=>'tags.html',
120             title=>'Tags',
121             date=>DateTime->now,
122             content=>'',
123             );
124             $self->nodes_by_url->{'tags.html'}=$tagindex;
125             return $tagindex;
126             }
127              
128             sub run {
129             my $self = shift;
130              
131             $self->collect;
132             $self->write;
133             }
134              
135             sub collect {
136             my $self = shift;
137             my $iterator = Path::Class::Iterator->new(
138             root => $self->source_dir,
139             breadth_first => 1,
140             );
141              
142             my $schedule = $self->schedule;
143             my $now = DateTime->now;
144              
145             until ( $iterator->done ) {
146             my $file = $iterator->next;
147             next if -d $file;
148             next unless $file =~ /\.txt$/;
149              
150             my $node = Blio::Node->new_from_file( $self, $file );
151             if ($schedule && $node->date > $now) {
152             say "skipping ".$node->id." (scheduled for ".$node->date." but now is ".$now.")";
153             next;
154             }
155             $self->nodes_by_url->{ $node->url } = $node;
156              
157             if ( $node->source_file->parent->stringify eq
158             $self->source_dir->stringify ) {
159             $self->add_top_node($node);
160             }
161             else {
162             my $possible_parent_url = $node->possible_parent_url;
163             if ( my $parent = $self->nodes_by_url->{$possible_parent_url} ) {
164             $node->parent($parent);
165             $parent->add_child($node);
166             #say $node->url .' is child of '.$parent->url;
167             }
168             else {
169             say "Cannot find parent, but not a root node: " . $node->url;
170             say "For each subdirectoy, you need a file in the parent directory";
171             say "with the name of the subdirectory and .txt extension";
172             say "Need a file called " . $node->source_file->parent->stringify . '.txt';
173             exit 0;
174             }
175             }
176             }
177              
178             unless ($self->nodes_by_url->{'index.html'}) {
179             my $index = Blio::Node->new(
180             base_dir => $self->source_dir,
181             source_file => $0,
182             id=>'index.html',
183             url=>'index.html',
184             title=>'Index',
185             date=>DateTime->now,
186             content=>'',
187             );
188             $self->nodes_by_url->{'index.html'}=$index;
189             $index->children($self->tree);
190             }
191             }
192              
193             sub write {
194             my $self = shift;
195              
196             while (my ($url, $node) = each %{$self->nodes_by_url}) {
197             say "writing $url" unless $self->quiet;
198             if ($node->paged_list) {
199             $node->write_paged_list($self);
200             }
201             else {
202             $node->write($self);
203             }
204             }
205              
206             }
207              
208             __PACKAGE__->meta->make_immutable;
209             1;
210              
211             __END__
212              
213             =pod
214              
215             =encoding UTF-8
216              
217             =head1 NAME
218              
219             Blio - domms blogging "engine"
220              
221             =head1 VERSION
222              
223             version 2.003
224              
225             =head1 SYNOPSIS
226              
227             Backend for the C<blio.pl> command. See L<blio.pl> and/or C<perldoc blio.pl> for details.
228              
229             more docs pending...
230              
231             docs provided by gabor, need to be integrated:
232              
233             =head1 CONFIGURATION
234              
235             The configuration parameters can be provided either in the configuration file that defauts to blio.ini
236             or on the command line.
237              
238             The configuration file can look like this:
239              
240             name=Test site
241             source_dir=src/
242             output_dir=.
243             template_dir=templates/
244              
245             The configureation file must exists.
246             Otherwise you will get a warning like this:
247              
248             Specified configfile 'blio.ini' does not exist, is empty, or is not readable
249              
250             If no source_dir provided or there is no src/ directory, you get this exception:
251              
252             Can't call method "done" on an undefined value at .../Blio.pm line 137.
253              
254             =over 4
255              
256             =item name
257              
258             The name of the site in the title of the pages. Default to Blio
259              
260             =item source_dir
261              
262             The directory where the source files are. Each page of the site has a corresponding source file with .txt extension.
263             Defaults to the C<src/> directory relative to the current working directory where your run the C<build.pl> script.
264              
265             =item output_dir
266              
267             Directory where the generated html files should go. Defaults to C<out/> relative to the current working directory.
268              
269             =item template_dir
270              
271             The location of the template files. Defaults to C<templates/> relative to the current working directory.
272             As a fallback, there is a set of templates provided by Blio. They come in the share/templates directory of
273             the distribution and are installed along the module.
274              
275             =item site_url
276              
277             =item site_author
278              
279             =item converter
280              
281             =item thumbnail
282              
283             =back
284              
285             TODO - there are more fields that need explanation.
286              
287             =head2 Source directory hierarchy
288              
289             The source directory defined using the C<source_dir> paramater can havs subdirectories, but each subdirectory needs
290             a 'parent' page. The name of the parent page is the same as the name of the subdirectory with the additional .txt
291             extentsion. So if you'd like to have a C<src/project/> subdriectory, you also need to have a page called
292             C<src/project.txt>.
293              
294             If there is no index.txt in the src/ directory, Blio will generate a default index.html file.
295             This is not the case with subdirectories.
296              
297             =head2 Source files
298              
299             Each source file has a txt extension. It has several lines of header and a body.
300             The module that represents each file is L<Blio::Node>.
301              
302             title: The Project
303             date: 2013-02-10T00:27:53
304             language: en
305             converter: textile
306             tags: Perl
307              
308             This is the project page.
309              
310             The only required entry in the header is the C<title>.
311              
312             TODO - there are more fields that need explanation.
313              
314             =head1 AUTHOR
315              
316             Thomas Klausner <domm@cpan.org>
317              
318             =head1 COPYRIGHT AND LICENSE
319              
320             This software is copyright (c) 2013 by Thomas Klausner.
321              
322             This is free software; you can redistribute it and/or modify it under
323             the same terms as the Perl 5 programming language system itself.
324              
325             =cut