From faf9aec11bf8a462ec33c690cb831a6badef6106 Mon Sep 17 00:00:00 2001 From: Frederik Vanrenterghem Date: Thu, 15 Jun 2023 21:09:48 +0800 Subject: [PATCH] Add ikistrap plugin for ikistrap theme. Source: https://github.com/gsliepen/ikistrap/blob/master/lib/IkiWiki/Plugin/ikistrap.pm --- IkiWiki/Plugin/ikistrap.pm | 120 +++++++++++++++++++++++++++++++++++++ 1 file changed, 120 insertions(+) create mode 100644 IkiWiki/Plugin/ikistrap.pm diff --git a/IkiWiki/Plugin/ikistrap.pm b/IkiWiki/Plugin/ikistrap.pm new file mode 100644 index 000000000..c67d83003 --- /dev/null +++ b/IkiWiki/Plugin/ikistrap.pm @@ -0,0 +1,120 @@ +#!/usr/bin/perl +package IkiWiki::Plugin::ikistrap; + +use warnings; +use strict; +use IkiWiki 3.00; + +sub import { + hook(type => "checkconfig", id => "ikistrap", call => \&checkconfig); + hook(type => "getsetup", id => "ikistrap", call => \&getsetup); + hook(type => "refresh", id => "ikistrap", call => \&refresh); + hook(type => "pagetemplate", id => "ikistrap", call => \&pagetemplate); + hook(type => "preprocess", id => "progress", call => \&progress); +} + +sub checkconfig() { + if (! defined $config{bootstrap_js}) { + $config{bootstrap_js} = 1; + } +} + +sub getsetup() { + return + plugin => { + description => "Bootstrap 5 theme support", + section => "web", + safe => 1, + }, + bootstrap_local => { + description => "Install Bootstrap css and js files locally instead of using jsDelivr?", + example => 0, + type => "boolean", + default => 0, + rebuild => 1, + }, + bootstrap_js => { + description => "Load Bootstrap's Javascript helpers?", + example => 0, + type => "boolean", + default => 1, + rebuild => 1, + } +} + +sub check($$) { + my($basename, $href) = @_; + my $filename = "$config{destdir}/$basename"; + return if(-e $filename); + debug("Fetching missing $basename..."); + system("/usr/bin/curl -# \"$href\" -o \"$filename\""); +} + +sub refresh() { + return 0 unless($config{bootstrap_local}); + mkdir("$config{destdir}"); + + # CSS + mkdir("$config{destdir}/css"); + check("css/bootstrap.min.css", "https://cdn.jsdelivr.net/npm/bootstrap\@5.0.0/dist/css/bootstrap.min.css"); + check("css/bootstrap-icons.css", "https://cdn.jsdelivr.net/npm/bootstrap-icons\@1.4.1/font/bootstrap-icons.css"); + + # Fonts + mkdir("$config{destdir}/css/fonts"); + check("css/fonts/bootstrap-icons.woff2", "https://cdn.jsdelivr.net/npm/bootstrap-icons\@1.4.1/font/fonts/bootstrap-icons.woff2"); + + # JavaScript (if enabled) + return 0 unless($config{bootstrap_js}); + mkdir("$config{destdir}/js"); + check("js/bootstrap.bundle.min.js", "https://cdn.jsdelivr.net/npm/bootstrap\@5.0.0/dist/js/bootstrap.bundle.min.js"); +} + +sub pagetemplate(@) { + my %params = @_; + my $template = $params{template}; + + $template->param(bootstrap_js => $config{bootstrap_js}); + $template->param(bootstrap_local => $config{bootstrap_local}); +} + +# Emulate the progress plugin, but do it the HTML5 + Bootstrap way. +# Also allow setting an extra class attribute. +sub progress(@) { + my %params = @_; + my $percentage_pattern = qr/[0-9]+\%?/; # pattern to validate percentages + my ($fill, $value, $max); + + if (defined $params{percent}) { + $fill = $params{percent}; + ($fill) = $fill =~ m/($percentage_pattern)/; # fill is untainted now + $fill =~ s/%$//; + if (! defined $fill || ! length $fill || $fill > 100 || $fill < 0) { + error(sprintf(gettext("illegal percent value %s"), $params{percent})); + } + $value = $fill; + $max = "100"; + $fill .= "%"; + } elsif (defined $params{totalpages} and defined $params{donepages}) { + $max = pagespec_match_list($params{page}, $params{totalpages}, deptype => deptype("presence")); + $value = pagespec_match_list($params{page}, $params{donepages}, deptype => deptype("presence")); + + if ($max == 0) { + $fill = "100%"; + } else { + $fill = sprintf("%u%%", $value / $max * 100); + } + } else { + error(gettext("need either `percent` or `totalpages` and `donepages` parameters")); + } + + my $class = "progress-bar"; + if (defined $params{class}) { + $class .= " $params{class}"; + } + + return <
$fill

+EODIV +} + +1 -- 2.39.2