@node HTML/Stream, HTML/TreeBuilder, HTML/QuickCheck, Module List
@unnumbered HTML output stream class, and some markup utilities


@unnumberedsec NAME

HTML::Stream - HTML output stream class, and some markup utilities

@unnumberedsec DESCRIPTION

This module provides you with an object-oriented (and subclassable)
way of outputting HTML.  Basically, you open up an "HTML stream"
on an existing filehandle, and then do all of your output to the
HTML stream (you can intermix HTML-stream-output and ordinary-print-output,
if you like).

Here@'s small sample of the different ways you can use this module:

@example
use HTML::Stream;
$HTML = new HTML::Stream \*STDOUT;

# The vanilla interface...
tag  $HTML @'A@', HREF=>"$href";
tag  $HTML @'IMG@', SRC=>"logo.gif", ALT=>"LOGO";
text $HTML "My caption!";
tag  $HTML @'_A@';
text $HTML $a_lot_of_text;
@end example

@example
# The chocolate interface (with whipped cream)...
$HTML -> A(HREF=>"$href")
      -> IMG(SRC=>"logo.gif", ALT=>"LOGO")
      -> t("My caption!")
      -> _A
      -> t($a_lot_of_text);
@end example

@example
# The strawberry interface...
output $HTML [A, HREF=>"$href"], 
             [IMG, SRC=>"logo.gif", ALT=>"LOGO"],
             "My caption!",
             [_A];
output $HTML $a_lot_of_text;
@end example

@unnumberedsubsec Function interface

Let@'s start out with the simple stuff.
This module provides a collection of non-OO utility functions
for escaping HTML text and producing HTML tags, like this:

@example
use HTML::Stream qw(:funcs);        # imports functions from @@EXPORT_OK

print html_tag(A, HREF=>$url);
print @'&copy; 1996 by@', html_escape($myname), @'!@';
print html_tag(@'/A@');
@end example

By the way: that last line could be rewritten as:

@example
print html_tag(_A);
@end example

And if you need to get a parameter in your tag that doesn@'t have an
associated value, supply the @emph{undefined} value (@emph{not} the empty string!):

@example
print html_tag(TD, NOWRAP=>undef, ALIGN=>@'LEFT@');

     <TD NOWRAP ALIGN=LEFT>

print html_tag(IMG, SRC=>@'logo.gif@', ALT=>@'@');

     <IMG SRC="logo.gif" ALT="">
@end example

There are also some routines for reversing the process, like:

@example
$text = "This <i>isn@'t</i> &quot;fun&quot;...";    
print html_unmarkup($text);
   
     This isn@'t &quot;fun&quot;...
  
print html_unescape($text);
   
     This isn@'t "fun"...
@end example

