#!/usr/bin/perl -n # hevea-retarget-crossrefs # Michael Ernst # Last updated: February 20, 2013 # To use: # hevea-retarget-crossrefs < orig.html > new.html # This script replaces HTML cross-references of the form # # by cross-refenences to named labels, such as # # This script is not necessary with Hevea version 2.04 and later. # It is required that the original .tex source file contained a \label # command at the end of each \chapter or \[sub]section command, like so: # \chapter{Introduction\label{introduction}} # The given label that will replace the "htoc" one in the .html file. # Rationale: # In the table of contents, Hevea (versions before 2.04) creates HTML # cross-references that use Hevea-generated labels of the form "htoc99", # even when a \label already exists. This leads to users following a link # from the table of contents, then bookmarking or mentioning that link. # The "htoc99" link may point to a completely different section if the # manual is reordered or even if a new section is added. So, it is better # for webpages not to contain the easy-to-misuse "htoc99" cross-references. # Note: Hevea 2.00-2.03 breaks the \label command within \section-like # headings. (Hevea 1.10 works properly; 2.03 is the latest as of this # writing.) No matter what descriptive text you use in the \label command, # Hevea 2.0 changes it to an inscrutible label like "sec99", which makes it # impossible to create stable links into a document from outside. (Hevea # 2.0 does not break other uses of \label, but as described in section # B.4.1 of the manual (http://hevea.inria.fr/doc/), it is necessary to put # the \label within the \section command.) This message on the Hevea # mailing list gives a workaround: replace \label by \hlabel, within # \section commands: # https://sympa.inria.fr/sympa/arc/hevea/2012-09/msg00006.html # This script does not work with in-place editing (perl's -i argument). # use strict; # use English; # $WARNING = 1; $debug = 0; # $debug = 1; # if (scalar(@ARGV) != 1) { # die "Expected exactly 1 argument, got " . scalar(@ARGV); # } # my $filename = $ARGV[0]; push @lines, $_; END { for (my $i = 0; $i(((Chapter )?([0-9]+|[A-Z]))(\.[0-9]+)*)()(.*?)()(()*)():$9$2$7$11$8$13:) { $mapping{$1} = $10; if ($debug) { print STDERR "$1 => $mapping{$1}\n"; } } # Move around the ")(.*?)(()*)():$1$6$5$8:; } foreach my $line (@lines) { if ($line =~ //) { my $htoc = $1; my $replacement = $mapping{$htoc}; if (defined($replacement)) { if ($debug) { print STDERR $line; } # Also remove "Chapter" if present, for brevity $line =~ s/$htoc(">)(Chapter )?/$replacement$1/; if ($debug) { print STDERR $line; } } else { print STDERR "No symbolic name for section $htoc\n"; } } $line =~ s/(/$1 ALT="$2">/g; print $line; } } # Local Variables: # time-stamp-start: "^# Last updated: " # time-stamp-end: "\\.?$" # time-stamp-format: "%:b %:d, %:y" # time-stamp-line-limit: 10 # End: