PerlInHTML User Documentation

Feb 10, 2000

Theodore S. Norvell

PerlInHTML is a Perl module that allows code written in the Perl programming language to be embedded within HTML documents.

The makeHTML Function and Embedded Expressions

Suppose a file called example1.prl.html contains

<head><title>An  example document</title></head>
<body>55*99 is (! 55*99 !).</body>

Then executing the Perl script

require PerlInHTML ;
PerlInHTML::makeHTML( "example1.prl.html", "example1.html" ) ;

would create a new file called example1.html, which contains

<head><title>An  example document</title></head>
<body>55*99 is 5445.</body>

The part of the original file between the (! and the !)  is an expression, written in Perl, and is executed by the makeHTML function. The value of the expression is converted to a string and is put in the output file rather than the (!, the !), and the stuff in between.

Embedding Statements and Declarations

Sometimes you want to embed Perl statements rather than just expressions. This can be done by putting the Perl statements between (* and *). For example, if we change example1.prl.html to

<head><title>An  example document</title></head>
<body>(*local $a, $a = 55*99 ; *)55*99 is (! $a !).</body>

the output will be the same as before. One can also put Perl function definitions between the (* and *) delimiters.

The "put" Subroutine.

Another way to add the result of a Perl expression to the output file is to use the PerlInHTML::put subroutine. It takes 1 or more arguments, and adds them to the output. This subroutine is particularly handy in loops and conditionally executed code. For example to make a list of factorials up to 10, we could write.

<head><title>A list</title></head>
<body>(*
  sub factorial {
    my $n = @_[0] ;
    my $r = 1 ;
    my $i ;
    for( $i = 1 ; $i < $n ; ++$i ) { $r *= $i ; }
    return $r ; }
  my $i ;
  for( $i = 0 ; $i < 10 ; ++$i ) {
    my $f = factorial( $i ) ;
    PerlInHTML::put("$i factorial is $f. ") ;}
*)
</body>

Special Features for WYSIWYG HTML Editors

The previous PerlInHTML file will look rather bad in a WYSIWYG (What You See Is What You Get) editor such as Microsoft's FrontPage or FrontPage Express. This is because newlines are treated like spaces, so the Perl code will be displayed as a single word-wrapped paragraph.

To make life easier, for those who want to use WYSIWYG editors, all HTML tags that occur between (* and *), or between (! and !) are removed before Perl sees the statements or the expression. That means that the above example could be written with <BR> tags after each line of Perl. In fact, <BR> tags are replaced by newlines, as are <P> tags. All other HTML tags are simply removed. Furthermore the sequences &lt; &gt, which editors use in place of the < and > characters are replaced by those characters. The &lt; and &gt; sequences are called "character entity references" in HTML jargon. A complete list of character entity references replacements is

