|
|
We author and manage this web site with Microsoft
FrontPage 2000, which provides convenient WYSIWYG HTML editing and
many powerful site management features. Unfortunately, FrontPage's
search and replace remains underdeveloped and does not support regular
expressions or true multi-line operations. It's also quite fussy about
obtaining your permission before making a replacement, and there's no
way to tell it to "just go ahead and replace all" in multiple
files. However, HTML is a
text file format, and it thus lends itself to processing by a variety of
text-oriented tools, such as Eluent Replace.
Alas, we found that it isn't
quite that simple, but happily, we did find a solution within Eluent
Replace, and the method described below illustrates how you can use
scripting to adapt Eluent Replace to problems it wasn't specifically designed to solve.
If you've ever looked at the folder structure of a FrontPage web,
you've no doubt noticed folders with funny names like _vti_cnf, _borders,
etc. FrontPage uses these folders to host files that specify various
things it doesn't maintain in each page's HTML itself, such as shared
borders and file properties. In particular, FrontPage creates a _vti_cnf
folder in each folder that hosts HTML, image, and other browsable
files, and for each of these files, FrontPage creates a configuration
file of the same name in the corresponding _vti_cnf folder. A
configuration file is just a text file that contains a list of
name/value pairs which indicate who last edited the page, the file size,
and so on. The problem lies in FrontPage's management of these
configuration files.
If you were to open a file outside the FrontPage environment, edit
it, and save it, it would be reasonable to expect FrontPage to notice
your changes when you switch back to FrontPage, or the next time you
load the web containing the file. This doesn't
happen, at least not completely, and we find that FrontPage simply won't
upload our modified
pages when we try to publish our disk-based web.
We did a little experiment which consisted of opening files from
Windows Explorer with Notepad, making little changes, saving them, and
seeing how FrontPage reacted. After a while, we determined that
FrontPage was not updating the vti_timelastmodified lines in
configuration files, even after choosing Recalculate Hyperlinks
from its Tools menu. We found that deleting lines beginning
with vti_timelastmodified from the configuration files
corresponding to the modified web files and recalculating hyperlinks
solved our publishing problem. Apparently, the stale time values had
prevented FrontPage from publishing the changed files, and for some
reason, FrontPage was reluctant to update vti_timelastmodified
from the file system information, even though it did update vti_filesize
and other fields! Knowing this, it wasn't too hard to write
a Quick Script for Eluent Replace that:
- Records which web files were modified during execution of the
Replace Task.
- Ensures that vti_timelastmodified lines occurring only in configuration
files corresponding to modified web files are deleted. (When you
Recalculate Hyperlinks, FrontPage restores these lines with the
correct file modification times.)
The Quick Script, written in Perl, of course, is presented below. It
relies on a recursive Path Plan and takes
advantage of the fact that such a Path Plan returns a folder's files
before descending into its subfolders. This is important, because the
script needs to handle web files before their corresponding
configuration files. A screenshot follows the
script and shows the Replace Task dialog box preparing to use our FrontPage
2000 S/R Replace Plan. We conclude with a downloadable Replace Plan
you can merge into your Replace Plan database and full instructions
on how to use it.
# This
Quick Script is intended for use with FrontPage 2000
# webs residing on a hard drive.
# Basic sanity check
die "This script requires at least two Replace Rules"
if ($__RULE_COUNT__ < 2);
# This hash contains the names of the "vti files"
# complementary to modified "web files". A web file is
# one that doesn't live in a path below a _vti folder.
# A "vti file" lives in a _vti_cnf folder.
my %modFiles;
# These variables identify the current file as a web file
# or a vti file. If both are false, it's neither, and it
# isn't processed.
my $isWebFile;
my $isVtiFile;
# For a web file, this variable contains the full path to
# its corresponding vti file. For a vti file, it contains
# the full path to the vti file itself. For other file
# types, it's the empty string.
my $vtiPath;
sub SplitPath($)
{
# This function splits a fully qualified filename into
# directory and file parts, which it returns as a
# two-item list. It also converts to lower case so
# comparisons made elsewhere will always work.
my $fname = lc(shift);
my $rPos = rindex($fname,'\\');
return (substr($fname,0,$rPos), substr($fname,$rPos+1));
}
# Define event functions to be called by the script
# Eluent Replace writes for us.
sub OnBeginFile
{
# This function is called before each file is processed.
# It determines if the file is a "web file" or a special
# "vti file", based on its directory. If it's a web file,
# it allows the file to be processed, while if it's a
# vti file, it allows it to be processed only if
# replacements were made to its complementary web file.
my ($path, $leaf) = SplitPath($__FILE__);
$isWebFile = $path !~ /\\_vti/;
$isVtiFile = $path =~ /\\_vti_cnf$/;
$vtiPath = ($isWebFile)
? $path . "\\_vti_cnf\\" . $leaf
: (($isVtiFile) ? $path . "\\" . $leaf : '');
return ($isWebFile)
? 1
: (($isVtiFile) ? $modFiles{$vtiPath} : 0);
}
sub OnEndFile
{
# This function is called after each file is processed,
# even if the user canceled or OnBeginFile returned false.
# It makes an entry in the hash %modFiles for web files
# in which replacements were made. OnBeginFile uses this
# information to reject "vti files" whose
corresponding
# web files were not modified. As a result, when we go
# to publish our web, FrontPage will upload only the
# changed files.
my $commit = shift;
$modFiles{$vtiPath} = $commit if ($isWebFile);
return $commit;
}
sub OnRule
{
# This function is called before each Replace Rule is
# applied, and its return value determines whether the
# rule is applied or skipped. Below, we relate the file
# type, web or vti, to the rule number, and we allow
# only rule 1 for vti files and rules > 1 for web
files.
# Other files we might encounter aren't even searched.
my $ruleNum = shift;
return ($ruleNum > 1) ? $isWebFile : $isVtiFile;
}
|
Below, the Replace Task dialog box displays the Replace Plan as you
would begin to add your own Replace Rules. The first rule is fixed, and
you should not alter it in any way, as it's responsible for deleting
stale vti_timelastmodified lines from configuration files
corresponding to modified web files. Note that the Path Plan specifies a
recursive enumeration of files on our web, which as described above, is
important for correct operation of our Quick Script.

