File Coverage

blib/lib/MasonX/StaticBuilder.pm
Criterion Covered Total %
statement 9 9 100.0
branch n/a
condition n/a
subroutine 3 3 100.0
pod n/a
total 12 12 100.0


line stmt bran cond sub pod time code
1             package MasonX::StaticBuilder;
2              
3 2     2   29632 use strict;
  2         4  
  2         74  
4 2     2   10 use warnings;
  2         3  
  2         101  
5              
6             our $VERSION = '0.04';
7              
8 2     2   11 use base qw(Class::Accessor);
  2         7  
  2         1510  
9             MasonX::StaticBuilder->mk_accessors(qw(input_dir));
10              
11             use Carp;
12             use File::Find::Rule;
13             use MasonX::StaticBuilder::Component;
14              
15             =head1 NAME
16              
17             MasonX::StaticBuilder -- Build a static website from Mason components
18              
19             =head1 SYNOPSIS
20              
21             use MasonX::StaticBuilder;
22             my $tree = MasonX::StaticBuilder->new($input_dir);
23             $tree->write($output_dir, %args);
24              
25             =head1 DESCRIPTION
26              
27             Ever had to develop a website to deploy on a host that doesn't have
28             Mason? I have. The most crazy-making thing about it is that you
29             desparately want to use all the Mason tricks you're used to, but you
30             can't even do:
31              
32             <& header &>
33              
34             AUGH!
35              
36             Well, this fixes it.
37              
38             Do your work in one directory, using whatever Mason stuff you want.
39             Then use MasonX::StaticBuilder to build a static website from it.
40              
41             (Obviously you can also use this for non-web purposes.)
42              
43             The following Mason features are tested and known to work in this
44             release:
45              
46             =over 4
47              
48             =item *
49              
50             Evaluation of expressions in <% %>
51              
52             =item *
53              
54             Args blocks
55              
56             =item *
57              
58             Init blocks
59              
60             =item *
61              
62             Inclusion of components using <& &>
63              
64             =item *
65              
66             Autohandlers
67              
68             =back
69              
70             The following are not known to work (and I'm not sure they even make
71             sense):
72              
73             =over 4
74              
75             =item *
76              
77             dhandlers
78              
79             =back
80              
81             Anything not on that list means it's not something I regularly use, and
82             I don't have a test for it yet. Additions to the test suite to cover
83             these other areas of Mason functionality are very welcome.
84              
85             =head1 METHODS
86              
87             =head2 new()
88              
89             A simple constructor. Pass it the directory where the components are to
90             be found.
91              
92             Note: if the directory doesn't exist, or whatever, this will return
93             undef.
94              
95             =begin testing
96              
97             use_ok('MasonX::StaticBuilder');
98             my $t = MasonX::StaticBuilder->new(".");
99             isa_ok($t, 'MasonX::StaticBuilder');
100             can_ok($t, qw(input_dir));
101              
102             my $no = MasonX::StaticBuilder->new("this/directory/does/not/exist");
103             is($no, undef, "return undef if dir doesn't exist");
104              
105             =end testing
106              
107             =cut
108              
109             sub new {
110             my ($class, $input_dir) = @_;
111             if ($input_dir && -e $input_dir && -d $input_dir) {
112             $input_dir = File::Spec->rel2abs($input_dir);
113             my $self = {};
114             bless $self, $class;
115             $self->input_dir($input_dir);
116             return $self;
117             } else {
118             return undef;
119             }
120             }
121              
122             =head2 write()
123              
124             Expand the template directory and write it out to the specified output
125             directory, passing any additional args to the mason components it finds.
126              
127             =begin testing
128              
129             my $t = MasonX::StaticBuilder->new("t/test-input-dir");
130             system "rm -rf t/test-output-dir";
131             mkdir("t/test-output-dir");
132             $t->write("t/test-output-dir", foo => "bar");
133              
134             my %expected_contents = (
135             simple => "bugger all",
136             expr => 42,
137             args => "Foo is bar",
138             init => "Baz is quux",
139             "sub-component" => "bugger all",
140             "autohandler-dir/ahtest" => "This is a header",
141             "autohandler-dir/ahtest" => "autohandler goodness",
142             );
143              
144             foreach my $file (sort keys %expected_contents) {
145             my $fullfile = "t/test-output-dir/$file";
146             open FILE, "<", $fullfile;
147             local $/ = undef;
148             my $file_contents = ;
149             like(
150             $file_contents,
151             qr($expected_contents{$file}),
152             "File $file expanded correctly."
153             );
154             close FILE;
155             }
156              
157             =end testing
158              
159             =cut
160              
161             sub write {
162             my ($self, $outdir, @args) = @_;
163             my $rule = File::Find::Rule->file()
164             ->not_name("autohandler")
165             ->not_name("dhandler")
166             ->start($self->input_dir());
167             while (my $c = $rule->match()) {
168             next if $c =~ /\.svn/;
169             my $comp_name = $self->_get_comp_name($c);
170             my $component = MasonX::StaticBuilder::Component->new({
171             comp_root => $self->input_dir(),
172             comp_name => $comp_name,
173             });
174              
175             my $output = $component->fill_in(@args);
176             my $outfile = $outdir . $comp_name;
177              
178             # make sub-dirs if necessary
179             if ($comp_name =~ m([^/]/[^/]) ) {
180             my ($subdir, $file) = ($comp_name =~ m(^(.*)/(.*?)$));
181             unless (-d "$outdir/$subdir") {
182             if (mkdir("$outdir/$subdir")) {
183             $self->_write_file($outfile, $output);
184             } else {
185             carp "Can't create required subdirectory $outdir/$subdir: $!";
186             }
187             }
188             } else {
189             $self->_write_file($outfile, $output);
190             }
191             }
192             }
193              
194             sub _write_file {
195             my ($self, $outfile, $output) = @_;
196             open (OUT, ">", $outfile) or carp "Can't open output file $outfile: $!";
197             print OUT $output;
198             close OUT;
199             }
200              
201             sub _get_comp_name {
202             my ($self, $filename) = @_;
203             my $comp_root = $self->input_dir();
204             $filename =~ s/$comp_root//;
205             return $filename;
206             }
207              
208             =head1 BUGS
209              
210             I haven't tested a wide range of Mason functionality, just the stuff I
211             regularly use. Patches welcome.
212              
213             The best way to report bugs on this software is vy the CPAN RT system at
214             http://rt.cpan.org/
215              
216             =head1 AUTHOR
217              
218             Kirrily Robert, skud@cpan.org
219              
220             =head1 LICENSE
221              
222             This module is distributed under the GPL/Artistic dual license, and may
223             be used under the same terms as Perl itself.
224              
225             =cut
226              
227             1;