]> git.vanrenterghem.biz Git - git.ikiwiki.info.git/blob - IkiWiki/Plugin/ikistrap.pm
Add ikistrap plugin for ikistrap theme.
[git.ikiwiki.info.git] / IkiWiki / Plugin / ikistrap.pm
1 #!/usr/bin/perl
2 package IkiWiki::Plugin::ikistrap;
4 use warnings;
5 use strict;
6 use IkiWiki 3.00;
8 sub import {
9         hook(type => "checkconfig", id => "ikistrap", call => \&checkconfig);
10         hook(type => "getsetup", id => "ikistrap", call => \&getsetup);
11         hook(type => "refresh", id => "ikistrap", call => \&refresh);
12         hook(type => "pagetemplate", id => "ikistrap", call => \&pagetemplate);
13         hook(type => "preprocess", id => "progress", call => \&progress);
14 }
16 sub checkconfig() {
17         if (! defined $config{bootstrap_js}) {
18                 $config{bootstrap_js} = 1;
19         }
20 }
22 sub getsetup() {
23         return
24                 plugin => {
25                         description => "Bootstrap 5 theme support",
26                         section => "web",
27                         safe => 1,
28                 },
29                 bootstrap_local => {
30                         description => "Install Bootstrap css and js files locally instead of using jsDelivr?",
31                         example => 0,
32                         type => "boolean",
33                         default => 0,
34                         rebuild => 1,
35                 },
36                 bootstrap_js => {
37                         description => "Load Bootstrap's Javascript helpers?",
38                         example => 0,
39                         type => "boolean",
40                         default => 1,
41                         rebuild => 1,
42                 }
43 }
45 sub check($$) {
46         my($basename, $href) = @_;
47         my $filename = "$config{destdir}/$basename";
48         return if(-e $filename);
49         debug("Fetching missing $basename...");
50         system("/usr/bin/curl -# \"$href\" -o \"$filename\"");
51 }
53 sub refresh() {
54         return 0 unless($config{bootstrap_local});
55         mkdir("$config{destdir}");
57         # CSS
58         mkdir("$config{destdir}/css");
59         check("css/bootstrap.min.css", "https://cdn.jsdelivr.net/npm/bootstrap\@5.0.0/dist/css/bootstrap.min.css");
60         check("css/bootstrap-icons.css", "https://cdn.jsdelivr.net/npm/bootstrap-icons\@1.4.1/font/bootstrap-icons.css");
62         # Fonts
63         mkdir("$config{destdir}/css/fonts");
64         check("css/fonts/bootstrap-icons.woff2", "https://cdn.jsdelivr.net/npm/bootstrap-icons\@1.4.1/font/fonts/bootstrap-icons.woff2");
66         # JavaScript (if enabled)
67         return 0 unless($config{bootstrap_js});
68         mkdir("$config{destdir}/js");
69         check("js/bootstrap.bundle.min.js", "https://cdn.jsdelivr.net/npm/bootstrap\@5.0.0/dist/js/bootstrap.bundle.min.js");
70 }
72 sub pagetemplate(@) {
73         my %params = @_;
74         my $template = $params{template};
76         $template->param(bootstrap_js => $config{bootstrap_js});
77         $template->param(bootstrap_local => $config{bootstrap_local});
78 }
80 # Emulate the progress plugin, but do it the HTML5 + Bootstrap way.
81 # Also allow setting an extra class attribute.
82 sub progress(@) {
83         my %params = @_;
84         my $percentage_pattern = qr/[0-9]+\%?/; # pattern to validate percentages
85         my ($fill, $value, $max);
87         if (defined $params{percent}) {
88                 $fill = $params{percent};
89                 ($fill) = $fill =~ m/($percentage_pattern)/; # fill is untainted now
90                 $fill =~ s/%$//;
91                 if (! defined $fill || ! length $fill || $fill > 100 || $fill < 0) {
92                         error(sprintf(gettext("illegal percent value %s"), $params{percent}));
93                 }
94                 $value = $fill;
95                 $max = "100";
96                 $fill .= "%";
97         } elsif (defined $params{totalpages} and defined $params{donepages}) {
98                 $max = pagespec_match_list($params{page}, $params{totalpages}, deptype => deptype("presence"));
99                 $value = pagespec_match_list($params{page}, $params{donepages}, deptype => deptype("presence"));
101                 if ($max == 0) {
102                         $fill = "100%";
103                 } else {
104                         $fill = sprintf("%u%%", $value / $max * 100);
105                 }
106         } else {
107                 error(gettext("need either `percent` or `totalpages` and `donepages` parameters"));
108         }
110         my $class = "progress-bar";
111         if (defined $params{class}) {
112                 $class .= " $params{class}";
113         }
115         return <<EODIV
116 <p><div class="progress"><div class="$class" role="progressbar" style="width: $value%" aria-valuenow="$value" aria-valuemin="0" aria-valuemax="$max">$fill</div></div></p>
117 EODIV