Be aware that the method described here operates on raw HTML, and you
need to be careful to modify only the HTML that you "own". For
example, FrontPage merges pages referenced by Include Page
components into the files that use them, and if you replace text in the
included area, your changes won't persist. You would need to modify the included
pages, whose HTML you own, instead of the pages that include them. Also, be careful that you
don't damage any of FrontPage's special comments that refer to webbots,
and be sure you modify only those HTML tags you intend to modify. These
considerations apply to any external program you use to edit HTML
files belonging to FrontPage webs, not just Eluent Replace. Finally,
note that we've tested this method only with FrontPage 2000. It may or
may not work with earlier versions, and although it makes no assumptions
about web structure beyond what we've already described, we cannot
guarantee it will work with your FrontPage 2000 webs. You should try it
out on a backup copy of your web to become familiar with it and to
determine if it's suitable for you. That said, we've used this method
repeatedly to help maintain our web site, and we've found it very
useful.
To get started, here's what you need to do:
- Download fp2k_replace_plan.txt.
- Run Eluent Replace, press the menu button
,
and choose Import.
- Find, select, and open the fp2k_replace_plan.txt file in the file
selector. The Replace Plan is imported.
To use the Replace Plan you just imported, do the following:
- Close all files in FrontPage 2000.
- Select the FrontPage 2000 S/R Replace Plan from the Replace
Plan list.
- Press the New Rule button
to create a new rule. Don't alter the first rule in the list.
- Define your rule, and repeat (2, 3) as necessary.
- Define your Path Plan. Usually, you will specify the root of your
disk-based web, and Folder Depth will be Infinite. Set
Masks as desired and use the filter buttons to define any
filters you need. If you work with this web on a regular basis, save the
Path Plan so that you can easily use it in the future.
- Press OK. Unless you've already saved or renamed the
Replace Plan, the Replace Task dialog box will ask you if you want to
save the Replace Plan. Say "no," because you will use this
Replace Plan as the basis for future Replace Tasks.
- Eluent Replace will begin to carry out your Replace Task. We set the Confirmation
option for the first Replace Rule, which causes Eluent Replace to
prompt you before updating configuration files. Once you're
satisfied it's doing the right thing, the next time you use this
Replace Plan, you can uncheck the first rule's Confirmation check
box, which is labeled C. (In the program, pointing to a rule
label displays a tooltip describing it.) This is the only change you
should ever make to the first rule, unless you really know
what you're doing. :)
- When you return to FrontPage 2000, choose Recalculate
Hyperlinks from the Tools menu for webs containing
modified files.
That's it! If all has gone well, the next time you publish your web,
FrontPage will upload all the files you modified, and only those files.
Hopefully, a future FrontPage will be more diligent in
noticing changes made outside its environment, and then this Quick
Script workaround will no longer be necessary.
|