summaryrefslogtreecommitdiff
path: root/IkiWiki/Plugin/map.pm
blob: 581ae5011f8a002190f133f6ce999797bae43b1b (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. if (length $common_prefix) {
  35. $common_prefix.="/";
  36. }
  37. $common_prefix.=shift(@a);
  38. shift @b;
  39. }
  40. }
  41. }
  42. }
  43. # Common prefix should not be a page in the map.
  44. while (defined $common_prefix && length $common_prefix &&
  45. exists $mapitems{$common_prefix}) {
  46. $common_prefix=IkiWiki::dirname($common_prefix);
  47. }
  48. # Needs to update whenever a page is added or removed, so
  49. # register a dependency.
  50. add_depends($params{page}, $params{pages});
  51. # Explicitly add all currently shown pages, to detect when pages
  52. # are removed.
  53. add_depends($params{page}, join(" or ", keys %mapitems));
  54. # Create the map.
  55. my $parent="";
  56. my $indent=0;
  57. my $openli=0;
  58. my $dummy=0;
  59. my $map = "<div class='map'>\n<ul>\n";
  60. foreach my $item (sort keys %mapitems) {
  61. $item=~s/^\Q$common_prefix\E\///
  62. if defined $common_prefix && length $common_prefix;
  63. my $depth = ($item =~ tr/\//\//) + 1;
  64. my $baseitem=IkiWiki::dirname($item);
  65. while (length $parent && length $baseitem && $baseitem !~ /^\Q$parent\E(\/|$)/) {
  66. $parent=IkiWiki::dirname($parent);
  67. last if !$dummy && length $parent && $baseitem =~ /^\Q$parent\E(\/|$)/;
  68. $indent--;
  69. $map .= "</li>\n";
  70. if ($indent > 0) {
  71. $map .= "</ul>\n";
  72. }
  73. }
  74. $dummy=0;
  75. while ($depth < $indent) {
  76. $indent--;
  77. $map .= "</li>\n";
  78. if ($indent > 0) {
  79. $map .= "</ul>\n";
  80. }
  81. }
  82. my @bits=split("/", $item);
  83. my $p="";
  84. $p.="/".shift(@bits) for 1..$indent;
  85. while ($depth > $indent) {
  86. $indent++;
  87. if ($indent > 1) {
  88. $map .= "<ul>\n";
  89. }
  90. if ($depth > $indent) {
  91. $dummy=1;
  92. $p.="/".shift(@bits);
  93. $map .= "<li>"
  94. .htmllink($params{page}, $params{destpage},
  95. $p, class => "mapparent",
  96. noimageinline => 1)
  97. ."\n";
  98. $openli=1;
  99. }
  100. else {
  101. $openli=0;
  102. }
  103. }
  104. $map .= "</li>\n" if $openli;
  105. $map .= "<li>"
  106. .htmllink($params{page}, $params{destpage},
  107. "/".$common_prefix."/".$item,
  108. class => "mapitem", noimageinline => 1)
  109. ."\n";
  110. $openli=1;
  111. $parent=$item;
  112. }
  113. while ($indent > 0) {
  114. $indent--;
  115. $map .= "</li>\n</ul>\n";
  116. }
  117. $map .= "</div>\n";
  118. return $map;
  119. } # }}}
  120. 1