Table of Contents:

Version 1.0.7 released 22-October-1999


Version 1.0.5 released.Sat Jul 31 09:11:18 1999
This is the official release of Genpage 1.0.5. This is the first version of genpage that has proper and tested platform support for Win32 and MacOS as well as *NIX. VMS support is still outstanding. Other platforms may work with some judicious 'beating with a big stick' :)

Please read the Changelog file for details of changes and bugfixes.

Version 1.0.6 released.Wed Aug 04 12:11:18 1999
This is the official release of Genpage 1.0.6.

This is a quick release to catch an errata in 1.0.5.

If you put a %outputfile% tag in a content file the specified filename is used instead of the standard generated one. This allows genpage users to 'hard-code' filenames into content files.

Please read the Changelog file for details of changes and bugfixes.

Version 1.0.7 released.Sat Feb 19 19:45:23 2000
This is the official release of Genpage 1.0.7.

After a long hiatus, Genpage is finally back on track. 1.0.7 fixes many bugs, and adds several tweaks and some new functionailty. Be sure to read the documentation carefully as there are one or two changes that will probably break some sites, particularly in relation to the -I flag and recipes.

Please read the Changelog file for details of changes and bugfixes.

Full news


Click here to download the current version.


Genpage is a perl script designed to make managing web content within a consistent looking web site easier.

This is achieved by building a template of the persistent features on a site into a separate layout file that all the content files are applied to.

I built Genpage as a tool to help me build and maintain the mnemonic website, a site with 56 WebPages that would have been a nightmare to manage by hand and ensure that all look and feel consistent.

Initially I wrote a simple script to include consistent components (such as toolbars) so that I only had to modify a link in one file and have it reflected throughout the site. The current version can do much more. It's greatest power is in it's simplicity. Read on.

Mailing Lists

There are two mailing lists set up for announcements and discussions about genpage.

The mailing list genpage-announce is simply for announcements about new Genpage releases, bugfixes and relevant information (like recipe announcements).

To subscribe you can simply click the link above, or send an email with the subject (or body) "subscribe" to

The mailing list genpage-users is for general discussions about the development, use and abuse of Genpage amongst users.

To subscribe you can simply click the link above, or send an email with the subject (or body) "subscribe" to

Using Genpage

