Commits

Michele Bini committed 2409fb9

Comments (0)

Files changed (1)

HtmlHeadingsToTableOfContents.pl

+#! D:\perl\bin\perl.exe
+
+###############################################################################
+###############################################################################
+#
+# To add a table of contents, based on its headings, to an HTML page.
+#
+#			Version 2
+#
+#	by Andrew Hardwick, http://duramecho.com, 2002/3/22
+#
+#	Released under GNU Public Licence.
+#
+###############################################################################
+###############################################################################
+#
+# How To Use
+#
+# Run from a command line with the source file name as arguement.
+# If it finds an existing table of contents from this program then it will
+#  replace it, otherwise it will add a new table at the top of the HTML body
+#  (if you move this, be sure to move the '<!--TableOfContentsAnchor:...-->'
+#  markers as well so that, if you need the table of contents updated, this
+#  program can tell where you want the table of contents to be).
+#
+###############################################################################
+#
+# Known Deficiencies
+#
+# It ignores commenting out of HTML sections so it may find spurious headings.
+# It does not check that the anchors it puts in and the HTML the comments it
+#  puts in the HTML to mark the bits it has inserted don't duplicate existing
+#  ones.
+#
+###############################################################################
+###############################################################################
+
+# Include libraries
+use Cwd;		# To find current directory
+use strict;		# Disenable automatic variables
+
+# Global Variables
+my @HeadingCount;
+my @HeadingTexts;
+my @HeadingLevels;
+my @HeadingLabels;
+
+###############################################################################
+# Main rountine
+###############################################################################
+
+{	my ($c,$d);
+	# Get data from file
+	my $From=cwd().'/'.$ARGV[0];
+	open(FILETOPROCESS,'<'.$From)||
+			die("Cannot open $From to read.");
+	my $Html;
+	read FILETOPROCESS,$Html,-s $From;
+	close FILETOPROCESS;
+	# Remove any old anchors
+	$Html=~s/<!--TableOfContentsAnchor:Begin-->
+			.*?
+			<!--TableOfContentsAnchor:End-->
+			//gsx;
+	# Find all headings & mark them with anchors
+	$Html=~s/<H(\d)(.*?)>(.*?)<\/H\1>/
+			'<H'.$1.$2.'><!--TableOfContentsAnchor:Begin--><A NAME="'.
+			MarkHeading($3,$1).
+			'"><\/A><!--TableOfContentsAnchor:End-->'.
+			$3.'<\/H'.$1.'>'/gise;
+	# Avoid jumping down more than one level at a time by adding null headings
+	for($c=0;$c<scalar(@HeadingTexts)-1;$c++)
+	{	if($HeadingLevels[$c]<$HeadingLevels[$c+1]-1)
+		{	splice(@HeadingLevels,$c+1,0,$HeadingLevels[$c]+1);
+			splice(@HeadingTexts,$c+1,0,'');
+			splice(@HeadingLabels,$c+1,0,'');}}
+	# Start HTML table of contents
+	my $Toc="<!--TableOfContents:Begin-->\n<UL>\n";
+	my $PreviousHeadingLevel=1;
+	# Add in contents lines
+	for($c=0;$c<scalar(@HeadingTexts);$c++)
+	{	# Indent/outdent contents line
+		for($d=$PreviousHeadingLevel;$d<$HeadingLevels[$c];$d++)
+		{	$Toc=~s/^(.*)<\/LI>(.*?)$/$1<UL>$2/s;}
+		for($d=$PreviousHeadingLevel;$d>$HeadingLevels[$c];$d--)
+		{	$Toc.="<\/UL><\/LI>\n";}
+		# Write a contents line
+		$Toc.='<LI><A HREF="#'.$HeadingLabels[$c].'">'.
+				$HeadingTexts[$c]."<\/A><\/LI>\n";
+		$PreviousHeadingLevel=$HeadingLevels[$c];}
+	# Outdent fully
+	for($d=$PreviousHeadingLevel;$d>1;$d--)
+		{	$Toc=~s/^(.*)<\/LI>(.*?)$/$1<\/UL>$2/s;}
+	# Remove null links
+	$Toc=~s/<A HREF=\"#\"><\/A>//g;
+	# Finish off table of contents
+	$Toc.="<\/UL>\n<!--TableOfContents:End-->\n";
+	# Replace old table of contents with new, or put at top if no old one
+	if(!($Html=~s/<!--TableOfContents:Begin-->\n
+			.*?
+			<!--TableOfContents:End-->\n
+			/$Toc/sx))
+	{	$Html=~s/(<BODY.*?>)/$1\n$Toc/is;}
+	# Write data back to the file
+	open(FILETOPROCESS,'>'.$From)||
+			die("Cannot open $From to write.");
+	print FILETOPROCESS $Html;
+	close FILETOPROCESS;}
+
+###############################################################################
+# MarkHeading
+###############################################################################
+# This works out a heading number for a heading, adds the heading to a 
+#  list and creates an anchor in the heading
+###############################################################################
+# Parameters
+#  1: The text of the heading.
+#  2: The level (1-9) of the heading.
+# Returns
+#  A label to use for the HTML anchor.
+###############################################################################
+
+sub MarkHeading
+{	my ($HeadingText,$HeadingLevel)=@_;
+	# Paranoia
+	$HeadingLevel=1 if($HeadingLevel<1);
+	$HeadingLevel=9 if($HeadingLevel>9);
+	# Work out heading number (add at current level & trim after)
+	$HeadingCount[$HeadingLevel-1]++;
+	@HeadingCount[$HeadingLevel..8]=(0)x9;
+	my $HeadingNumber=join('.',@HeadingCount[0..($HeadingLevel-1)]);
+	# Create a label
+	my $Label='Section_'.$HeadingNumber;
+	# Remove any HTML tags from the heading text
+	$HeadingText=~s/<.*?>//gis;
+	# Store the results
+	push(@HeadingTexts,$HeadingText);
+	push(@HeadingLevels,$HeadingLevel);
+	push(@HeadingLabels,$Label);
+	# Display progress on screen
+	print '-'x$HeadingLevel." $HeadingText\n";
+	return $Label;}
+
+###############################################################################