]> git.vanrenterghem.biz Git - git.ikiwiki.info.git/blobdiff - IkiWiki/Plugin/toc.pm
update for rename of recentchanges.mdwn to json.tl.ph.mdwn
[git.ikiwiki.info.git] / IkiWiki / Plugin / toc.pm
index c36ce289368c945eff3f3e94164bfc004e2b5235..4d29e704050f65dd8d22b57f655a1a2b70e19a57 100644 (file)
@@ -4,59 +4,82 @@ package IkiWiki::Plugin::toc;
 
 use warnings;
 use strict;
 
 use warnings;
 use strict;
-use IkiWiki;
+use IkiWiki 3.00;
 use HTML::Parser;
 
 use HTML::Parser;
 
-sub import { #{{{
-       IkiWiki::hook(type => "preprocess", id => "toc",
-               call => \&preprocess);
-       IkiWiki::hook(type => "format", id => "toc",
-               call => \&format);
-} # }}}
+sub import {
+       hook(type => "getsetup", id => "toc", call => \&getsetup);
+       hook(type => "preprocess", id => "toc", call => \&preprocess);
+       hook(type => "format", id => "toc", call => \&format);
+}
+
+sub getsetup () {
+       return
+               plugin => {
+                       safe => 1,
+                       rebuild => undef,
+                       section => "widget",
+               },
+}
 
 
-my @tocs;
+my %tocpages;
 
 
-sub preprocess (@) { #{{{
+sub preprocess (@) {
        my %params=@_;
 
        my %params=@_;
 
-       $params{levels}=1 unless exists $params{levels};
+       if ($params{page} eq $params{destpage}) {
+               $params{levels}=1 unless exists $params{levels};
 
 
-       # It's too early to generate the toc here, so just record the
-       # info.
-       push @tocs, \%params;
+               # It's too early to generate the toc here, so just record the
+               # info.
+               $tocpages{$params{destpage}}=\%params;
 
 
-       return "\n[[toc $#tocs]]\n";
-} # }}}
+               return "\n<div class=\"toc\"></div>\n";
+       }
+       else {
+               # Don't generate toc in an inlined page, doesn't work
+               # right.
+               return "";
+       }
+}
 
 
-sub format ($) { #{{{
-       my $content=shift;
+sub format (@) {
+       my %params=@_;
+       my $content=$params{content};
        
        
-       return $content unless @tocs && $content=~/\[\[toc (\d+)\]\]/ && $#tocs >= $1;
-       my $id=$1;
-       my %params=%{$tocs[$id]};
+       return $content unless exists $tocpages{$params{page}};
+       %params=%{$tocpages{$params{page}}};
 
        my $p=HTML::Parser->new(api_version => 3);
        my $page="";
        my $index="";
        my %anchors;
 
        my $p=HTML::Parser->new(api_version => 3);
        my $page="";
        my $index="";
        my %anchors;
-       my $curlevel;
-       my $startlevel=0;
+       my $startlevel=($params{startlevel} ? $params{startlevel} : 0);
+       my $curlevel=$startlevel-1;
        my $liststarted=0;
        my $indent=sub { "\t" x $curlevel };
        $p->handler(start => sub {
        my $liststarted=0;
        my $indent=sub { "\t" x $curlevel };
        $p->handler(start => sub {
-               my $tagname=shift;
-               my $text=shift;
+               my ($tagname, $text, $attr) = @_;
                if ($tagname =~ /^h(\d+)$/i) {
                        my $level=$1;
                        my $anchor="index".++$anchors{$level}."h$level";
                if ($tagname =~ /^h(\d+)$/i) {
                        my $level=$1;
                        my $anchor="index".++$anchors{$level}."h$level";
-                       $page.="$text<a name=\"$anchor\" />";
-       
-                       # Take the first header level seen as the topmost level,
+                       $page.="$text<a name=\"$anchor\"></a>";
+                       # if the heading already has a unique ID, use that instead in TOC
+                       if ($attr->{id}) {
+                               $anchor = $attr->{id};
+                       }
+
+                       # Unless we're given startlevel as a parameter,
+                       # take the first header level seen as the topmost level,
                        # even if there are higher levels seen later on.
                        if (! $startlevel) {
                                $startlevel=$level;
                                $curlevel=$startlevel-1;
                        }
                        # even if there are higher levels seen later on.
                        if (! $startlevel) {
                                $startlevel=$level;
                                $curlevel=$startlevel-1;
                        }
+                       elsif (defined $params{startlevel} &&
+                              $level < $params{startlevel}) {
+                           return;
+                       }
                        elsif ($level < $startlevel) {
                                $level=$startlevel;
                        }
                        elsif ($level < $startlevel) {
                                $level=$startlevel;
                        }
@@ -81,22 +104,30 @@ sub format ($) { #{{{
                                }
                                $liststarted=0;
                        }
                                }
                                $liststarted=0;
                        }
+                               
+                       $index.=&$indent."</li>\n" unless $liststarted;
+                       $liststarted=0;
+                       $index.=&$indent."<li class=\"L$curlevel\">".
+                               "<a href=\"#$anchor\">";
        
                        $p->handler(text => sub {
                                $page.=join("", @_);
        
                        $p->handler(text => sub {
                                $page.=join("", @_);
-                               $index.=&$indent."</li>\n" unless $liststarted;
-                               $liststarted=0;
-                               $index.=&$indent."<li class=\"L$curlevel\">".
-                                       "<a href=\"#$anchor\">".
-                                       join("", @_).
-                                       "</a>\n";
-                               $p->handler(text => undef);
+                               $index.=join("", @_);
                        }, "dtext");
                        }, "dtext");
+                       $p->handler(end => sub {
+                               my $tagname=shift;
+                               if ($tagname =~ /^h(\d+)$/i) {
+                                       $p->handler(text => undef);
+                                       $p->handler(end => undef);
+                                       $index.="</a>\n";
+                               }
+                               $page.=join("", @_);
+                       }, "tagname, text");
                }
                else {
                        $page.=$text;
                }
                }
                else {
                        $page.=$text;
                }
-       }, "tagname, text");
+       }, "tagname, text, attr");
        $p->handler(default => sub { $page.=join("", @_) }, "text");
        $p->parse($content);
        $p->eof;
        $p->handler(default => sub { $page.=join("", @_) }, "text");
        $p->parse($content);
        $p->eof;
@@ -107,9 +138,7 @@ sub format ($) { #{{{
                $index.=&$indent."</ol>\n";
        }
 
                $index.=&$indent."</ol>\n";
        }
 
-       # Ignore cruft around the toc marker, probably <p> tags added by
-       # markdown which shouldn't appear in a list anyway.
-       $page=~s/\n.*\[\[toc $id\]\].*\n/$index/;
+       $page=~s/(<div class=\"toc\">)/$1\n$index/;
        return $page;
 }
 
        return $page;
 }