diff options
author | joey <joey@0fa5a96a-9a0e-0410-b3b2-a0fd24251071> | 2006-08-28 07:40:20 +0000 |
---|---|---|
committer | joey <joey@0fa5a96a-9a0e-0410-b3b2-a0fd24251071> | 2006-08-28 07:40:20 +0000 |
commit | e16746a52f40f478af1b634c532d90c25cc0ec76 (patch) | |
tree | 2ef03282413737d0fed459903b176ea96e6267c0 /IkiWiki | |
parent | e5b323a6331df4f400ea5a3eaa82441f85d41950 (diff) | |
download | ikiwiki-e16746a52f40f478af1b634c532d90c25cc0ec76.tar ikiwiki-e16746a52f40f478af1b634c532d90c25cc0ec76.tar.gz |
* Add toc (table of contents) plugin.
Diffstat (limited to 'IkiWiki')
-rw-r--r-- | IkiWiki/Plugin/skeleton.pm | 10 | ||||
-rw-r--r-- | IkiWiki/Plugin/toc.pm | 116 |
2 files changed, 126 insertions, 0 deletions
diff --git a/IkiWiki/Plugin/skeleton.pm b/IkiWiki/Plugin/skeleton.pm index 1201d055c..4683b00ba 100644 --- a/IkiWiki/Plugin/skeleton.pm +++ b/IkiWiki/Plugin/skeleton.pm @@ -21,6 +21,8 @@ sub import { #{{{ call => \&htmlize); IkiWiki::hook(type => "sanitize", id => "skeleton", call => \&sanitize); + IkiWiki::hook(type => "format", id => "skeleton", + call => \&format); IkiWiki::hook(type => "pagetemplate", id => "skeleton", call => \&pagetemplate); IkiWiki::hook(type => "delete", id => "skeleton", @@ -71,6 +73,14 @@ sub sanitize ($) { #{{{ return $content; } # }}} +sub format ($) { #{{{ + my $content=shift; + + IkiWiki::debug("skeleton plugin running as a formatter"); + + return $content; +} # }}} + sub pagetemplate (@) { #{{{ my %params=@_; my $page=$params{page}; diff --git a/IkiWiki/Plugin/toc.pm b/IkiWiki/Plugin/toc.pm new file mode 100644 index 000000000..c36ce2893 --- /dev/null +++ b/IkiWiki/Plugin/toc.pm @@ -0,0 +1,116 @@ +#!/usr/bin/perl +# Table Of Contents generator +package IkiWiki::Plugin::toc; + +use warnings; +use strict; +use IkiWiki; +use HTML::Parser; + +sub import { #{{{ + IkiWiki::hook(type => "preprocess", id => "toc", + call => \&preprocess); + IkiWiki::hook(type => "format", id => "toc", + call => \&format); +} # }}} + +my @tocs; + +sub preprocess (@) { #{{{ + my %params=@_; + + $params{levels}=1 unless exists $params{levels}; + + # It's too early to generate the toc here, so just record the + # info. + push @tocs, \%params; + + return "\n[[toc $#tocs]]\n"; +} # }}} + +sub format ($) { #{{{ + my $content=shift; + + return $content unless @tocs && $content=~/\[\[toc (\d+)\]\]/ && $#tocs >= $1; + my $id=$1; + my %params=%{$tocs[$id]}; + + my $p=HTML::Parser->new(api_version => 3); + my $page=""; + my $index=""; + my %anchors; + my $curlevel; + my $startlevel=0; + my $liststarted=0; + my $indent=sub { "\t" x $curlevel }; + $p->handler(start => sub { + my $tagname=shift; + my $text=shift; + 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, + # even if there are higher levels seen later on. + if (! $startlevel) { + $startlevel=$level; + $curlevel=$startlevel-1; + } + elsif ($level < $startlevel) { + $level=$startlevel; + } + + return if $level - $startlevel >= $params{levels}; + + if ($level > $curlevel) { + while ($level > $curlevel + 1) { + $index.=&$indent."<ol>\n"; + $curlevel++; + $index.=&$indent."<li class=\"L$curlevel\">\n"; + } + $index.=&$indent."<ol>\n"; + $curlevel=$level; + $liststarted=1; + } + elsif ($level < $curlevel) { + while ($level < $curlevel) { + $index.=&$indent."</li>\n" if $curlevel; + $curlevel--; + $index.=&$indent."</ol>\n"; + } + $liststarted=0; + } + + $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); + }, "dtext"); + } + else { + $page.=$text; + } + }, "tagname, text"); + $p->handler(default => sub { $page.=join("", @_) }, "text"); + $p->parse($content); + $p->eof; + + while ($startlevel && $curlevel >= $startlevel) { + $index.=&$indent."</li>\n" if $curlevel; + $curlevel--; + $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/; + return $page; +} + +1 |