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