File Coverage

blib/lib/Giblog.pm
Criterion Covered Total %
statement 29 88 32.9
branch 0 22 0.0
condition 0 3 0.0
subroutine 11 18 61.1
pod 6 6 100.0
total 46 137 33.5


line stmt bran cond sub pod time code
1             package Giblog;
2              
3 2     2   82682 use strict;
  2         4  
  2         56  
4 2     2   8 use warnings;
  2         4  
  2         57  
5              
6 2     2   1297 use Getopt::Long 'GetOptions';
  2         21870  
  2         9  
7 2     2   823 use Giblog::API;
  2         3  
  2         51  
8 2     2   10 use Carp 'confess';
  2         5  
  2         85  
9 2     2   1039 use Pod::Usage 'pod2usage';
  2         66080  
  2         181  
10 2     2   18 use List::Util 'min';
  2         4  
  2         181  
11 2     2   12 use File::Spec;
  2         4  
  2         1713  
12              
13             our $VERSION = '3.00';
14              
15             sub new {
16 59     59 1 40752 my $class = shift;
17              
18 59         161 my $self = {
19             @_
20             };
21              
22 59         170 return bless $self, $class;
23             }
24              
25             sub _extract_usage {
26 0 0   0   0 my $file = @_ ? "$_[0]" : (caller 1)[1];
27              
28 0         0 open my $handle, '>', \my $output;
29 0         0 pod2usage -exitval => 'noexit', -input => $file, -output => $handle;
30 0         0 $output =~ s/^.*\n|\n$//;
31 0         0 $output =~ s/\n$//;
32              
33 0         0 return _unindent($output);
34             }
35              
36             sub _unindent {
37 0     0   0 my $str = shift;
38 0 0       0 my $min = min map { m/^([ \t]*)/; length $1 || () } split "\n", $str;
  0         0  
  0         0  
39 0 0       0 $str =~ s/^[ \t]{0,$min}//gm if $min;
40 0         0 return $str;
41             }
42              
43             sub run_command {
44 0     0 1 0 my ($class, @argv) = @_;
45              
46             # Command line option
47 0         0 local @ARGV = @argv;
48 0         0 my $getopt_option_save = Getopt::Long::Configure(qw(default no_auto_abbrev no_ignore_case pass_through));
49 0         0 GetOptions(
50             "h|help" => \my $help,
51             "H|C|home=s" => \my $home_dir,
52             );
53 0         0 Getopt::Long::Configure($getopt_option_save);
54              
55             # Command name
56 0         0 my $command_name = shift @ARGV;
57              
58             # Show help
59 0 0 0     0 die _extract_usage if $help || !$command_name;
60              
61             # Giblog
62 0         0 my $giblog = Giblog->new(home_dir => $home_dir);
63              
64             # API
65 0         0 my $api = Giblog::API->new(giblog => $giblog);
66              
67             # Add "lib" in home directory to include path
68 0         0 local @INC = @INC;
69 0 0       0 if (defined $home_dir) {
70 0         0 unshift @INC, "$home_dir/lib";
71             }
72             else {
73 0         0 unshift @INC, "lib";
74             }
75              
76             # Command is implemented in command
77 0         0 my $command_class = "Giblog::Command::$command_name";
78 0         0 eval "use $command_class;";
79 0 0       0 if ($@) {
80 0         0 confess "Can't load command $command_class:\n$!\n$@";
81             }
82 0         0 my $command = $command_class->new(api => $api);
83              
84 0         0 @argv = @ARGV;
85 0         0 $command->run(@argv);
86             }
87              
88 53     53 1 120 sub home_dir { shift->{'home_dir'} }
89 10     10 1 37 sub config { shift->{config} }
90              
91             sub build {
92 0     0 1   my ($class) = @_;
93              
94             # Build
95 0           my $cmd = 'giblog build';
96 0 0         system($cmd) == 0
97             or die "Can't execute $cmd: $!";
98             }
99              
100             sub serve {
101 0     0 1   my ($class, $app) = @_;
102              
103             # Read config file
104 0           my $config_file = "$FindBin::Bin/giblog.conf";
105 0           my $config;
106 0 0         $config = do $config_file
107             or die "Can't read config file $config_file";
108              
109             # Remove base path before dispatch
110 0           my $base_path = $config->{base_path};
111 0 0         if (defined $base_path) {
112              
113             # Subdir depth
114 0           my @parts = File::Spec->splitdir($base_path);
115 0           my $subdir_depth = @parts - 1;
116              
117             $app->hook(before_dispatch => sub {
118 0     0     my $c = shift;
119              
120             # Root is redirect
121 0 0         unless (@{$c->req->url->path->parts}) {
  0            
122 0           $c->stash(is_redirect => 1);
123             }
124              
125             # Remove base path
126 0           for (my $i = 0; $i < $subdir_depth; $i++) {
127 0           shift @{$c->req->url->path->parts};
  0            
128             }
129 0           });
130             }
131              
132 0           my $r = $app->routes;
133              
134             $r->get('/' => sub {
135 0     0     my $c = shift;
136              
137 0           my $is_redirect = $c->stash('is_redirect');
138 0 0         if ($is_redirect) {
139 0           $c->redirect_to($base_path);
140             }
141             else {
142 0           $c->reply->static('index.html');
143             }
144 0           });
145              
146 0           $app->start;
147             }
148              
149             =encoding utf8
150              
151             =head1 NAME
152              
153             Giblog - Create Websites and Blogs that can be managed with Git
154              
155             =begin html
156              
157            

