Here's small sample of the different ways you can use this module:
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;
# 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);
# The strawberry interface... output $HTML [A, HREF=>"$href"], [IMG, SRC=>"logo.gif", ALT=>"LOGO"], "My caption!", [_A]; output $HTML $a_lot_of_text;
There's even a small built-in subclass, HTML::Stream::Latin1 , which can handle Latin-1 input right out of the box. But all in good time...
use HTML::Stream qw(:funcs); # imports functions from @EXPORT_OK print html_tag(A, HREF=>$url); print '© 1996 by', html_escape($myname), '!'; print html_tag('/A');
By the way: that last line could be rewritten as:
print html_tag(_A);
And if you need to get a parameter in your tag that doesn't have an associated value, supply the undefined value (not the empty string!):
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="">
There are also some routines for reversing the process, like:
$text = "This <i>isn't</i> "fun"..."; print html_unmarkup($text); This isn't "fun"... print html_unescape($text); This isn't "fun"...
Yeah, yeah, yeah , I hear you cry. We've seen this stuff before. But wait! There's more...
use HTML::Stream; $HTML = new HTML::Stream \*STDOUT; tag $HTML 'A', HREF=>$url; ent $HTML 'copy'; text $HTML " 1996 by $myname!"; tag $HTML '_A';
Or, if indirect-object syntax ain't your thang:
$HTML->tag(A, HREF=>$url); $HTML->ent('copy'); $HTML->text(" 1996 by $myname!"); $HTML->tag(_A);
As you've probably guessed:
ent() Outputs an HTML entity, like the © or < . 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.
It you're not
using indirect-object syntax, you might prefer to use t()
and e()
instead of text()
and ent()
: they are absolutely identical... just shorter to type:
$HTML -> tag(A, HREF=>$url); $HTML -> e('copy'); $HTML -> t(" 1996 by $myname!"); $HTML -> tag(_A);
Now, it wouldn't be nice to give you those text()
and ent()
shortcuts without giving you one for tag()
, would it? Of course not...
$HTML -> A(HREF=>$url); $HTML -> e('copy'); $HTML -> t(" 1996 by $myname!"); $HTML -> _A;
As you've probably guessed:
A(HREF=>$url) == tag(A, HREF=>$url) == <A HREF="/the/url"> _A == tag(_A) == </A>
All such ``tag-methods'' use the tagname in all-uppercase
. A "_"
prefix on any tag-method means that an end-tag is desired. The "_"
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) _TAG
looks a little like /TAG
because of the straight line.
$HTML -> IMGG(SRC=>$src);
(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 global operation, and not stream-specific), do this:
HTML::Stream->accept_tag('MARQUEE'); # for you MSIE fans...
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 FONT
tag.
$HTML -> A(HREF=>$url) -> e('copy') -> t("1996 by $myname!") -> _A;
But wait... there's one more flavor...
p(),
a(),
etc. (especially when markup-functions
like tr()
conflict with existing Perl functions). So I came up
with this:
output $HTML [A, HREF=>$url], "Here's my $caption", [_A];
Conceptually, arrayrefs are sent to html_tag()
, and strings to
html_escape()
.
P
, _P
, and 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:
$HTML -> HTML -> HEAD -> TITLE -> t("Hello!") -> _TITLE -> _HEAD -> BODY(BGCOLOR=>'#808080');
Actually produces:
<HTML><HTML> <HEAD> <TITLE>Hello!</TITLE> </HEAD> <BODY BGCOLOR="#808080">
(This will improve slightly as time goes on). You can also output newline
explicitly via the special nl
method in the Chocolate Interface:
$HTML->nl; # one newline $HTML->nl(6); # six newlines
ent()
(or e()
) method to output an entity:
$HTML->t('Copyright ')->e('copy')->t(' 1996 by Me!');
But this can be a pain, particularly for Europeans:
$HTML -> t('Copyright ') -> e('copy') -> t(' 1996 by Fran') -> e('ccedil') -> t('ois, Inc.!');
Sooooooooo...
autoescape()
method to change the way a particular HTML::Stream works at any time.
First, here's a couple of special invocations:
$HTML->autoescape('ALL'); # escapes [<>"&] - the default $HTML->autoescape('NON_ENT'); # escapes [<>"] only, and not [&]
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):
sub my_autoescape { my $text = shift; $text = HTML::Stream::escape_all($text); # start with default $text =~ s/\(c\)/©/ig; # (C) becomes copyright $text =~ s/\\,(c)/\&$1cedil;/ig; # \,c becomes a cedilla $text; }
# 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);
If you find yourself in a situation where you're doing this a lot, a better way is to create a subclass of HTML::Stream which installs your custom function when constructed. For example, see the HTML::Stream::Latin1 example in this module, used as follows:
use HTML::Stream; $HTML = new HTML::Stream::Latin1 \*STDOUT; output $HTML "\253A right angle is 90\260, \277No?\273\n";
By the way, the following are equivalent:
$HTML->autoescape('ALL') $HTML->autoescape(\&HTML::Stream::escape_all);
No arguments to autoescape()
returns the current autoescape function.
new()
with a filehandle: any object that responds to a print() method will do
. Of course, this includes blessed
FileHandles.
If you supply a GLOB reference (like \*STDOUT
) or a string (like
"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:
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";
package MY::HTML; @ISA = qw(HTML::Stream); sub Aside { $_[0] -> FONT(SIZE=>-1) -> I; } sub _Aside { $_[0] -> _I -> _FONT; }
Now, you can do this:
my $HTML = new MY::HTML \*STDOUT; $HTML -> Aside -> t("Don't drink the milk, it's spoiled... pass it on...") -> _Aside;
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.
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:
### 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;
And this:
### Approach #2... output $HTML [A, HREF=>"$href"], [IMG, SRC=>"logo.gif", ALT=>"LOGO"], "My caption!", [_A]; output $HTML $a_lot_of_text;
And this:
### Approach #3... $HTML -> A(HREF=>"$href") -> IMG(SRC=>"logo.gif", ALT=>"LOGO") -> t("My caption!") -> _A -> t($a_lot_of_text);
Each run about 5x slower than this:
### Approach #4... print '<A HREF="', html_escape($href), '>', '<IMG SRC="logo.gif" ALT="LOGO">', "My caption!", '</A>'; print html_escape($a_lot_of_text);
Of course, I'd much rather use any of first three (especially #3)
if I had to get something done right in a hurry. Or did you not notice the
typo in approach #4? ;-)
(BTW, thanks to Benchmark:: for allowing me to... er... benchmark stuff.)
Fixed bug in accept_tag(),
where 'my' variable was shadowing
argument.
Thanks to John D Groenveld for the bug report and the patch.
Enjoy.