# markdown文書に TOC を追加する この日記(wiki)では [[http://daringfireball.net/projects/markdown/syntax markdown]] を採用している。HTML 化には {{cpan: Text::MultiMarkdown }} を使用しているわけですが、特にページがある程度のサイズになってくるものだと、TOC(Table Of Content: もくじ) が欲しくなる。 例えば [[/wiki/development/sandbox sandbox]] の冒頭で見出しがページ内リンクで並んでいるようなやつ。 というわけで、以下のようなコードで TOC に対応した。 sub toc { my ($self, $text_ref, $c) = @_; while ( $$text_ref =~ s#\{\{(?:toc|TOC) (\d)(\-)?(\d)?\}\}#
\n\n
# ) { my $toc_h_min = $1 || 1; my $toc_h_max = ($1 && $3) ? $3 : (!$3 && !$2 && $1) ? $1 : 9; $toc_h_min = 9 if $toc_h_min > 9; $toc_h_max = 9 if $toc_h_max > 9 || $toc_h_max < $toc_h_min; my $toc = HTML::Toc->new; my $tocInsertor = HTML::TocInsertor->new; $toc->setOptions({ header => '', footer => '', insertionPoint => 'replace ', doLinkToId => 0, levelToToc => "[$toc_h_min-$toc_h_max]", templateAnchorName => \&__assembleAnchorName, }); $tocInsertor->insert($toc, $$text_ref, { output => $text_ref }); } sub __assembleAnchorName { my ($aFile, $aGroupId, $aLevel, $aNode, $text, $children) = @_; if ($text !~ /^\s*$/) { $text =~ s/\s/_/g; html_decode($text); $text = encode($text); $text =~ s/([^A-Za-z0-9_:.-])/sprintf('.%02X', ord($1))/eog; $text = 'L'.$text if $text =~ /\A\W/o; } $text = 'id' if $text eq ''; return $text; } } `{{TOC 3-}}` (実際は半角)というような記述を目次に整形してくれる。 {{cpan: HTML::Toc}} と {{cpan: HTML::TocInsertor}} を使えばだいたいこれだけ。 正規表現のあたりは改良の余地があるかと思う。 元ねたは {{cpan: MojoMojo}} から。