2 # Table Of Contents generator
3 package IkiWiki::Plugin::toc;
11 IkiWiki::hook(type => "preprocess", id => "toc",
12 call => \&preprocess);
13 IkiWiki::hook(type => "format", id => "toc",
19 sub preprocess (@) { #{{{
22 $params{levels}=1 unless exists $params{levels};
24 # It's too early to generate the toc here, so just record the
28 return "\n[[toc $#tocs]]\n";
34 return $content unless @tocs && $content=~/\[\[toc (\d+)\]\]/ && $#tocs >= $1;
36 my %params=%{$tocs[$id]};
38 my $p=HTML::Parser->new(api_version => 3);
45 my $indent=sub { "\t" x $curlevel };
46 $p->handler(start => sub {
49 if ($tagname =~ /^h(\d+)$/i) {
51 my $anchor="index".++$anchors{$level}."h$level";
52 $page.="$text<a name=\"$anchor\" />";
54 # Take the first header level seen as the topmost level,
55 # even if there are higher levels seen later on.
58 $curlevel=$startlevel-1;
60 elsif ($level < $startlevel) {
64 return if $level - $startlevel >= $params{levels};
66 if ($level > $curlevel) {
67 while ($level > $curlevel + 1) {
68 $index.=&$indent."<ol>\n";
70 $index.=&$indent."<li class=\"L$curlevel\">\n";
72 $index.=&$indent."<ol>\n";
76 elsif ($level < $curlevel) {
77 while ($level < $curlevel) {
78 $index.=&$indent."</li>\n" if $curlevel;
80 $index.=&$indent."</ol>\n";
85 $p->handler(text => sub {
87 $index.=&$indent."</li>\n" unless $liststarted;
89 $index.=&$indent."<li class=\"L$curlevel\">".
90 "<a href=\"#$anchor\">".
93 $p->handler(text => undef);
100 $p->handler(default => sub { $page.=join("", @_) }, "text");
104 while ($startlevel && $curlevel >= $startlevel) {
105 $index.=&$indent."</li>\n" if $curlevel;
107 $index.=&$indent."</ol>\n";
110 # Ignore cruft around the toc marker, probably <p> tags added by
111 # markdown which shouldn't appear in a list anyway.
112 $page=~s/\n.*\[\[toc $id\]\].*\n/$index/;