# 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}} から。