ikiwiki/IkiWiki/Plugin/sparkline.pm

174 lines
3.7 KiB
Perl
Raw Permalink Normal View History

2007-03-07 06:33:45 +01:00
#!/usr/bin/perl
package IkiWiki::Plugin::sparkline;
use warnings;
use strict;
use IkiWiki 3.00;
2007-03-07 06:33:45 +01:00
use IPC::Open2;
my $match_num=qr/[-+]?[0-9]+(?:\.[0-9]+)?/;
my %locmap=(
top => 'TEXT_TOP',
right => 'TEXT_RIGHT',
bottom => 'TEXT_BOTTOM',
left => 'TEXT_LEFT',
);
sub import {
hook(type => "getsetup", id => "sparkline", call => \&getsetup);
2007-03-07 06:33:45 +01:00
hook(type => "preprocess", id => "sparkline", call => \&preprocess);
}
2007-03-07 06:33:45 +01:00
sub getsetup () {
return
plugin => {
safe => 1,
rebuild => undef,
2010-02-12 12:35:52 +01:00
section => "widget",
},
}
sub preprocess (@) {
2007-03-07 06:33:45 +01:00
my %params=@_;
my $php;
my $style=(exists $params{style} && $params{style} eq "bar") ? "Bar" : "Line";
$php=qq{<?php
require_once('sparkline/Sparkline_$style.php');
\$sparkline = new Sparkline_$style();
\$sparkline->SetDebugLevel(DEBUG_NONE);
};
foreach my $param (qw{BarWidth BarSpacing YMin YMaz}) {
if (exists $params{lc($param)}) {
$php.=qq{\$sparkline->Set$param(}.int($params{lc($param)}).qq{);\n};
}
}
my $c=0;
while (@_) {
my $key=shift;
my $value=shift;
if ($key=~/^($match_num)(?:,($match_num))?(?:\(([a-z]+)\))?$/) {
$c++;
my ($x, $y);
if (defined $2) {
$x=$1;
$y=$2;
}
else {
$x=$c;
$y=$1;
}
if ($style eq "Bar" && defined $3) {
$php.=qq{\$sparkline->SetData($x, $y, '$3');\n};
}
else {
$php.=qq{\$sparkline->SetData($x, $y);\n};
}
}
elsif (! length $value) {
error gettext("parse error")." \"$key\"";
2007-03-07 06:33:45 +01:00
}
elsif ($key eq 'featurepoint') {
my ($x, $y, $color, $diameter, $text, $location)=
split(/\s*,\s*/, $value);
if (! defined $diameter || $diameter < 0) {
2009-07-19 20:13:57 +02:00
error gettext("invalid featurepoint diameter");
2007-03-07 06:33:45 +01:00
}
$x=int($x);
$y=int($y);
$color=~s/[^a-z]+//g;
$diameter=int($diameter);
$text=~s/[^-a-zA-Z0-9]+//g if defined $text;
if (defined $location) {
$location=$locmap{$location};
if (! defined $location) {
2009-07-19 20:13:57 +02:00
error gettext("invalid featurepoint location");
2007-03-07 06:33:45 +01:00
}
}
$php.=qq{\$sparkline->SetFeaturePoint($x, $y, '$color', $diameter};
$php.=qq{, '$text'} if defined $text;
$php.=qq{, $location} if defined $location;
$php.=qq{);\n};
}
}
if ($c eq 0) {
error gettext("missing values");
2007-03-07 06:33:45 +01:00
}
my $height=int($params{height} || 20);
if ($height < 2 || $height > 100) {
2009-07-19 20:13:57 +02:00
error gettext("invalid height value");
2007-03-07 06:33:45 +01:00
}
if ($style eq "Bar") {
$php.=qq{\$sparkline->Render($height);\n};
}
else {
if (! exists $params{width}) {
error gettext("missing width parameter");
2007-03-07 06:33:45 +01:00
}
my $width=int($params{width});
if ($width < 2 || $width > 1024) {
2009-07-19 20:13:57 +02:00
error gettext("invalid width value");
2007-03-07 06:33:45 +01:00
}
$php.=qq{\$sparkline->RenderResampled($width, $height);\n};
}
$php.=qq{\$sparkline->Output();\n?>\n};
# Use the sha1 of the php code that generates the sparkline as
# the base for its filename.
eval q{use Digest::SHA};
2007-03-07 06:33:45 +01:00
error($@) if $@;
my $fn=$params{page}."/sparkline-".
IkiWiki::possibly_foolish_untaint(Digest::SHA::sha1_hex($php)).
2007-03-07 06:33:45 +01:00
".png";
will_render($params{page}, $fn);
2007-03-07 06:33:45 +01:00
if (! -e "$config{destdir}/$fn") {
my $pid;
2009-02-11 18:29:39 +01:00
my $sigpipe=0;
2007-03-07 06:33:45 +01:00
$SIG{PIPE}=sub { $sigpipe=1 };
$pid=open2(*IN, *OUT, "php");
# open2 doesn't respect "use open ':utf8'"
binmode (OUT, ':utf8');
print OUT $php;
close OUT;
my $png;
{
local $/=undef;
$png=<IN>;
}
close IN;
waitpid $pid, 0;
$SIG{PIPE}="DEFAULT";
if ($sigpipe || ! defined $png) {
error gettext("failed to run php");
2007-03-07 06:33:45 +01:00
}
if (! $params{preview}) {
writefile($fn, $config{destdir}, $png, 1);
}
else {
2010-06-09 23:43:20 +02:00
# in preview mode, embed the image in a data uri
# to avoid temp file clutter
eval q{use MIME::Base64};
error($@) if $@;
return "<img src=\"data:image/png;base64,".
encode_base64($png)."\" />";
}
2007-03-07 06:33:45 +01:00
}
return '<img src="'.urlto($fn, $params{destpage}).'" alt="graph" />';
}
2007-03-07 06:33:45 +01:00
1