]> git.vanrenterghem.biz Git - git.ikiwiki.info.git/blob - IkiWiki/Plugin/map.pm
Merge branch 'master' of ssh://git.ikiwiki.info/srv/git/ikiwiki.info
[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 2.00;
14 sub import { #{{{
15         hook(type => "preprocess", id => "map", call => \&preprocess);
16 } # }}}
18 sub preprocess (@) { #{{{
19         my %params=@_;
20         $params{pages}="*" unless defined $params{pages};
21         
22         my $common_prefix;
24         # Get all the items to map.
25         my %mapitems;
26         foreach my $page (keys %pagesources) {
27                 if (pagespec_match($page, $params{pages}, location => $params{page})) {
28                         if (exists $params{show} && 
29                             exists $pagestate{$page} &&
30                             exists $pagestate{$page}{meta}{$params{show}}) {
31                                 $mapitems{$page}=$pagestate{$page}{meta}{$params{show}};
32                         }
33                         else {
34                                 $mapitems{$page}='';
35                         }
36                         # Check for a common prefix.
37                         if (! defined $common_prefix) {
38                                 $common_prefix=$page;
39                         }
40                         elsif (length $common_prefix &&
41                                $page !~ /^\Q$common_prefix\E(\/|$)/) {
42                                 my @a=split(/\//, $page);
43                                 my @b=split(/\//, $common_prefix);
44                                 $common_prefix="";
45                                 while (@a && @b && $a[0] eq $b[0]) {
46                                         if (length $common_prefix) {
47                                                 $common_prefix.="/";
48                                         }
49                                         $common_prefix.=shift(@a);
50                                         shift @b;
51                                 }
52                         }
53                 }
54         }
55         
56         # Common prefix should not be a page in the map.
57         while (defined $common_prefix && length $common_prefix &&
58                exists $mapitems{$common_prefix}) {
59                 $common_prefix=IkiWiki::dirname($common_prefix);
60         }
62         # Needs to update whenever a page is added or removed (or in some
63         # cases, when its content changes, if show=title), so register a
64         # dependency.
65         add_depends($params{page}, $params{pages});
66         # Explicitly add all currently shown pages, to detect when pages
67         # are removed.
68         add_depends($params{page}, join(" or ", keys %mapitems));
70         # Create the map.
71         my $parent="";
72         my $indent=0;
73         my $openli=0;
74         my $dummy=0;
75         my $map = "<div class='map'>\n<ul>\n";
76         foreach my $item (sort keys %mapitems) {
77                 my @linktext = (length $mapitems{$item} ? (linktext => $mapitems{$item}) : ());
78                 $item=~s/^\Q$common_prefix\E\///
79                         if defined $common_prefix && length $common_prefix;
80                 my $depth = ($item =~ tr/\//\//) + 1;
81                 my $baseitem=IkiWiki::dirname($item);
82                 while (length $parent && length $baseitem && $baseitem !~ /^\Q$parent\E(\/|$)/) {
83                         $parent=IkiWiki::dirname($parent);
84                         last if !$dummy && length $parent && $baseitem =~ /^\Q$parent\E(\/|$)/;
85                         $indent--;
86                         $map .= "</li>\n";
87                         if ($indent > 0) {
88                                 $map .= "</ul>\n";
89                         }
90                 }
91                 $dummy=0;
92                 while ($depth < $indent) {
93                         $indent--;
94                         $map .= "</li>\n";
95                         if ($indent > 0) {
96                                 $map .= "</ul>\n";
97                         }
98                 }
99                 my @bits=split("/", $item);
100                 my $p="";
101                 $p.="/".shift(@bits) for 1..$indent;
102                 while ($depth > $indent) {
103                         $indent++;
104                         if ($indent > 1) {
105                                 $map .= "<ul>\n";
106                         }
107                         if ($depth > $indent) {
108                                 $dummy=1;
109                                 $p.="/".shift(@bits);
110                                 $map .= "<li>"
111                                         .htmllink($params{page}, $params{destpage},
112                                                  $p, class => "mapparent",
113                                                  noimageinline => 1)
114                                         ."\n";
115                                 $openli=1;
116                         }
117                         else {
118                                 $openli=0;
119                         }
120                 }
121                 $map .= "</li>\n" if $openli;
122                 $map .= "<li>"
123                         .htmllink($params{page}, $params{destpage}, 
124                                 "/".$common_prefix."/".$item,
125                                 @linktext,
126                                 class => "mapitem", noimageinline => 1)
127                         ."\n";
128                 $openli=1;
129                 $parent=$item;
130         }
131         while ($indent > 0) {
132                 $indent--;
133                 $map .= "</li>\n</ul>\n";
134         }
135         $map .= "</div>\n";
136         return $map;
137 } # }}}