&quot; --> "
&apos; --> '
&amp; --> &
&lt; --> <
&gt; --> >
&nbsp; --> a space
&ensp; --> a space
&emsp; --> a space
&thinsp; --> a space
&ndash; --> -
&mdash; --> -
&lsqua; --> `
&rsquo; --> '
&ldquo --> "
&rdquo; --> "

Suppose you want the browser to display each sentence of the previous example on a separate line. You might think that changing the "put" statement to

    PerlInHTML::put("$i factorial is $f.<BR>") ;}

would do it. But remember that the <BR> tag is replaced by a newline before Perl sees the expression. A correct way to do it would be

    PerlInHTML::put("$i factorial is $f.&lt;BR&gt;") ;}

As confusing as this may seem, when you are using a WYSIWYG editor, it is seamless. You just type "<BR>" and the editor takes care of the rest.

 

Quoting HTML

Of course, in order to know to type "<BR>", you have to know HTML. Many people nowadays use WYSIWYG editors to let them edit HTML without knowing all the tags. Others, know most of the tags, but still prefer the convenience and visual feedback of a WYSIWYG editor. In either case, having to type in the tags seems a step backwards. This section looks at a way of making it easier to enter and edit the appropriate tags.

Suppose you wanted to put the word "factorial" in the previous example in italics. Of course you could just write

    PerlInHTML::put("$i &lt;I&gt;factorial&lt;/I&gt; is $f.&lt;BR&gt;") ;}

But there is another way. You can quote sections of HTML within a section of Perl, using delimiters (? and ?). Whatever HTML is between these delimiters is quoted exactly, without HTML tags being replaced, nor are character entity references replaced. The (?, ?), and the text between them are translated to a Perl expression that evaluates to a string. So we can write:

    PerlInHTML::put($i . (? <I>factorial<I> is ?) . $f . (?<BR>?)) ;}

The advantage of doing it this way is apparent when you use WYSIWYG editor, as the word factorial will appear in italics and the <BR> tag will appear as a newline. In other words, in the editor, the text looks like this:

PerlInHTML::put($i . (? factorial is ?) . $f . (?
?)) ;}

And of course between a (? and a ?), you can edit the HTML using all the fancy editing capabilities of your editor.

Nesting

The text between (? and ?) is quoted exactly, so the following would not have worked:

    PerlInHTML::put((?$i <I>factorial<I> is $f <BR>?)) ;}

That would just just print: $i factorial is $f. In Perl terminology the variables are not interpolated into the string. There is however a way out; you can use (! and !), to insert a Perl expression into the string. So we could write

    PerlInHTML::put((?(!$i!) <I>factorial<I> is (!$f!)<BR>?)) ;}

This is more powerful than Perl's interpolation, because any Perl expression can be inserted within a (?/?) quoted string.

Of course, you can also use (* and *) within (?/?) quoted strings.

Blocks

HTML tags come in two flavours, there are flow tags and block tags. Flow tags are tags like <I> and <A>, which occur within a paragraph. Block tags are tags like <P>, <H1>, and <TABLE>, which define various kinds of paragraph.

WYSIWYG editors can be sticky about where you put text; it generally has to go within a block, not between blocks. This can cause problems. Consider the following example. Suppose you wanted to display the same table more than once on your web page. Using PerlInHTML, this is fairly easy; you can just write

    (* $tab = (? <TABLE>...</TABLE> ?) *)

Later you can just put (!$tab!) wherever the table is required. But some editors (for example FrontPage) will not let you put a table in the middle of a paragraph like that. Furthermore they won't let you put the (!$tab!) outside of any paragraph, which is what you require. About the closest you can get is

    <p>(* $tab = (?</p><TABLE>...</TABLE><p>?)*)</p>

This introduces a spurious paragraph and also assigns some weird HTML to $tab. The (!tab!) will have to be within a paragraph itself, like this

    <p>(!$tab!)</p>

The net result is an extra paragraph where the table is defined and two extra paragraphs every time the table is used

To get around this problem, PerlInHTML has special forms of the delimiters for use with blocks. These are (**, **), (!!, !!), (??, and ??). You should use (?? and ??) to quote HTML blocks, use (!! and !!) when the contained Perl expression will evaluate to an HTML block, and use (** and **) to avoid spurious paragraphs where the (** and **) were.

The technical details are that a <P> tag that immediately precedes a ??), (**, or (!! will be deleted from the output, and a </P> that immediately follows a (??, **), or !!) will likewise be deleted.

Here is an indication how the table example looks in a WYSIWYG editor

Other Functions

Besides "makeHTML" and "put", there are a few other functions in the PerlInHTML module.

includeHTML

The includeHTML function, takes a single argument, the name of a file, and processes the file just as makeHTML does, the difference, is that, while makeHTML writes a new file, includeHTML returns the resulting HTML code as its result.

includeBody

This is similar to includeHTML, but it ignores every part of the input file except for the part between the <BODY> tag and the </BODY> tag. This allows you to put information that needs to be included on several different HTML pages in one file. Typical usage is

    (!! PerlInHTML::includeBody( 'commonFile.prl.html' ) !!)

The file can contain embedded Perl, and one can pass values to that code via global variables.

hmtl2Perl

This function is intended mainly to implement the other functions, it takes an HTML text as a string argument and converts it to a Perl expression, which is returned as a result.

evalWarn

Again, this function is mainly intended to implement the other functions. It evaluates a Perl expression, like Perl's eval function, but with the added feature that it prints a warning message to STDERR, if an error occurs. Suppose $h contains a string of HTML with embedded Perl, then evalWarn( html2Perl( $h ) ) returns a the same string, but with the embedded Perl having been evaluated. E.g., if $h is

"<HEAD>Example</HEAD><BODY>(! 9 * 5 !)</BODY>"

then evalWarn( html2Perl( $h) ) returns

"<HEAD>Example</HEAD><BODY>45</BODY>"

Gory Details

PerlInHTML is implemented as a Perl module in a file called PerlInHTML.pm.

The embedded Perl expressions and statements are evaluated in package "main".

A Full Example

This example illustrates one simple way that PerlInHTML can save time.

We have a set of pages. At the moment, there are only three, but this could change over time. At the top and bottom of each page we want a navigation bar containing links to all the other pages in the set, but not the current one. The name of the current page appears in the navigation bar, not as a link, but in bold. This means we have 6 navigation bars that come in three varieties. If we were to add a page, all 6 bars would have to be changed and 2 new bars created. Since all the bars are basically the same, it would be nice to describe them once and duplicate them as needed. Here is a solution using PerlInHTML.

First we define a template page that defines the look and structure of the pages, but not their contents. The navigation bar is defined once and used twice. This template page is stored in a file called star-template.prl.htm.

wpe74.jpg (35734 bytes)

Next we create a page that defines the contents of the three pages. It contains calls to makeHTML, which transform the template file into the three actual HTML files to be published. This page is stored in a file named star-page-builder.htm.

wpe75.jpg (44401 bytes)

Finally, we "execute" the second page using Perl. In UNIX, the command looks like this

perl -e 'use PerlInHTML ; includeHTML("star-page-builder.htm") ;'

This creates three HTML pages ready for the WWW. The first is here examples/intro.htm.