summaryrefslogtreecommitdiff
path: root/IkiWiki/Plugin/postsparkline.pm
blob: 1d4532366e4f2d12eac17f65e5cdf56bb6e7308b (plain)
  1. #!/usr/bin/perl
  2. package IkiWiki::Plugin::postsparkline;
  3. use warnings;
  4. use strict;
  5. use IkiWiki 3.00;
  6. sub import {
  7. IkiWiki::loadplugin('sparkline');
  8. hook(type => "getsetup", id => "postsparkline", call => \&getsetup);
  9. hook(type => "preprocess", id => "postsparkline", call => \&preprocess);
  10. }
  11. sub getsetup () {
  12. return
  13. plugin => {
  14. safe => 1,
  15. rebuild => undef,
  16. },
  17. }
  18. sub preprocess (@) {
  19. my %params=@_;
  20. if (! exists $params{max}) {
  21. $params{max}=100;
  22. }
  23. if (! exists $params{pages}) {
  24. return "";
  25. }
  26. my $deptype;
  27. if (! exists $params{time} || $params{time} ne 'mtime') {
  28. $params{timehash} = \%IkiWiki::pagectime;
  29. # need to update when pages are added or removed
  30. $deptype = deptype("presence");
  31. }
  32. else {
  33. $params{timehash} = \%IkiWiki::pagemtime;
  34. # need to update when pages are changed
  35. $deptype = deptype("content");
  36. }
  37. if (! exists $params{formula}) {
  38. error gettext("missing formula")
  39. }
  40. my $formula=$params{formula};
  41. $formula=~s/[^a-zA-Z0-9]*//g;
  42. $formula=IkiWiki::possibly_foolish_untaint($formula);
  43. if (! length $formula ||
  44. ! IkiWiki::Plugin::postsparkline::formula->can($formula)) {
  45. error gettext("unknown formula");
  46. }
  47. my @list=sort { $params{timehash}->{$b} <=> $params{timehash}->{$a} }
  48. pagespec_match_list($params{page}, $params{pages},
  49. deptype => $deptype,
  50. limit => sub { $_[0] ne $params{page} },
  51. );
  52. my @data=eval qq{IkiWiki::Plugin::postsparkline::formula::$formula(\\\%params, \@list)};
  53. if ($@) {
  54. error $@;
  55. }
  56. if (! @data) {
  57. # generate an empty graph
  58. push @data, 0 foreach 1..($params{max} / 2);
  59. }
  60. my $color=exists $params{color} ? "($params{color})" : "";
  61. delete $params{pages};
  62. delete $params{formula};
  63. delete $params{ftime};
  64. delete $params{color};
  65. return IkiWiki::Plugin::sparkline::preprocess(%params,
  66. map { $_.$color => "" } reverse @data);
  67. }
  68. sub perfoo ($@) {
  69. my $sub=shift;
  70. my $params=shift;
  71. my $max=$params->{max};
  72. my ($first, $prev, $cur);
  73. my $count=0;
  74. my @data;
  75. foreach (@_) {
  76. $cur=$sub->($params->{timehash}->{$_});
  77. if (defined $prev) {
  78. if ($prev != $cur) {
  79. push @data, "$prev,$count";
  80. $count=0;
  81. last if --$max <= 0;
  82. for ($cur+1 .. $prev-1) {
  83. push @data, "$_,0";
  84. last if --$max == 0;
  85. }
  86. }
  87. }
  88. else {
  89. $first=$cur;
  90. }
  91. $count++;
  92. $prev=$cur;
  93. }
  94. return @data;
  95. }
  96. package IkiWiki::Plugin::postsparkline::formula;
  97. sub peryear (@) {
  98. return IkiWiki::Plugin::postsparkline::perfoo(sub {
  99. return (localtime $_[0])[5];
  100. }, @_);
  101. }
  102. sub permonth (@) {
  103. return IkiWiki::Plugin::postsparkline::perfoo(sub {
  104. my ($month, $year)=(localtime $_[0])[4,5];
  105. return $year*12+$month;
  106. }, @_);
  107. }
  108. sub perday (@) {
  109. return IkiWiki::Plugin::postsparkline::perfoo(sub {
  110. my ($year, $yday)=(localtime $_[0])[5,7];
  111. return $year*365+$yday;
  112. }, @_);
  113. }
  114. sub interval ($@) {
  115. my $params=shift;
  116. my $max=$params->{max};
  117. my @data;
  118. for (my $i=1; $i < @_; $i++) {
  119. push @data, $params->{timehash}->{$_[$i-1]} - $params->{timehash}->{$_[$i]};
  120. last if --$max <= 0;
  121. }
  122. return @data;
  123. }
  124. 1