aboutsummaryrefslogtreecommitdiff
path: root/IkiWiki/Plugin/pagestats.pm
blob: 304ddd1c826e95f86d9dbfe139626852149e482c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
#!/usr/bin/perl
#
# Produce page statistics in various forms.
#
# Currently supported:
#   cloud: produces statistics in the form of a del.icio.us-style tag cloud
#          (default)
#   table: produces a table with the number of backlinks for each page
#
# by Enrico Zini
package IkiWiki::Plugin::pagestats;

use warnings;
use strict;
use IkiWiki 3.00;

# Names of the HTML classes to use for the tag cloud
our @classes = ('smallestPC', 'smallPC', 'normalPC', 'bigPC', 'biggestPC' );

sub import {
	hook(type => "getsetup", id => "pagestats", call => \&getsetup);
	hook(type => "preprocess", id => "pagestats", call => \&preprocess);
}

sub getsetup () {
	return 
		plugin => {
			safe => 1,
			rebuild => undef,
			section => "widget",
		},
}

sub linktext ($%) {
	# Return the text of the link to a tag, depending on option linktext.
	my ($page, %params) = @_;
	if (exists $params{show} &&
		exists $pagestate{$page} &&
		exists $pagestate{$page}{meta}{$params{show}}) {
		return $pagestate{$page}{meta}{$params{show}};
	}
	else {
		return undef;
	}
}

sub preprocess (@) {
	my %params=@_;
	$params{pages}="*" unless defined $params{pages};
	my $style = ($params{style} or 'cloud');

	# Backwards compatibility
	if (defined $params{show} && $params{show} =~ m/^\d+$/) {
		$params{limit} = $params{show};
		delete $params{show};
	}

	my %counts;
	my $max = 0;
	foreach my $page (pagespec_match_list($params{page}, $params{pages},
		                  # update when a displayed page is added/removed
	        	          deptype => deptype("presence"))) {
		use IkiWiki::Render;

		my @backlinks = IkiWiki::backlink_pages($page);

		if (exists $params{among}) {
			# only consider backlinks from the amoung pages
			@backlinks = pagespec_match_list(
				$params{page}, $params{among},
				# update whenever links on those pages change
				deptype => deptype("links"),
				list => \@backlinks
			);
		}
		else {
			# update when any page with links changes,
			# in case the links point to our displayed pages
			add_depends($params{page}, "*", deptype("links"));
		}

		$counts{$page} = scalar(@backlinks);
		$max = $counts{$page} if $counts{$page} > $max;
	}

	if (exists $params{limit}) {
		my $i=0;
		my %show;
		foreach my $key (sort { $counts{$b} <=> $counts{$a} || $a cmp $b } keys %counts) {
			last if ++$i > $params{limit};
			$show{$key}=$counts{$key};
		}
		%counts=%show;
	}

	if ($style eq 'table') {
		return "<table class='".(exists $params{class} ? $params{class} : "pageStats")."'>\n".
			join("\n", map {
				"<tr><td>".
				htmllink($params{page}, $params{destpage}, $_, noimageinline => 1, linktext => linktext($_, %params)).
				"</td><td>".$counts{$_}."</td></tr>"
			}
			sort { $counts{$b} <=> $counts{$a} || $a cmp $b } keys %counts).
			"\n</table>\n" ;
	}
	else {
		# In case of misspelling, default to a page cloud

		my $res;
		if ($style eq 'list') {
			$res = "<ul class='".(exists $params{class} ? $params{class} : "list")."'>\n";
		}
		else {
			$res = "<div class='".(exists $params{class} ? $params{class} : "pagecloud")."'>\n";
		}
		foreach my $page (sort keys %counts) {
			next unless $counts{$page} > 0;

			my $class = $classes[$counts{$page} * scalar(@classes) / ($max + 1)];
			
			$res.="<li>" if $style eq 'list';
			$res .= "<span class=\"$class\">".
							htmllink($params{page}, $params{destpage}, $page, linktext => linktext($page, %params)).
			        "</span>\n";
			$res.="</li>" if $style eq 'list';

		}
		if ($style eq 'list') {
			$res .= "</ul>\n";
		}
		else {
			$res .= "</div>\n";
		}

		return $res;
	}
}

1