summaryrefslogtreecommitdiff
path: root/IkiWiki/Plugin/map.pm
blob: 65a6ed552e9b28ebf7abb516543e2575200a5aca (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 2.00;
  12. sub import { #{{{
  13. hook(type => "preprocess", id => "map", call => \&preprocess);
  14. } # }}}
  15. sub preprocess (@) { #{{{
  16. my %params=@_;
  17. $params{pages}="*" unless defined $params{pages};
  18. my $common_prefix;
  19. # Get all the items to map.
  20. my %mapitems;
  21. foreach my $page (keys %pagesources) {
  22. if (pagespec_match($page, $params{pages}, location => $params{page})) {
  23. $mapitems{$page}=1;
  24. # Check for a common prefix.
  25. if (! defined $common_prefix) {
  26. $common_prefix=$page;
  27. }
  28. elsif (length $common_prefix &&
  29. $page !~ /^\Q$common_prefix\E(\/|$)/) {
  30. my @a=split(/\//, $page);
  31. my @b=split(/\//, $common_prefix);
  32. $common_prefix="";
  33. while (@a && @b && $a[0] eq $b[0]) {
  34. $common_prefix.=shift(@a);
  35. shift @b;
  36. }
  37. }
  38. }
  39. }
  40. # Common prefix should not be a page in the map.
  41. while (defined $common_prefix && length $common_prefix &&
  42. exists $mapitems{$common_prefix}) {
  43. $common_prefix=IkiWiki::dirname($common_prefix);
  44. }
  45. # Needs to update whenever a page is added or removed, so
  46. # register a dependency.
  47. add_depends($params{page}, $params{pages});
  48. # Explicitly add all currently shown pages, to detect when pages
  49. # are removed.
  50. add_depends($params{page}, join(" or ", keys %mapitems));
  51. # Create the map.
  52. my $parent="";
  53. my $indent=0;
  54. my $openli=0;
  55. my $map = "<div class='map'>\n<ul>\n";
  56. foreach my $item (sort keys %mapitems) {
  57. $item=~s/^\Q$common_prefix\E\///
  58. if defined $common_prefix && length $common_prefix;
  59. my $depth = ($item =~ tr/\//\//) + 1;
  60. my $baseitem=IkiWiki::dirname($item);
  61. while (length $parent && length $baseitem && $baseitem !~ /^\Q$parent\E(\/|$)/) {
  62. $parent=IkiWiki::dirname($parent);
  63. $indent--;
  64. $map .= "</li>\n";
  65. if ($indent > 0) {
  66. $map .= "</ul>\n";
  67. }
  68. }
  69. while ($depth < $indent) {
  70. $indent--;
  71. $map .= "</li>\n";
  72. if ($indent > 0) {
  73. $map .= "</ul>\n";
  74. }
  75. }
  76. my @bits=split("/", $item);
  77. my $p="";
  78. $p.="/".shift(@bits) for 1..$indent;
  79. while ($depth > $indent) {
  80. $indent++;
  81. if ($indent > 1) {
  82. $map .= "<ul>\n";
  83. }
  84. if ($depth > $indent) {
  85. $p.="/".shift(@bits);
  86. $map .= "<li>"
  87. .htmllink($params{page}, $params{destpage}, $p, class => "mapparent")
  88. ."\n";
  89. $openli=1;
  90. }
  91. else {
  92. $openli=0;
  93. }
  94. }
  95. $map .= "</li>\n" if $openli;
  96. $map .= "<li>"
  97. .htmllink($params{page}, $params{destpage},
  98. "/".$common_prefix."/".$item, class => "mapitem")
  99. ."\n";
  100. $openli=1;
  101. $parent=$item;
  102. }
  103. while ($indent > 0) {
  104. $indent--;
  105. $map .= "</li>\n</ul>\n";
  106. }
  107. $map .= "</div>\n";
  108. return $map;
  109. } # }}}
  110. 1