2 # Table Of Contents generator
3 package IkiWiki::Plugin::toc;
11 hook(type => "preprocess", id => "toc", call => \&preprocess);
12 hook(type => "format", id => "toc", call => \&format);
17 sub preprocess (@) { #{{{
20 if ($params{page} eq $params{destpage}) {
21 $params{levels}=1 unless exists $params{levels};
23 # It's too early to generate the toc here, so just record the
25 $tocpages{$params{destpage}}=\%params;
27 return "\n<div class=\"toc\"></div>\n";
30 # Don't generate toc in an inlined page, doesn't work
38 my $content=$params{content};
40 return $content unless exists $tocpages{$params{page}};
41 %params=%{$tocpages{$params{page}}};
43 my $p=HTML::Parser->new(api_version => 3);
50 my $indent=sub { "\t" x $curlevel };
51 $p->handler(start => sub {
54 if ($tagname =~ /^h(\d+)$/i) {
56 my $anchor="index".++$anchors{$level}."h$level";
57 $page.="$text<a name=\"$anchor\"></a>";
59 # Take the first header level seen as the topmost level,
60 # even if there are higher levels seen later on.
63 $curlevel=$startlevel-1;
65 elsif ($level < $startlevel) {
69 return if $level - $startlevel >= $params{levels};
71 if ($level > $curlevel) {
72 while ($level > $curlevel + 1) {
73 $index.=&$indent."<ol>\n";
75 $index.=&$indent."<li class=\"L$curlevel\">\n";
77 $index.=&$indent."<ol>\n";
81 elsif ($level < $curlevel) {
82 while ($level < $curlevel) {
83 $index.=&$indent."</li>\n" if $curlevel;
85 $index.=&$indent."</ol>\n";
90 $index.=&$indent."</li>\n" unless $liststarted;
92 $index.=&$indent."<li class=\"L$curlevel\">".
93 "<a href=\"#$anchor\">";
95 $p->handler(text => sub {
99 $p->handler(end => sub {
101 if ($tagname =~ /^h(\d+)$/i) {
102 $p->handler(text => undef);
103 $p->handler(end => undef);
113 $p->handler(default => sub { $page.=join("", @_) }, "text");
117 while ($startlevel && $curlevel >= $startlevel) {
118 $index.=&$indent."</li>\n" if $curlevel;
120 $index.=&$indent."</ol>\n";
123 $page=~s/(<div class=\"toc\">)/$1\n$index/;