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