158             Website
159            

160            

161            
162            

163            

164             A Website Example
165            

166            

167             Blog
168            

169            

170            
171            

172            

173             A Blog Example
174            

175              
176             =end html
177              
178             =head1 DESCRIPTION
179              
180             Giblog is a utility to create websites or blogs.
181             You can create websites or blogs using C command.
182             All created files is static files. You can manage them using B.
183             You can customize websites using C.
184              
185             =head1 SYNOPSYS
186            
187             # New empty website
188             $ giblog new mysite
189              
190             # New website
191             $ giblog new_website mysite
192              
193             # New blog
194             $ giblog new_blog mysite
195              
196             # Change directory
197             $ cd mysite
198              
199             # Add new entry
200             $ giblog add
201              
202             # Add new entry with home directory
203             $ giblog add -C /home/perlclub/mysite
204              
205             # Build website
206             $ giblog build
207            
208             # Build website with home directory
209             $ giblog build -C /home/perlclub/mysite
210              
211             # Serve a website
212             $ giblog serve
213              
214             # Save a website
215             $ giblog save -m "Commit Messages" origin main
216              
217             # Publish website
218             $ giblog publish origin main
219              
220             # Deploy a website
221             $ giblog deploy
222            
223             # Do "giblog build", "giblog save", "giblog publish", "giblog deploy" at once
224             $ giblog all -m "Commit Messages" origin main
225              
226             =head1 FEATURES
227              
228             Giblog have the following features.
229              
230             =over 4
231              
232             =item * Build websites and blogs.
233              
234             =item * All created files is static files. You can manage files using git.
235              
236             =item * Linux, macOS, Windows Support. (Windows needs msys2 or WSL2)
237              
238             =item * CSS supports smart phone.
239              
240             =item * Header, hooter and side bar support
241              
242             =item * Customize top and bottom section of content.
243              
244             =item * Customize HTML head.
245              
246             =item * Automatical Line break. p tag is automatically added.
247              
248             =item * Escape E, E automatically in pre tag
249              
250             =item * Title tag is automatically added from first h1-h6 tag.
251              
252             =item * Description meta tag is automatically added from first p tag.
253              
254             =item * You can customize your website by Perl.
255              
256             =item * You can serve your website in local environment. Contents changes is detected and build automatically(need L).
257              
258             =item * Fast. Build 645 pages by 0.78 seconds in starndard linux environment.
259              
260             =item * Support Github Pages, both user and project page.
261              
262             =back
263              
264             =head1 TUTORIAL
265              
266             =head2 Create Websites
267              
268             =head3 Create a Empty website
269              
270             L command create empty website. "mysite" is a name of your website.
271              
272             giblog new mysite
273              
274             If you want to create empty site, choice this command.
275             Templates and CSS is empty and provide minimal site building process.
276              
277             =head3 Create a Website
278              
279             L command create simple website. "mysite" is a name of your website.
280              
281             giblog new_website mysite
282              
283             If you want to create simple website, choice this command.
284             Top page "templates/index.html" is created.
285             List page "templates/list.html" is created, which is prepare to create blog entry pages easily for feature.
286              
287             CSS is responsive design and supports smart phone and provide basic site building process.
288              
289             =head3 Create a Blog
290              
291             L command create empty website. "mysite" is a name of your website.
292              
293             giblog new_blog mysite
294              
295             If you want to create blog, choice this prototype.
296             Top page "templates/index.html" is created, which show 7 days entries.
297             List page "templates/list.html" is created, which show all entries links.
298              
299             CSS is responsive design and supports smart phone and provide basic blog building process.
300              
301             =head2 Add a Blog Page
302              
303             L command add entry page.
304              
305             giblog add
306              
307             You need to change the directory created by L, L, or L before
308              
309             Created file name is, for example,
310              
311             templates/blog/20080108132865.html
312              
313             This file name contains current date and time.
314              
315             To write new entry, You open it, write h2 head and content.
316              
317            

