summaryrefslogtreecommitdiff
path: root/IkiWiki/Plugin/autoindex.pm
blob: 78571b27677d4377892f8f9a451f1c87dbde365a (plain)
  1. #!/usr/bin/perl
  2. package IkiWiki::Plugin::autoindex;
  3. use warnings;
  4. use strict;
  5. use IkiWiki 3.00;
  6. use Encode;
  7. sub import {
  8. hook(type => "checkconfig", id => "autoindex", call => \&checkconfig);
  9. hook(type => "getsetup", id => "autoindex", call => \&getsetup);
  10. hook(type => "refresh", id => "autoindex", call => \&refresh);
  11. IkiWiki::loadplugin("transient");
  12. }
  13. sub getsetup () {
  14. return
  15. plugin => {
  16. safe => 1,
  17. rebuild => 0,
  18. },
  19. autoindex_commit => {
  20. type => "boolean",
  21. example => 1,
  22. default => 1,
  23. description => "commit autocreated index pages",
  24. safe => 1,
  25. rebuild => 0,
  26. },
  27. }
  28. sub checkconfig () {
  29. if (! defined $config{autoindex_commit}) {
  30. $config{autoindex_commit} = 1;
  31. }
  32. }
  33. sub genindex ($) {
  34. my $page=shift;
  35. my $file=newpagefile($page, $config{default_pageext});
  36. add_autofile($file, "autoindex", sub {
  37. my $message = sprintf(gettext("creating index page %s"),
  38. $page);
  39. debug($message);
  40. my $dir = $config{srcdir};
  41. if (! $config{autoindex_commit}) {
  42. $dir = $IkiWiki::Plugin::transient::transientdir;
  43. }
  44. my $template = template("autoindex.tmpl");
  45. $template->param(page => $page);
  46. writefile($file, $dir, $template->output);
  47. if ($config{rcs} && $config{autoindex_commit}) {
  48. IkiWiki::disable_commit_hook();
  49. IkiWiki::rcs_add($file);
  50. IkiWiki::rcs_commit_staged(message => $message);
  51. IkiWiki::enable_commit_hook();
  52. }
  53. });
  54. }
  55. sub refresh () {
  56. eval q{use File::Find};
  57. error($@) if $@;
  58. eval q{use Cwd};
  59. error($@) if $@;
  60. my $origdir=getcwd();
  61. my (%pages, %dirs);
  62. foreach my $dir ($config{srcdir}, @{$config{underlaydirs}}, $config{underlaydir}) {
  63. next if $dir eq $IkiWiki::Plugin::transient::transientdir;
  64. chdir($dir) || next;
  65. find({
  66. no_chdir => 1,
  67. wanted => sub {
  68. my $file=decode_utf8($_);
  69. $file=~s/^\.\/?//;
  70. return unless length $file;
  71. if (IkiWiki::file_pruned($file)) {
  72. $File::Find::prune=1;
  73. }
  74. elsif (! -l $_) {
  75. my ($f) = $file =~ /$config{wiki_file_regexp}/; # untaint
  76. return unless defined $f;
  77. return if $f =~ /\._([^.]+)$/; # skip internal page
  78. if (! -d _) {
  79. $pages{pagename($f)}=1;
  80. }
  81. elsif ($dir eq $config{srcdir}) {
  82. $dirs{$f}=1;
  83. }
  84. }
  85. }
  86. }, '.');
  87. chdir($origdir) || die "chdir $origdir: $!";
  88. }
  89. # Compatibility code.
  90. #
  91. # {deleted} contains pages that have been deleted at some point.
  92. # This plugin used to delete from the hash sometimes, but no longer
  93. # does; in [[todo/autoindex_should_use_add__95__autofile]] Joey
  94. # thought the old behaviour was probably a bug.
  95. #
  96. # The effect of listing a page in {deleted} was to avoid re-creating
  97. # it; we migrate these pages to {autofile} which has the same effect.
  98. # However, {autofile} contains source filenames whereas {deleted}
  99. # contains page names.
  100. my %deleted;
  101. if (ref $wikistate{autoindex}{deleted}) {
  102. %deleted=%{$wikistate{autoindex}{deleted}};
  103. delete $wikistate{autoindex}{deleted};
  104. }
  105. elsif (ref $pagestate{index}{autoindex}{deleted}) {
  106. # an even older version
  107. %deleted=%{$pagestate{index}{autoindex}{deleted}};
  108. delete $pagestate{index}{autoindex};
  109. }
  110. if (keys %deleted) {
  111. foreach my $dir (keys %deleted) {
  112. my $file=newpagefile($dir, $config{default_pageext});
  113. $wikistate{autoindex}{autofile}{$file} = 1;
  114. }
  115. }
  116. foreach my $dir (keys %dirs) {
  117. if (! exists $pages{$dir} && grep /^$dir\/.*/, keys %pages) {
  118. genindex($dir);
  119. }
  120. }
  121. }
  122. 1