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