How to use Giblog

318              
319             How to use Giblog. This is ...
320              
321             Other parts wrapping content like Header and footer is automatically added in building process.
322              
323             =head2 Add a Content Page
324              
325             If you want to create content page, put file into "templates" directory.
326              
327             templates/access.html
328             templates/profile.html
329              
330             Then open these file, write h2 head and content.
331              
332            

How to use Giblog

333              
334             How to use Giblog. This is ...
335              
336             Other parts wrapping content like Header and footer is automatically added in building process.
337              
338             You can put file into sub directory.
339              
340             templates/profile/more.html
341              
342             Note that "templates/static" and "templates/common" is special directories.
343             Don't push content page files into these directories.
344              
345             # Special directories you don't put content page files into
346             templates/static
347             templates/common
348              
349             =head2 Add Satic files
350              
351             If you want to add static files like css, images, JavaScript, You put these file into "templates/static" directory.
352              
353             Files in "templates/static" directory is only copied to public files by build process.
354              
355             templates/static/js/jquery.js
356             templates/static/images/logo.png
357             templates/static/css/more.css
358              
359             =head2 Customize Header or Footer, Side bar, Top of Content, Bottom of Content
360              
361             You can customize header, footer, side bar, top of content, bottom of content.
362              
363             ------------------------
364             Header
365             ------------------------
366             Top of content |
367             -----------------|
368             |Side
369             Content |bar
370             |
371             -----------------|
372             Bottom of content|
373             ------------------------
374             Footer
375             ------------------------
376              
377             If you want to edit these section, you edit these files.
378              
379             templates/common/header.html Header
380             templates/common/top.html Top of content
381             templates/common/side.html Side bar
382             templates/common/bottom.html Bottom of content
383             templates/common/footer.html Footer
384              
385             =head2 Customize HTML Header
386              
387             You can customize HTML header.
388              
389            
390            
391            
392            
393            
394              
395            
396            
397              
398             If you want to edit HTML header, you edit the following file.
399              
400             templates/common/meta.html
401              
402             =head2 Giblog Variables
403              
404             Explains Giblog variables.
405              
406             =head3 Define Giblog Variables
407              
408             You can define Giblog variable in C.
409              
410             # giblog.conf
411             use strict;
412             use warnings;
413             use utf8;
414              
415             {
416             site_title => 'mysite',
417             site_url => 'http://somesite.example',
418            
419             # Variables
420             vars => {
421             giblog_test_variable => 'Giblog Test Variable',
422             },
423             }
424              
425             C defines Giblog variables in C.
426              
427             =head3 Use Giblog Variables
428              
429             Use Giblog variables in templtes files.
430              
431             <%= $GIBLOG_VARIABLE_NAME %>
432              
433             B
434              
435             C
436              
437             # giblog.conf
438             use strict;
439             use warnings;
440             use utf8;
441              
442             {
443             site_title => 'mysite',
444             site_url => 'http://somesite.example',
445            
446             # Variables
447             vars => {
448             giblog_test_variable => 'Giblog Test Variable',
449             google_analytics_id => 'G-EIFHDUGHF45',
450             },
451             }
452              
453             C
454            
455            
456            
457            
458              
459            
460            
461            
468              
469             =head2 Build a Website
470              
471             Build a website using L command.
472              
473             giblog build
474              
475             You need to change the directory created by L, L, or L before executing "giblog build" command.
476              
477             L command execute C method of C module.
478              
479             C module exists in C.
480              
481             C module is automatically created.
482              
483             See C module.
484              
485             # "lib/Giblog/Command/build.pm" in website created by "new_blog" command
486             package Giblog::Command::build;
487              
488             use base 'Giblog::Command';
489              
490             use strict;
491             use warnings;
492              
493             use File::Basename 'basename';
494              
495             sub run {
496             my ($self, @args) = @_;
497              
498             # API
499             my $api = $self->api;
500              
501             # Read config
502             my $config = $api->read_config;
503              
504             # Copy static files to public
505             $api->copy_static_files_to_public;
506              
507             # Get files in templates directory
508             my $files = $api->get_templates_files;
509              
510             # Add base path to public css files
511             $api->add_base_path_to_public_css_files;
512              
513             for my $file (@$files) {
514             # Data
515             my $data = {file => $file};
516              
517             # Get content from file in templates directory
518             $api->get_content($data);
519              
520             # Parse Giblog syntax
521             $api->parse_giblog_syntax($data);
522              
523             # Parse title
524             $api->parse_title_from_first_h_tag($data);
525              
526             # Edit title
527             my $site_title = $config->{site_title};
528             if ($data->{file} eq 'index.html' || !defined $data->{title}) {
529             $data->{title} = $site_title;
530             }
531             else {
532             $data->{title} = "$data->{title} - $site_title";
533             }
534              
535             # Add page link
536             $api->add_page_link_to_first_h_tag($data, {root => 'index.html'});
537              
538             # Parse description
539             $api->parse_description_from_first_p_tag($data);
540              
541             # Read common templates
542             $api->read_common_templates($data);
543              
544             # Add meta title
545             $api->add_meta_title($data);
546              
547             # Add meta description
548             $api->add_meta_description($data);
549              
550             # Build entry html
551             $api->build_entry($data);
552              
553             # Build whole html
554             $api->build_html($data);
555              
556             # Replace Giblog variables
557             $api->replace_vars($data);
558            
559             # Add base path to content
560             $api->add_base_path_to_content($data);
561              
562             # Write to public file
563             $api->write_to_public_file($data);
564             }
565              
566             # Create index page
567             $self->create_index;
568              
569             # Create list page
570             $self->create_list;
571             }
572              
573             You can customize build process using L and any Perl programs.
574              
575             L is a usuful APIs to customize websites.
576              
577             =head2 Serve a Website
578              
579             You can serve a website by L command.
580              
581             # Serve website
582             giblog serve
583              
584             You see the following message.
585              
586             Web application available at http://127.0.0.1:3000
587              
588             L means the following command. L is a command to serve a L app in development mode.
589              
590             # Same as the following
591             morbo -w giblog.conf -w lib -w templates serve.pl
592              
593             If C, files in C or C directories are changed, the website is automatically rebuild.
594              
595             B
596              
597             If you use Giblog 1, you can serve your website by the following way.
598              
599             # Giblog 1.0
600             morbo -w giblog.conf -w lib -w templates serve.pl
601              
602             =head2 Save a Website
603              
604             Save Websites using L.
605              
606             giblog save -m "Commit Messages" origin main
607              
608             L means the following git commands.
609              
610             git add --all
611             git commit -m "Commit Messages"
612             git push origin main
613              
614             =head2 Publish a Website
615              
616             Publish the website using L command.
617              
618             # Publish the website
619             giblog publish origin main
620              
621             This is the same as the following command. In this example, the repository name is origin and the branch name is main. YY-mm-dd HH:MM:SS is current date and time.
622              
623             git -C public add --all
624             git -C public commit -m "Published by Giblog at YY-mm-dd HH:MM:SS"
625             git -C public push -f origin main
626              
627             =head2 Deploy a Website
628              
629             Deploy websites using L.
630            
631             # Deploy websites
632             giblog deploy
633              
634             L means the following command.
635              
636             perl deploy.pl
637              
638             You can write any program for the deployment in C.
639              
640             use strict;
641             use warnings;
642              
643             my @args = @ARGV;
644              
645             my $deploy_cmd = q(ssh prod_perl_club_sites 'git -C ~/www/en_perlzemi-public fetch && git -C ~/www/en_perlzemi-public reset --hard origin/main');
646              
647             system($deploy_cmd) == 0
648             or die "Can't execute deploy command: $deploy_cmd:$!";
649              
650             =head2 Execute All Commands at Once
651              
652             Do all Publish the website using L, L, L, L command.
653              
654             giblog all -m "Commit Messages" origin main
655              
656             This means the following commands
657              
658             giblog build
659             giblog save -m "Hello" origin main
660             giblog publish origin main
661             giblog deploy
662              
663             If C<--no-build> option is specified, "giblog build" is not executed.
664              
665             giblog all --no-build -m "Commit Messages" origin main
666              
667             If C<--no-save> option is specified, "giblog save" is not executed.
668              
669             giblog all --no-save -m "Commit Messages" origin main
670              
671             If C<--no-publish> option is specified, "giblog publish" is not executed.
672              
673             giblog all --no-publish -m "Commit Messages" origin main
674              
675             If C<--no-deploy> option is specified, "giblog deploy" is not executed.
676              
677             giblog all --no-deploy -m "Commit Messages" origin main
678              
679             =head1 CONFIG FILE
680              
681             Giblog config file is "giblog.conf".
682              
683             This is Perl script and return config as hash reference.
684              
685             use strict;
686             use warnings;
687             use utf8;
688              
689             # giblog.conf
690             {
691             site_title => 'mysite😄',
692             site_url => 'http://somesite.example',
693             }
694              
695             =head2 site_title
696              
697             site_title => 'mysite😄'
698              
699             Site title
700              
701             =head2 site_url
702              
703             site_url => 'http://somesite.example'
704              
705             Site URL.
706              
707             =head2 base_path
708              
709             base_path => '/subdir'
710              
711             Base path. Base path is used to deploy your site to sub directory.
712              
713             For example, Project page URL of Github Pages is
714              
715             https://yuki-kimoto.github.io/giblog-theme1-public/
716              
717             You specify the following
718              
719             base_path => '/giblog-theme1-public'
720              
721             Top character of base_path must be slash "/".
722              
723             HTML files is output into "public/giblog-theme1-public" directory.
724              
725             =head1 METHODS
726              
727             These methods is internally methods.
728             Normally, you don't need to know these methods.
729             See L to manipulate HTML contents.
730              
731             =head2 new
732              
733             my $api = Giblog->new(%params);
734              
735             Create L object.
736              
737             B
738              
739             =over 4
740              
741             =item * home_dir - home directory
742              
743             =item * config - config
744              
745             =back
746              
747             =head2 run_command
748              
749             $giblog->run_command(@argv);
750              
751             Run command system.
752              
753             =head2 config
754              
755             my $config = $giblog->config;
756              
757             Get Giblog config.
758              
759             =head2 home_dir
760              
761             my $home_dir = $giblog->home_dir;
762              
763             Get home directory.
764              
765             =head1 DOCUMENT
766              
767             =over 2
768              
769             =item * L
770              
771             =item * L
772              
773             =item * L
774              
775             =item * L
776              
777             =item * L
778              
779             =item * L
780              
781             =item * L
782              
783             =item * L
784              
785             =item * L
786              
787             =item * L
788              
789             =item * L
790              
791             =item * L
792              
793             =back
794              
795             =head1 FAQ
796              
797             =head2 Dose Giblog support Windows?
798              
799             Giblog doesn't support native Windows(Strawberry Perl, or Active Perl) because Giblog depends on L and L.
800              
801             If you use Giblog in Windows, you can use L or WSL2.
802              
803             =head2 What is the lowest version of Perl supported by Giblog?
804              
805             The lowest version of Perl is the same version as L because Giblog depends on L. The current version is Perl 5.16+.
806              
807             =head2 What is the lowest version of Git required by Giblog?
808              
809             Git 1.8.5+.
810              
811             =head2 What to consider when upgrading from Giblog 2 to Giblog 3?
812              
813             Giblog 3.0 is compatible with Giblog 2.0. You can upgrade from Giblog 2.0 to Giblog 3.0 naturally.
814              
815             =head2 What to consider when upgrading from Giblog 1 to Giblog 2?
816              
817             From Giblog 2.0 the lowest version of Perl depends on L, so use the latest Perl as possible.
818              
819             Git 1.8.5+ is required.
820              
821             =head1 OFFICEAL SITE
822              
823             L
824              
825             =head1 AUTHOR
826              
827             Yuki Kimoto, C<< >>
828              
829             =head1 CONTRIBUTORS
830              
831             Yasuaki Omokawa, C<< >>
832              
833             =head1 LICENSE AND COPYRIGHT
834              
835             Copyright 2018-2021 Yuki Kimoto.
836              
837             This program is free software; you can redistribute it and/or modify it
838             under the terms of the the Artistic License (2.0). You may obtain a
839             copy of the full license at:
840              
841             L
842              
843             =cut
844              
845             1;