forked from github/kensanata.oddmuse
PageHtml() to generate the HTML of the page without table of contents, extracting the generated HTML headings, producing the table of contents, and finish generating the real HTML of the page.
185 lines
6.1 KiB
Perl
185 lines
6.1 KiB
Perl
# Copyright (C) 2004, 2005, 2006, 2007 Alex Schroeder <alex@emacswiki.org>
|
|
#
|
|
# This program is free software; you can redistribute it and/or modify
|
|
# it under the terms of the GNU General Public License as published by
|
|
# the Free Software Foundation; either version 2 of the License, or
|
|
# (at your option) any later version.
|
|
#
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with this program; if not, write to the
|
|
# Free Software Foundation, Inc.
|
|
# 59 Temple Place, Suite 330
|
|
# Boston, MA 02111-1307 USA
|
|
|
|
$ModulesDescription .= '<p>XXX $Id: toc.pl,v 1.42 2007/08/12 23:43:15 as Exp $</p>';
|
|
|
|
push(@MyRules, \&TocRule);
|
|
|
|
# This must come *before* either headers.pl or the usemod.pl rules and
|
|
# adds support for portrait-support.pl
|
|
$RuleOrder{\&TocRule} = 90;
|
|
|
|
use vars qw($TocAutomatic $TocProcessing $TocShown $TocCounter);
|
|
|
|
$TocCounter = 0;
|
|
$TocAutomatic = 1;
|
|
$TocProcessing = 0;
|
|
$TocShown = 0;
|
|
my $TocPage;
|
|
|
|
push(@MyInitVariables, \&TocInit);
|
|
|
|
sub TocInit {
|
|
$TocPage = GetId(); # only do this for the "main" page
|
|
$TocCounter = 0;
|
|
}
|
|
|
|
# If we're rendering the headings inside the sidebar, we want to refer
|
|
# to the headings in the real page. $OpenPageName points to the
|
|
# $SidebarName, however, so that the forms extension works. That's why
|
|
# we have a separate variable being used, here.
|
|
|
|
sub TocRule {
|
|
my $key = $TocPage eq $OpenPageName || $OpenPageName eq '';
|
|
if (m!\G<toc(/[A-Za-z\x80-\xff/]+)?>!gci) {
|
|
my $html = CloseHtmlEnvironments()
|
|
. ($PortraitSupportColorDiv ? '</div>' : '');
|
|
$html .= TocHeadings(split(m|/|, $1)) unless $TocShown;
|
|
$html .= AddHtmlEnvironment('p');
|
|
$TocShown = 1;
|
|
$PortraitSupportColorDiv = 0; # after the HTML has been determined.
|
|
$PortraitSupportColor = 0;
|
|
return $html;
|
|
} elsif ($bol
|
|
&& $UseModMarkupInTitles
|
|
&& m/\G(\s*\n)*(\=+)[ \t]*(?=[^=\n]+=)/cg) {
|
|
my $depth = length($2);
|
|
$depth = 6 if $depth > 6;
|
|
$depth = 2 if $depth < 2;
|
|
my $html = CloseHtmlEnvironments()
|
|
. ($PortraitSupportColorDiv ? '</div>' : '');
|
|
$html .= TocHeadings() if not $TocShown and $TocAutomatic;
|
|
$TocShown = 1 if $TocAutomatic;
|
|
if ($key) {
|
|
$TocCounter++;
|
|
$html .= AddHtmlEnvironment('h' . $depth, qq{id="toc$TocCounter"});
|
|
} else {
|
|
$html .= AddHtmlEnvironment('h' . $depth);
|
|
}
|
|
$PortraitSupportColorDiv = 0; # after the HTML has been determined.
|
|
$PortraitSupportColor = 0;
|
|
return $html;
|
|
} elsif ($UseModMarkupInTitles
|
|
&& (InElement('h1')
|
|
|| InElement('h2')
|
|
|| InElement('h3')
|
|
|| InElement('h4')
|
|
|| InElement('h5')
|
|
|| InElement('h6'))
|
|
&& m/\G[ \t]*=+\n?/cg) {
|
|
return CloseHtmlEnvironments() . AddHtmlEnvironment('p');
|
|
} elsif ($bol && (defined(&UsemodRule) || defined(&CreoleRule))
|
|
&& !$UseModMarkupInTitles
|
|
&& m/\G(\s*\n)*(\=+)[ \t]*(.+?)[ \t]*(=*)[ \t]*(\n|$)/cg) {
|
|
my $depth = length($2);
|
|
$depth = 6 if $depth > 6;
|
|
$depth = 2 if $depth < 2;
|
|
my $text = $3;
|
|
my $html = CloseHtmlEnvironments()
|
|
. ($PortraitSupportColorDiv ? '</div>' : '');
|
|
$html .= TocHeadings() if not $TocShown and $TocAutomatic;
|
|
$TocShown = 1 if $TocAutomatic;
|
|
if ($key) {
|
|
$TocCounter++;
|
|
$html .= qq{<h$depth id="toc$TocCounter">$text</h$depth>};
|
|
} else {
|
|
$html .= qq{<h$depth>$text</h$depth>};
|
|
}
|
|
$html .= AddHtmlEnvironment('p');
|
|
$PortraitSupportColorDiv = 0; # after the HTML has been determined.
|
|
$PortraitSupportColor = 0;
|
|
return $html;
|
|
} elsif ($bol && defined(&HeadersRule)
|
|
&& (m/\G((.+?)[ \t]*\n(---+|===+)[ \t]*\n)/gc)) {
|
|
my $depth = substr($3,0,1) eq '=' ? 2 : 3;
|
|
my $text = $2;
|
|
my $html = CloseHtmlEnvironments()
|
|
. ($PortraitSupportColorDiv ? '</div>' : '');
|
|
$html .= TocHeadings() if not $TocShown and $TocAutomatic;
|
|
$TocShown = 1 if $TocAutomatic;
|
|
if ($key) {
|
|
$TocCounter++;
|
|
$html .= qq{<h$depth id="toc$TocCounter">$text</h$depth>};
|
|
} else {
|
|
$html .= qq{<h$depth>$text</h$depth>};
|
|
}
|
|
$html .= AddHtmlEnvironment('p');
|
|
$PortraitSupportColorDiv = 0; # after the HTML has been determined.
|
|
$PortraitSupportColor = 0;
|
|
return $html;
|
|
}
|
|
return undef;
|
|
}
|
|
|
|
sub TocHeadings {
|
|
# avoid recursion
|
|
return '' if $TocProcessing;
|
|
local $TocProcessing = 1;
|
|
local $TocShown = 0;
|
|
local $TocCounter;
|
|
# don't mess up \G
|
|
my ($oldpos, $old_) = (pos, $_);
|
|
my $class = 'toc' . join(' ', @_);
|
|
my $key = 'toc';
|
|
# double rendering
|
|
my $html = PageHtml($OpenPageName);
|
|
my $Headings = $q->h2(T('Contents'));
|
|
my $HeadingsLevel = undef;
|
|
my $HeadingsLevelStart = undef;
|
|
my $count = 1;
|
|
while ($html =~ m!<h([1-6]) id=[^>]*>(.*?)</h[1-6]>!g) {
|
|
my ($depth, $text) = ($1, $2);
|
|
my $link = $key . $count;
|
|
$text = QuoteHtml($text);
|
|
if (not defined $HeadingsLevelStart) {
|
|
# $HeadingsLevel is set to $depth - 1 so that we get an opening
|
|
# of the list. We need $HeadingsLevelStart to close all open
|
|
# tags at the end.
|
|
$HeadingsLevel = $depth - 1;
|
|
$HeadingsLevelStart = $depth - 1;
|
|
}
|
|
$count++;
|
|
# if the first subheading is has depth 2, then
|
|
# $HeadingsLevelStart is 1, and later subheadings may not be
|
|
# at level 1 or below.
|
|
$depth = $HeadingsLevelStart + 1 if $depth <= $HeadingsLevelStart;
|
|
$depth = 6 if $depth > 6;
|
|
# the order of the three expressions is important!
|
|
while ($HeadingsLevel > $depth) {
|
|
$Headings .= '</li></ol>';
|
|
$HeadingsLevel--;
|
|
}
|
|
if ($HeadingsLevel == $depth) {
|
|
$Headings .= '</li><li>';
|
|
}
|
|
while ($HeadingsLevel < $depth) {
|
|
$Headings .= '<ol><li>';
|
|
$HeadingsLevel++;
|
|
}
|
|
$Headings .= "<a href=\"#$link\">$text</a>";
|
|
}
|
|
while ($HeadingsLevel > $HeadingsLevelStart) {
|
|
$Headings .= '</li></ol>';
|
|
$HeadingsLevel--;
|
|
}
|
|
($_, pos) = ($old_, $oldpos); # restore \G (assignment order matters!)
|
|
$TocProcessing = 0;
|
|
return '' if $count <= 2;
|
|
return $q->div({-class=>$class}, $Headings) if $Headings;
|
|
}
|