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