@emph{Yeah, yeah, yeah}, I hear you cry.  @emph{We@'ve seen this stuff before.}
But wait!  There@'s more...

@unnumberedsubsec OO interface, vanilla

Using the function interface can be tedious... so we also
provide an @strong{"HTML output stream"} class.  Messages to an instance of
that class generally tell that stream to output some HTML.  Here@'s the
above example, rewritten using HTML streams:

@example
use HTML::Stream;
$HTML = new HTML::Stream \*STDOUT;

tag  $HTML @'A@', HREF=>$url;
ent  $HTML @'copy@';
text $HTML " 1996 by $myname!";
tag  $HTML @'_A@';
@end example

Or, if indirect-object syntax ain@'t your thang:

@example
$HTML->tag(A, HREF=>$url);
$HTML->ent(@'copy@');
$HTML->text(" 1996 by $myname!");
$HTML->tag(_A);
@end example

As you@'ve probably guessed:

@example
ent()      Outputs an HTML entity, like C<&copy;>.
tag()      Outputs an ordinary tag, like <A>, possibly with parameters.
           The parameters will all be HTML-escaped automatically.
text()     Outputs some text, which will be HTML-escaped.
@end example

It you@'re @emph{not} using indirect-object syntax, you might prefer
to use @code{t()} and @code{e()} instead of @code{text()} and @code{ent()}: they
are absolutely identical... just shorter to type:

@example
$HTML -> tag(A, HREF=>$url);
$HTML -> e(@'copy@');
$HTML -> t(" 1996 by $myname!");
$HTML -> tag(_A);
@end example

Now, it wouldn@'t be nice to give you those @code{text()} and @code{ent()} shortcuts
without giving you one for @code{tag()}, would it?  Of course not...

@unnumberedsubsec OO interface, chocolate

The known HTML tags are even given their own @strong{tag-methods,} compiled on 
demand... so the above could be written like this:

@example
$HTML -> A(HREF=>$url);
$HTML -> e(@'copy@');
$HTML -> t(" 1996 by $myname!");
$HTML -> _A;
@end example

As you@'ve probably guessed:

@example
A(HREF=>$url)   ==   tag(A, HREF=>$url)   ==   <A HREF="/the/url">
_A              ==   tag(_A)              ==   </A>
@end example

All such "tag-methods" use the tagname in @emph{all-uppercase}.
A @code{"_"} prefix on any tag-method means that an end-tag is desired.
The @code{"_"} was chosen for several reasons: 
(1) it@'s short and easy to type,
(2) it doesn@'t produce much visual clutter to look at,
(3) @code{_TAG} looks a little like @code{/TAG} because of the straight line.

@itemize @bullet
@item 
@emph{I know, I know... it looks like a private method.  You get used to it.  
Really.}

@end itemize
I should stress that this module will only auto-create tag methods
for @strong{known} HTML tags.  So you@'re protected from typos like this
(which will cause a fatal exception at run-time):

@example
$HTML -> IMGG(SRC=>$src);
@end example

(You@'re not yet protected from illegal tag parameters, but it@'s a start, 
ain@'t it?)

If you need to make a tag known (sorry, but this is currently a 
@emph{global} operation, and not stream-specific), do this:

@example
HTML::Stream->accept_tag(@'MARQUEE@');     # for you MSIE fans...
@end example

@strong{There is no corresponding "reject_tag"}.  I thought and thought
about it, and could not convince myself that such a method would 
do anything more useful that cause other people@'s modules to suddenly
stop working because some bozo function decided to reject the @code{FONT} tag.

@unnumberedsubsec OO interface, with whipped cream

In the grand tradition of C++, output method chaining is supported
in both the Vanilla Interface and the Chocolate Interface.  
So you can (and probably should) say:

@example
$HTML -> A(HREF=>$url) 
      -> e(@'copy@') -> t("1996 by $myname!") 
      -> _A;
@end example

But wait... there@'s one more flavor...

@unnumberedsubsec OO interface, strawberry

I was jealous of the compact syntax of HTML::AsSubs, but I didn@'t
want to worry about clogging the namespace with a lot of functions
like p(), a(), etc. (especially when markup-functions like tr() conflict
with existing Perl functions).  So I came up with this:

@example
output $HTML [A, HREF=>$url], "Here@'s my $caption", [_A];
@end example

Conceptually, arrayrefs are sent to @code{html_tag()}, and strings to 
@code{html_escape()}.

@unnumberedsubsec Newlines

As special cases, some tag-methods (like @code{P}, @code{_P}, and @code{BR}) all cause 
newlines to be output before and/or after the tag, so your HTML is a little 
more readable when you do stuff like "view source" on a browser.  So:

@example
$HTML -> HTML 
      -> HEAD  
      -> TITLE -> t("Hello!") -> _TITLE 
      -> _HEAD
      -> BODY(BGCOLOR=>@'#808080@');
@end example

Actually produces:

@example
<HTML><HTML>
<HEAD>
<TITLE>Hello!</TITLE>
</HEAD>
<BODY BGCOLOR="#808080">
@end example

(This will improve slightly as time goes on).
You can also output newline explicitly via the special @code{nl} method
in the Chocolate Interface:

@example
$HTML->nl;     # one newline
$HTML->nl(6);  # six newlines
@end example

@unnumberedsubsec Entities

As shown above, You can use the @code{ent()} (or @code{e()}) method to output 
an entity:

@example
$HTML->t(@'Copyright @')->e(@'copy@')->t(@' 1996 by Me!@');
@end example

But this can be a pain, particularly for Europeans:

@example
$HTML -> t(@'Copyright @') 
      -> e(@'copy@') 
      -> t(@' 1996 by Fran@') -> e(@'ccedil@') -> t(@'ois, Inc.!@');
@end example

Sooooooooo...

@unnumberedsubsec Changing the way text is escaped

The default "autoescape" behavior of an HTML stream can be a drag if
you@'ve got a lot character entities that you want to output.  So here@'s
how you can use the @code{autoescape()} method to change the way an
HTML::Stream works at any time:

@example
$HTML->autoescape(@'ALL@');        # escapes [<>"&] - the default
$HTML->autoescape(@'NON_ENT@');    # escapes [<>"] only, and not [&]
@end example

If you can also install your own autoescape function (note that you might
very well want to install it for just a little bit only, and then 
de-install it):

@example
sub my_autoescape @{
    my $text = shift;
	$text = HTML::Stream::html_escape_all($text);   # start with default
    $text =~ s/\(c\)/&copy;/ig;        # (C) becomes copyright
    $text =~ s/\\,(c)/\&$1cedil;/ig;   # \,c becomes a cedilla
 	$text;
@}
@end example

@example
# Start using my autoescape:
my $oldesc = $HTML->autoescape(\&my_autoescape);      # use sub refs ONLY!
$HTML-> ADDRESS;
$HTML-> IMG(SRC=>@'logo.gif@', ALT=>@'Fran\,cois, Inc@');
output $HTML @'Copyright (C) 1996 by Fran\,cois, Inc.!@';
$HTML->_ADDRESS;

# Stop using my autoescape:
$HTML->autoescape($oldesc);
@end example

By the way, the following are equivalent:

@example
$HTML->autoescape(@'ALL@')
$HTML->autoescape(\&HTML::Stream::escape_all);
@end example

No arguments to @code{autoescape()} returns the current autoescape function.

@unnumberedsubsec Outputting HTML to things besides filehandles

As of Revision 1.21, you no longer need to supply new() with a 
filehandle: @emph{any object that responds to a print() method will do}.
Of course, this includes @strong{blessed} FileHandles.

If you supply a GLOB reference (like @code{\*STDOUT}) or a string (like
@code{"Module::FH"}), HTML::Stream will automatically create an invisible
object for talking to that filehandle (I don@'t dare bless it into a
FileHandle, since it@'d get closed when the HTML::Stream is destroyed,
and you might not like that).

You say you want to print to a string?  For kicks and giggles, try this:

@example
package StringHandle;
sub new @{
	my $self = @'@';
	bless \$self, shift;
@}
sub print @{
    my $self = shift;
    $$self .= join(@'@', @@_);
@}

  
package main;
use HTML::Stream;

my $SH = new StringHandle;
my $HTML = new HTML::Stream $SH;
$HTML -> H1 -> "<Hello & welcome!>" -> _H1;
print "PRINTED STRING: ", $$SH, "\n";
@end example

@unnumberedsubsec Subclassing

This is where you can make your application-specific HTML-generating code
@emph{much} easier to look at.  Consider this:

@example
package MY::HTML;
@@ISA = qw(HTML::Stream);
 
sub Aside @{
	$_[0] -> FONT(SIZE=>-1) -> I;
@}
sub _Aside @{
	$_[0] -> _I -> _FONT;
@}
@end example

Now, you can do this:

@example
my $HTML = new MY::HTML \*STDOUT;

$HTML -> Aside
      -> t("Don@'t drink the milk, it@'s spoiled... pass it on...")
      -> _Aside;
@end example

If you@'re defining these markup-like, chocolate-interface-style functions,
I recommend using mixed case with a leading capital.  You probably 
shouldn@'t use all-uppercase, since that@'s what this module uses for
real HTML tags.

@unnumberedsec PERFORMANCE

Slower than I@'d like.  Both the output() method and the various "tag" 
methods seem to run about 5 times slower than the old 
just-hardcode-the-darn stuff approach.  That is, in general, this:

@example
### Approach #1...
tag  $HTML @'A@', HREF=>"$href";
tag  $HTML @'IMG@', SRC=>"logo.gif", ALT=>"LOGO";
text $HTML "My caption!";
tag  $HTML @'_A@';
text $HTML $a_lot_of_text;
@end example

And this:

@example
### Approach #2...
output $HTML [A, HREF=>"$href"], 
	         [IMG, SRC=>"logo.gif", ALT=>"LOGO"],
		 "My caption!",
		 [_A];
output $HTML $a_lot_of_text;
@end example

And this:

@example
### Approach #3...
$HTML -> A(HREF=>"$href")
	  -> IMG(SRC=>"logo.gif", ALT=>"LOGO")
	  -> t("My caption!")
	  -> _A
      -> t($a_lot_of_text);
@end example

Each run about 5x slower than this:

@example
### Approach #4...
print @'<A HREF="@', html_escape($href), @'>@',
      @'<IMG SRC="logo.gif" ALT="LOGO">@',
  	  "My caption!",
      @'</A>@';
print html_escape($a_lot_of_text);
@end example

Of course, I@'d much rather use any of first three @emph{(especially #3)} 
if I had to get something done right in a hurry.  Or did you not notice
the typo in approach #4?  @code{;-)}

(BTW, thanks to Benchmark:: for allowing me to... er... benchmark stuff.)

@unnumberedsec WHY IN THE WORLD DID I WRITE THIS?

I was just mucking about with different ways of generating large
HTML documents, seeing which ways I liked the most/least.

@unnumberedsec VERSION

$Revision: 1.24 $

@unnumberedsec AUTHOR

Eryq, eryq@@rhine.gsfc.nasa.gov .  

Enjoy.