Genpage recurses a content directory (by default it's ./content) and applies the template to all .content files therein. The default layout file is expected to be in ./layout/template.html and the output website goes into ./www by default.

The content function

To use Genpage, you construct your website template into a file, and provide markers within that file for where content is inserted. All of your content then goes into .content files. This is probably best illustrated by an example

Example 1


  <title> <!-- _GP_ content("title") --> </title>
  <!-- _GP_ content("body") -->

The content function is a genpage builtin (of which there are only six!
Did I mention simplicity?)

The corresponding content files will look like this:



Foo Page


This is the body content for the file foo.html



Bar Page


This is the body content for the file bar.html


Genpage works on the idea of a content directory that it recurses, looking for .content files and parsing. All other files are copied to the output directory as is. Genpage has an ignore parameter that accepts a standard regexp of files to ignore. (for example, the mnemonic webpages are stored in a CVS repository but I don't want all the CVS directories in the web tree so I set the ignore to CVS - more on this anon.

Also note the <!-- _GP_ --> construct. the _GP_ in the comment is required to tell Genpage that it's not just an normal html comment. The reason that it's a comment at all ( Genpage deliberately removes it during generation ) is so that, if, like me, you use a layout tool to design the webpages, and then manage the content in a straightforward editor, then we don't want the tags either confusing your wysiwyg editor nor the editor arbitrarily deleting them as unknowns.

Special Content Tags

As of version 1.0.3 genpage allows a content file to specify the template to be used in generating it's output. This is achieved by placing the special tag %template% in the content file somewhere.


This will cause the template adifferenttemplate.html in the layout directory (specified with the -l parameter) to be used instead of the default template.

In addition, as of version 1.0.6 genpage allows a different output filename to be specified by placing the special tag %outputfile% in the content file.


This will cause the output adifferentoutputfile.html in the output directory (specified with the -o parameter) to be used instead of <content filename prefix>.html(or whatever has been specified with the suffix flag)

Note: This functionality had a bug in pre-1.0.7 versions which caused the output file to be dumped into the root of the output directory. This bug has been fixed in 1.0.7

As of version 1.0.7 genpage allows a different output filename suffix to be specified by placing the special tag %outputsuffix% in the content file.


This will cause the output <content filename prefix>.shtml in the output directory (specified with the -o parameter) to be used instead of <content filename prefix>.html(or whatever has been previously specified with the suffix flag)

Note that %outputfile% overrides %outputsuffix%

The include function

Ok, above is a basic example. Genpage also has an include function that is used to include standard chunks.

Example 1


  <title> <!-- _GP_ content("title") --> </title>
  <!-- _GP_ include("$root/include/mytoolbar.html") -->
  <!-- _GP_ content("body") -->

The above example simply includes a file in the include directory called mytoolbar.html directly into the output html file.

Note the use of $root above. $root is an internal Genpage variable that is exposed to your template and content files. There are several such variables exposed, these are listed below. This hints at somthing larger that I'll explain further on.

As of version 1.0.7, the include function looks in the include directory (specified by either the -I parameter or the includedir genpage.conf entry) by default, so the include statement above could be written easier as


  <title> <!-- _GP_ content("title") --> </title>
  <!-- _GP_ include("mytoolbar.html") -->
  <!-- _GP_ content("body") -->

The include function can take an optional second parameter that is a section tag which includes a section of the file (as opposed to the whole). The concept is basically very similar to the content functionality except this time is is on any arbitrary filename you specify.

Example 2


  <title> <!-- _GP_ content("title") --> </title>
  <!-- _GP_ include("mytoolbar.html","top") -->
  <!-- _GP_ content("body") -->
  <!-- _GP_ include("mytoolbar.html","bottom") -->

The above example includes a toolbar file that has seperate sections for top and bottom. This may be convenient for storing all your toolbars in one place or sectioning out chunks of java script in a file for example.

The mytoolbar.html might look like this:


<li>toptool element 1
<li>toptool element 2
<li>toptool element 3

<li>bottomtool element 1
<li>bottomtool element 2
<li>bottomtool element 3

The strip function

Put very simply, the strip function takes a string as a parameter and returns that string stripped of leading and trailing whitespace. The reason for this is simply to make things like comparisons easier as Genpage swallows any strings (e.g. in the content function) whole, whitespace and all.

The gloss function

The gloss function takes a parameter that represents a key in a glossary file and returns the resultant value.

A glossary file is simply a list of "key" "value" pairs, one per line.


key1 value1
key2 http://value2.url/
key3 This is a horrible long chunk of text that I hate typing in again and again.

By default, genpage looks for the glossary file in layout/glossary however you can specify a different location using the -g command line option.

The gloss function can be called in two ways, either simply as gloss("key") or as <%key%> which works in the same way. The reason for the second method is to avoid problems with wysiwyg editors that will barf on tags that use "'s having the gloss("key") embedded in it.

e.g. <A HREF="<!-- _GP_ gloss("key2") -->">foo here</a> will cause your editor to barf because it will see the "'s as being prematurely closed.

whereas: <A HREF="<!-- _GP_ <%key2%> -->">foo here</a> will pass cleanly through most wysiwyg editors I believe.

In addition, the gloss function accepts a second parameter which is an alternate glossary file to use. e.g. use either:

<A HREF="<!-- _GP_ gloss("key2","myotherglossary") -->">foo here</a> or <A HREF="<!-- _GP_ <%key2,myotherglossary%> -->">foo here</a>

The recipe function

The recipe function is used to include a "recipe" to enhance the functionality of genpage. Recipes are dealt with in detail in the recipe's section below.

The expand function

The expand function is the genpage parser function that does the replacement of <!-- _GP_ whatever --> tags with the output from whatever functions are called.

This function is intended for advanced users who wish to write recipes of their own. Most people should steer clear of it as voodoo is involved :).

The path function

The path function basically converts a filename/path from any format into the proper format for your operating system type (with the exception of VMS at present, since I don't have access to a VMS machine).

Example 1

<!-- _GP_ path("$root/include/myfile.html") --> when run on a *NIX system will return

Whereas, the same command when run on a DOS box will return

And in MacPerl will return

The version function

There is but one more builtin function and it's so simple it doesn't need an example. <!-- _GP_ &version; --> returns the Genpage version (complete with hyperlink to this page). Use it extensively! :)

As an addition to version 1.0.4, the version function accepts an optional parameter (anything) that will cause it to output in fancy mode. Fancy mode plonks a "built using genpage" graphic instead of the text link.

There are several examples, in the Genpage distribution that you should read to familiarise yourself with how Genpage works.

Inline perl

Right, that's the beginners class over. Time to get rough!

Genpage evaluates everything inside the <!-- _GP_ --> tags as perl. This means that you can chunk arbitrary perl code into the template, content or include files to customise the behaviour for a particular purpose.

The following example should make things a little clearer.

Example 1


<!-- _GP_
# undef all the functions we're defining. This stops lots of
# complaining about re-defining the sub for each content file thats
# processed.

       if (defined(&who)) { undef &who; }
       if (defined(&where)) { undef &where; }
       if (defined(&when)) { undef &when; }

<!-- _GP_
# These functions are defined here as straightforward perl - remember
# to undef them first if you don't want perl complaining about lots of
# subroutine re-definitions if Genpage is processing more than one
# content file.
# The reason is that the template is evaluated from scratch for each
# new content file.
# Hence, it is probably good practise to undef everything you define
# within the scope of a layout file before you start

    sub who {
         my $ret=`/usr/bin/whoami`;
         chop $ret;
        return ($ret);

    sub when {
        my $ret=`/bin/date`;
        chop $ret;
        return ($ret);

    sub where {
        my $ret=`/bin/hostname -f`;
        chop $ret;
        return ($ret);

  <title> <!-- _GP_ content("title") --> </title>
  <!-- _GP_ include("$root/include/mytoolbar.html") -->
  <!-- _GP_ content("body") -->
  <p> This page generated by <!-- _GP_ &who; --> on server
            <!-- &where; -->


What we've done is define 3 new functions for Genpage, who, when and where that get called later as straightforward perl. In effect, we've extended the capabilities of Genpage at runtime.

Two things to note, The Genpages tags can occur anywhere as they're interpreted and stripped out of the output HTML. The second thing to note is that I deliberately undef the functions at the top of the file. Genpage is a single run process and hence any subroutine definitions that are created in this fashion are defined for the duration of the run. As Genpage parses each content file, it would re-call the template code to generate the who, when and where subroutines for each content file. This will cause perl to complain about subroutine re-definitions. To avoid it, check if your subroutine or variables are defined and undef them by default.

A side effect here is that you could also overload the inline functions to do something else if you wished :)))

The astute amongst you will probably have already figured this out, but the chunk of code above could of course been put into a seperate file and included into the template (or into a particular content file if that's what you wanted) using the <!-- _GP_ include() --> construct.

The above examples however, use a type of method that has largely been replaced by the inclusion of the recipe() function which is a much slicker way of defining new functionality for genpage on the fly. Read on.


Recipes, simply put, are user contributed modules that enhance the capability of the genpage script at runtime.

What they offer, is the ability to drop your commonly used function into included module files that are pulled into genpage during execution.

Unlike a chunk of inline perl, recipe files look and act exactly like a standard perl file that you'd 'require' into your perl scripts. For genpage, the recipe() duplicates the perl 'require' function, but does not return a '1' if the file is already loaded (because it screws up output files).

The Genpage distribution contains several very useful user contributed recipes in the standard include directory. For information on user contributed recipe's and the guidelines for writing your own please visit the recipes page

Command Line Parameters

usage: genpage [-dqfh] [-c content-dir] [-l layout-dir ] [-o output-dir] 
               [-I include-dir] [ -L lib-dir ] [-t template-file] 
               [ -i ignore-regexp ] [-s file-suffix ] [-g glossary-file ] 
               [ -p parameter-file ] [-a afterpass-filter] [-e eval-params ] 
               [ -E execute-command ] [-r recipe ]
       -d debug mode.     Turn on debugging (very verbose!)
       -q quiet mode.     Dont print anything while running.
       -f force mode.     Force the parsing of content files.
       -h help.           Print this help text.
       -c content-dir     The directory where your content tree exists.
                          Defaults to ./content.
       -l layout-dir      The standard directory to find templates in.
                          Defaults to ./layout
       -o output-dir      The directory to put the output website.
                          Defaults to ./www
       -I include-dir     Optional directory to look for include() files in.
                          Defaults to ./include
       -L lib-dir         Optional directory to look for recipes in.
                          Defaults to ./lib
       -t template-file   The standard template to use to generate the site.
                          Defaults to template.html (in the layout-dir)
       -i ignore regexp   Regular expression telling genpage to ignore certain
                          files or directories. 
                          Defaults to - CVS|.*,v$|^\#.*\#$|.*~$
       -s file suffix     Suffix to use for parsed output files. 
                          Defaults to .html
       -g glossary-file   A glossary file to use for the gloss() function
                          Defaults to ./layout/glossary
       -p paramteter-file File with Genpage run parameters.
                          Defaults to ./genpage.conf
       -a after-filter    A filter program to run on each generated file
                          after genpage has processed it.
       -e eval-expression A perl expression to pass into genpage for
                          later use. (e.g. pass some parameters to a
                          recipe from command line)
       -E execute-program A program to execute after genpage has finished
                          processing. (e.g. sitecopy?!?)
       -r recipe-file(s)  A comma seperated list of recipes to include at

       Genpage - Version: 1.0.7
       Copyright (C) Joe Vaughan  1999-2000
       This program is released under the terms of the GNU Public License
       Please read the accompanying COPYING file for details.

       For detailed instructions on how to use Genpage, please consult the 
       accompanying documentation. If you have questions, comments or 
       suggestions for Genpage please contact the author.

Parameter files

Because Genpage has so many command line switches, as a convenience these switches can be set from a parameters file.

The format of this file is as follows:

# Example paramaters for genpage.
# Note: It's case sensitive for now.
#      Command line options override what's in here!
template 	= template.html
layoutdir       = layout
contentdir 	= content
outputdir 	= www
includedir      = include
libdir          = lib
force 		= 0	
debug 		= 0	
quiet 		= 0	
ignore_regexp 	= CVS|.*,v$|^\#.*\#$|.*~$
suffix 		= .html
glossary 	= layout/glossary   
afterpass       = 
evalparam       =
execute         =
recipes		=

Explanation of the parameters

Each of the parameters above are synonymous with a command line switch
ParameterSynonymous withExplanation
template -t The name of the default template file to use
layoutdir -l Directory where templates are located
contentdir -c Directory where the content of the site is located
outputdir -o Loction of output web directory
includedir -I Directory to search for include() files
libdir -L Directory to search first for recipes.
force -f Forces Genpage to regenerate the site. (Default behaviour is to only parse and output changed files.)
debug -d Makes Genpage output debug information (warning: very verbose.)
quiet -q Force genpage to run quietly (i.e. no output to stdout)
ignore_regexp -i A perl regular expression giving files to ignore.
suffix -s The suffix to apply to output files (e.g. .html)
glossary -g Location of a glossary file (see documentation on the gloss() function
afterpass -a A program or script to run on each output file after genpage has generated it.
evalparam -e A chunk of perl to be evaluated in genpage. (e.g. for passing parameters to recipes from genpage command line)
execute -E A command, program or script to run when genpage has finished its run.
recipes -r A comma seperated list of recipe files to load into genpage at startup.

The parameter names and their case are fixed. Command line parameters override settings in the parameter file.

Genpage defaults to a file called genpage.conf in the root of your site tree. You can specify an alternative using the '-p' command line option. (In truth, -p is now probably the only command line parameter you need, if any.)

Exposed Variables.

Following is a list of the exposed variables from Genpage.
It's probably best not to screw around with these unless you really know what you're doing

In truth most of the variables that Genpage uses are exposed to you. The list above is simply the potentially most useful. A quick perusal of the code should show you what you need if they're not what you want.


Genpage is a work in progress and I'm always looking to improve it. (That way I learn more perl) or figure out new ways of doing things with it. If you use it, modify it, build some cool websites with it or want me to make it do something that you think would be useful, then please drop me a line at

This page generated using Genpage - Version: 1.0.7 on server by xemacweb
Wed Aug 15 15:23:30 2001

Copyright (C) Joe Vaughan 1999