File Coverage

blib/lib/StaticVolt.pm
Criterion Covered Total %
statement 108 114 94.7
branch 13 22 59.0
condition 3 6 50.0
subroutine 21 21 100.0
pod 2 2 100.0
total 147 165 89.0


line stmt bran cond sub pod time code
1             # ABSTRACT: Static website generator
2              
3             package StaticVolt;
4             {
5             $StaticVolt::VERSION = '1.00';
6             }
7              
8 4     4   97130 use strict;
  4         9  
  4         168  
9 4     4   24 use warnings;
  4         7  
  4         130  
10              
11 4     4   29 use Cwd qw( getcwd );
  4         7  
  4         246  
12 4     4   3971 use File::Copy qw( copy );
  4         20546  
  4         320  
13 4     4   32 use File::Find;
  4         9  
  4         264  
14 4     4   23 use File::Path qw( mkpath rmtree );
  4         7  
  4         224  
15 4     4   22 use File::Spec;
  4         8  
  4         85  
16 4     4   3769 use FindBin;
  4         4327  
  4         354  
17 4     4   9843 use Template;
  4         118268  
  4         152  
18 4     4   3830 use YAML;
  4         39271  
  4         311  
19              
20 4     4   38 use base qw( StaticVolt::Convertor );
  4         8  
  4         2443  
21              
22 4     4   2017 use StaticVolt::Convertor::Markdown;
  4         15  
  4         152  
23 4     4   2851 use StaticVolt::Convertor::Textile;
  4         17  
  4         5765  
24              
25             sub new {
26 5     5 1 1015 my ( $class, %config ) = @_;
27              
28 5         32 my %config_defaults = (
29             'includes' => '_includes',
30             'layouts' => '_layouts',
31             'source' => '_source',
32             'destination' => '_site',
33             );
34              
35 5         22 for my $config_key ( keys %config_defaults ) {
36 20   66     67 $config{$config_key} = $config{$config_key}
37             || $config_defaults{$config_key};
38 20         80 $config{$config_key} = File::Spec->canonpath( $config{$config_key} );
39             }
40              
41 5         46 return bless \%config, $class;
42             }
43              
44             sub _clean_destination {
45 2     2   4 my $self = shift;
46              
47 2         14 my $destination = $self->{'destination'};
48 2         1973 rmtree $destination;
49              
50 2         6 return;
51             }
52              
53             sub _traverse_files {
54 8     8   13 my $self = shift;
55              
56 8         12 push @{ $self->{'files'} }, $File::Find::name;
  8         24  
57              
58 8         10802 return;
59             }
60              
61             sub _gather_files {
62 2     2   6 my $self = shift;
63              
64 2         6 my $source = $self->{'source'};
65 2     8   191 find sub { _traverse_files $self }, $source;
  8         27  
66              
67 2         14 return;
68             }
69              
70             sub _extract_file_config {
71 4     4   13 my ( $self, $fh_source_file ) = @_;
72              
73 4         22 my $delimiter = qr/^---\n$/;
74 4 50       133 if ( <$fh_source_file> =~ $delimiter ) {
75 4         9 my @yaml_lines;
76 4         21 while ( my $line = <$fh_source_file> ) {
77 8 100       36 if ( $line =~ $delimiter ) {
78 4         10 last;
79             }
80 4         16 push @yaml_lines, $line;
81             }
82              
83 4         33 return Load join '', @yaml_lines;
84             }
85             }
86              
87             sub compile {
88 2     2 1 2059 my $self = shift;
89              
90 2         11 $self->_clean_destination;
91 2         11 $self->_gather_files;
92              
93 2         7 my $source = $self->{'source'};
94 2         7 my $destination = $self->{'destination'};
95 2         5 for my $source_file ( @{ $self->{'files'} } ) {
  2         8  
96 8         2622 my $destination_file = $source_file;
97 8         800 $destination_file =~ s/^$source/$destination/;
98 8 100       696 if ( -d $source_file ) {
99 4         988 mkpath $destination_file;
100 4         15 next;
101             }
102              
103 4 50       187 open my $fh_source_file, '<', $source_file
104             or die "Failed to open $source_file for input: $!";
105 4         23 my $file_config = $self->_extract_file_config($fh_source_file);
106              
107             # For files that do not have a configuration defined, copy them over
108 4 50       38935 unless ($file_config) {
109 0         0 copy $source_file, $destination_file;
110 0         0 next;
111             }
112              
113 4         29 my ($extension) = $source_file =~ m/\.(.+?)$/;
114              
115             # If file does not have a registered convertor and is not an HTML file,
116             # copy the file over to the destination and skip current loop iteration
117 4 50 33     40 if ( !$self->has_convertor($extension) && $extension ne 'html' ) {
118 0         0 copy $source_file, $destination_file;
119 0         0 next;
120             }
121              
122             # Only files that have a registered convertor need to be handled
123              
124 4         24 $destination_file =~ s/\..+?$/.html/; # Change extension to .html
125              
126 4         13 my $file_layout = $file_config->{'layout'};
127 4         13 my $includes = $self->{'includes'};
128 4         10 my $layouts = $self->{'layouts'};
129 4         175 my $abs_include_path = File::Spec->catfile( getcwd, $includes );
130 4         51 my $abs_layout_path =
131             File::Spec->catfile( getcwd, $layouts, $file_layout );
132 4         55 my $template = Template->new(
133             'INCLUDE_PATH' => $abs_include_path,
134             'WRAPPER' => $abs_layout_path,
135             'ABSOLUTE' => 1,
136             );
137              
138 4         441939 my $source_file_content = do { local $/; <$fh_source_file> };
  4         19  
  4         208  
139 4         8 my $converted_content;
140 4 50       20 if ( $extension eq 'html' ) {
141 0         0 $converted_content = $source_file_content;
142             }
143             else {
144 4         38 $converted_content =
145             $self->convert( $source_file_content, $extension );
146             }
147              
148 4         11022 $file_config->{sv_rel_base} = $self->_relative_path ( $destination_file );
149              
150 4 50       635 open my $fh_destination_file, '>', $destination_file
151             or die "Failed to open $destination_file for output: $!";
152 4 50       18 if ($file_layout) {
153 4 50       32 $template->process( \$converted_content, $file_config,
154             $fh_destination_file )
155             or die $template->error;
156             }
157             else {
158 0         0 print $fh_destination_file $converted_content;
159             }
160              
161 4         1763455 close $fh_source_file;
162 4         2205 close $fh_destination_file;
163             }
164             }
165              
166              
167             sub _relative_path {
168              
169 10     10   2578 my ($self,$dest_file) = @_;
170              
171 10         186 my ($dummy1,$dest_file_dir,$dummy2) = File::Spec->splitpath( $dest_file );
172              
173 10         2734 my $rel_path = File::Spec->abs2rel ( $self->{'destination'},
174             $dest_file_dir );
175              
176 10 50       42 $rel_path .= "/" if $rel_path;
177              
178 10         48 return $rel_path;
179              
180             };
181              
182             1;
183              
184             __END__