File Coverage

blib/lib/App/LinkSite.pm
Criterion Covered Total %
statement 48 50 96.0
branch 0 2 0.0
condition n/a
subroutine 16 18 88.8
pod 1 1 100.0
total 65 71 91.5


line stmt bran cond sub pod time code
1             =head1 NAME
2              
3             App::LinkSite - Create a website listing all of your links
4              
5             =head1 SYNOPIS
6              
7             (You probably want to just look at the L application.)
8              
9             =head1 DESCRIPTION
10              
11             The main driver class for App::LinkSite.
12              
13             =cut
14              
15 1     1   86846 use Feature::Compat::Class;
  1         488  
  1         3  
16              
17             class App::LinkSite {
18             our $VERSION = '0.1.1';
19 1     1   160 use strict;
  1         2  
  1         19  
20 1     1   3 use warnings;
  1         1  
  1         50  
21 1     1   5 use feature qw[say signatures];
  1         1  
  1         48  
22 1     1   3 no if $] >= 5.038, 'warnings', qw[experimental::signatures experimental::class];
  1         2  
  1         57  
23              
24 1     1   477 use Template;
  1         18103  
  1         29  
25 1     1   642 use JSON;
  1         10636  
  1         5  
26 1     1   880 use Path::Tiny;
  1         10113  
  1         55  
27 1     1   7 use File::Find;
  1         1  
  1         48  
28 1     1   4 use File::Basename;
  1         1  
  1         37  
29 1     1   3 use FindBin '$Bin';
  1         2  
  1         118  
30 1     1   481 use File::ShareDir 'dist_dir';
  1         24993  
  1         50  
31              
32 1     1   410 use App::LinkSite::Site;
  1         3  
  1         26  
33 1     1   352 use App::LinkSite::Link;
  1         2  
  1         28  
34 1     1   396 use App::LinkSite::Social;
  1         3  
  1         27  
35 1     1   371 use App::LinkSite::Section;
  1         2  
  1         1126  
36              
37             field $file :reader :param = 'links.json';
38             # Where to look for the templates.
39             # If we've been installed from CPAN, then File::Share::dist_name
40             # gives us the correct directory. Otherwise, just look in the local
41             # src directory. Note that dist_name() dies if the directory is not
42             # found - hence the use of eval.
43             field $src :reader :param = eval { dist_dir("App-LinkSite") } || "$Bin/../src";
44             field $out :reader :param = 'docs';
45             field $ga4 :reader :param = undef;
46             field $site :reader :param = undef;
47              
48             field $tt;
49              
50             ADJUST {
51             my $json = path($file)->slurp;
52             my $data = JSON->new->decode($json);
53              
54             $ga4 = $data->{ga4} // '';
55              
56             $tt = Template->new({
57             # Templates in the CPAN distro directory
58             INCLUDE_PATH => $src,
59             # Output in the data directory
60             OUTPUT_PATH => $out,
61             VARIABLES => {
62             ga4 => $ga4,
63             version => $VERSION,
64             }
65             });
66              
67             my $socials = [ map {
68             $_->{handle} //= $data->{handle};
69             App::LinkSite::Social->new(%$_)
70             } $data->{social}->@* ];
71              
72             my $links = [ map { App::LinkSite::Link->new(%$_) } $data->{links}->@* ];
73              
74             my $sections = [];
75             if ($data->{sections}) {
76             $sections = [ map {
77             my $section_links = [ map { App::LinkSite::Link->new(%$_) } $_->{links}->@* ];
78             App::LinkSite::Section->new(
79             title => $_->{title},
80             links => $section_links,
81             )
82             } $data->{sections}->@* ];
83             }
84              
85             $site = App::LinkSite::Site->new(
86             name => $data->{name},
87             handle => $data->{handle},
88             image => $data->{image},
89             desc => $data->{desc},
90             og_image => $data->{og_image},
91             site_url => $data->{site_url},
92             socials => $socials,
93             links => $links,
94             sections => $sections,
95             $data->{text_color} ? (text_color => $data->{text_color}) : (),
96             $data->{background_color} ? (background_color => $data->{background_color} ) : (),
97             );
98             }
99              
100             =head1 METHODS
101              
102             =head2 run
103              
104             The main driver method for the process.
105              
106             =cut
107              
108             method run {
109             debug("src is: $src");
110             debug("out is: $out");
111             path($out)->mkdir;
112 0     0     find( { wanted => sub { $self->do_this }, no_chdir => 1 }, $src);
113              
114             if ($site->image or $site->og_image) {
115             path("$out/img")->mkdir;
116             debug("Copy images");
117             for my $img ($site->image, $site->og_image) {
118             next unless $img;
119             path("img/$img")->copy("$out/img");
120             }
121             }
122              
123             if (-f './CNAME') {
124             debug("Copy CNAME");
125             path('./CNAME')->copy("$out/CNAME");
126             }
127              
128             debug("Copy input JSON file");
129             path($file)->copy($out);
130             }
131              
132             =head2 do_this
133              
134             A method is called for each file that is found in the `src` directory.
135              
136             =cut
137              
138             method do_this {
139             if ($File::Find::name eq $src or $File::Find::name eq "$src/") {
140             debug("Skipping $File::Find::name");
141             return;
142             }
143              
144             my $path = $File::Find::name =~ s|^$src/||r;
145              
146             if (/\.tt$/) {
147             debug("Process $path to", basename($path, '.tt'));
148             $tt->process($path, { site => $self->site }, basename($path, '.tt'))
149             or die $tt->error;
150             } else {
151             if (-d) {
152             debug("Make directory $path");
153             path("$out/$path")->mkdir;
154             } elsif (-f) {
155             debug("Copy $path");
156             path("$src/$path")->copy("$out/$path");
157             } else {
158             debug("Confused by $File::Find::name");
159             }
160             }
161             }
162              
163             =head2 debug
164              
165             Debug output. Set `LINKSITE_DEBUG` to a true value to turn this on.
166              
167             export LINKSITE_DEBUG=1
168              
169             =cut
170              
171             sub debug {
172 0 0   0 1   warn "@_\n" if $ENV{LINKSITE_DEBUG};
173             }
174             }
175              
176             =head1 AUTHOR
177              
178             Dave Cross
179              
180             =head1 COPYRIGHT AND LICENCE
181              
182             Copyright (c) 2024, Magnum Solutions Ltd. All Rights Reserved.
183              
184             This library is free software; you can redistribute it and/or modify it
185             under the same terms as Perl itself.
186              
187             =cut
188              
189             1;