]> git.vanrenterghem.biz Git - git.ikiwiki.info.git/blob - IkiWiki/Plugin/map.pm
Merge remote branch 'upstream/master' into prv/po
[git.ikiwiki.info.git] / IkiWiki / Plugin / map.pm
1 #!/usr/bin/perl
2 #
3 # Produce a hierarchical map of links.
4 #
5 # by Alessandro Dotti Contra <alessandro@hyboria.org>
6 #
7 # Revision: 0.2
8 package IkiWiki::Plugin::map;
10 use warnings;
11 use strict;
12 use IkiWiki 3.00;
14 sub import {
15         hook(type => "getsetup", id => "map", call => \&getsetup);
16         hook(type => "preprocess", id => "map", call => \&preprocess);
17 }
19 sub getsetup () {
20         return
21                 plugin => {
22                         safe => 1,
23                         rebuild => undef,
24                         section => "widget",
25                 },
26 }
28 sub preprocess (@) {
29         my %params=@_;
30         $params{pages}="*" unless defined $params{pages};
31         
32         # Needs to update whenever a page is added or removed (or in some
33         # cases, when its content changes, if show= is specified).
34         my $deptype=deptype(exists $params{show} ? "content" : "presence");
35         
36         my $common_prefix;
38         # Get all the items to map.
39         my %mapitems;
40         foreach my $page (pagespec_match_list($params{page}, $params{pages},
41                                         deptype => $deptype)) {
42                 if (exists $params{show} && 
43                     exists $pagestate{$page} &&
44                     exists $pagestate{$page}{meta}{$params{show}}) {
45                         $mapitems{$page}=$pagestate{$page}{meta}{$params{show}};
46                 }
47                 else {
48                         $mapitems{$page}='';
49                 }
50                 # Check for a common prefix.
51                 if (! defined $common_prefix) {
52                         $common_prefix=$page;
53                 }
54                 elsif (length $common_prefix &&
55                        $page !~ /^\Q$common_prefix\E(\/|$)/) {
56                         my @a=split(/\//, $page);
57                         my @b=split(/\//, $common_prefix);
58                         $common_prefix="";
59                         while (@a && @b && $a[0] eq $b[0]) {
60                                 if (length $common_prefix) {
61                                         $common_prefix.="/";
62                                 }
63                                 $common_prefix.=shift(@a);
64                                 shift @b;
65                         }
66                 }
67         }
68         
69         # Common prefix should not be a page in the map.
70         while (defined $common_prefix && length $common_prefix &&
71                exists $mapitems{$common_prefix}) {
72                 $common_prefix=IkiWiki::dirname($common_prefix);
73         }
75         # Create the map.
76         my $parent="";
77         my $indent=0;
78         my $openli=0;
79         my $addparent="";
80         my $map = "<div class='map'>\n";
82         if (! keys %mapitems) {
83                 # return empty div for empty map
84                 $map .= "</div>\n";
85                 return $map; 
86         } 
87         else {
88                 $map .= "<ul>\n";
89         }
91         foreach my $item (sort keys %mapitems) {
92                 my @linktext = (length $mapitems{$item} ? (linktext => $mapitems{$item}) : ());
93                 $item=~s/^\Q$common_prefix\E\///
94                         if defined $common_prefix && length $common_prefix;
95                 my $depth = ($item =~ tr/\//\//) + 1;
96                 my $baseitem=IkiWiki::dirname($item);
97                 while (length $parent && length $baseitem && $baseitem !~ /^\Q$parent\E(\/|$)/) {
98                         $parent=IkiWiki::dirname($parent);
99                         last if length $addparent && $baseitem =~ /^\Q$addparent\E(\/|$)/;
100                         $addparent="";
101                         $indent--;
102                         $map .= "</li>\n";
103                         if ($indent > 0) {
104                                 $map .= "</ul>\n";
105                         }
106                 }
107                 while ($depth < $indent) {
108                         $indent--;
109                         $map .= "</li>\n";
110                         if ($indent > 0) {
111                                 $map .= "</ul>\n";
112                         }
113                 }
114                 my @bits=split("/", $item);
115                 my $p="";
116                 $p.="/".shift(@bits) for 1..$indent;
117                 while ($depth > $indent) {
118                         $indent++;
119                         if ($indent > 1) {
120                                 $map .= "<ul>\n";
121                         }
122                         if ($depth > $indent) {
123                                 $p.="/".shift(@bits);
124                                 $addparent=$p;
125                                 $addparent=~s/^\///;
126                                 $map .= "<li>"
127                                         .htmllink($params{page}, $params{destpage},
128                                                  "/".$common_prefix.$p, class => "mapparent",
129                                                  noimageinline => 1)
130                                         ."\n";
131                                 $openli=1;
132                         }
133                         else {
134                                 $openli=0;
135                         }
136                 }
137                 $map .= "</li>\n" if $openli;
138                 $map .= "<li>"
139                         .htmllink($params{page}, $params{destpage}, 
140                                 "/".$common_prefix."/".$item,
141                                 @linktext,
142                                 class => "mapitem", noimageinline => 1)
143                         ."\n";
144                 $openli=1;
145                 $parent=$item;
146         }
147         while ($indent > 0) {
148                 $indent--;
149                 $map .= "</li>\n</ul>\n";
150         }
151         $map .= "</div>\n";
152         return $map;