NAME
HTML::Seamstress::Quickstart - A gentle introduction to HTML::Seamstress
Introduction
This guide is designed to get you started with dynamically generating and modifying ("templating") HTML with HTML::Seamstress.
We will work through several examples, with each one increasing your ability to work with Seamstress effectively.
Sample files
All the files for the samples are in the directory lib/HTML/Seamstress/Quickstart
Pure TreeBuilder
Welcome to the first example. This is our bare-bones example. Let's say we want to dynamically modify the following HTML:
<html>
<head>
<title>Greetings</title>
</head>
<body>
<h1>Greetings</h1>
Hello there <span id=name>person</span>, your lucky number is
<span id=lucky_number>666</span>
</body>
</html>
Let's not use Seamstress at all in this case. Remember Seamstress just makes using HTML::Tree more convenient when writing software - it is completely optional and totally non-magical. So here's the (admittedly verbose) pure TreeBuilder solution:
use strict;
use warnings;
use HTML::TreeBuilder;
my $name = 'Redd Foxx';
my $number = 887;
my $tree = HTML::TreeBuilder->new_from_file('html/greeting.html');
my $name_elem = $tree->look_down(id => 'name');
$name_elem->delete_content;
$name_elem->push_content($name);
my $number_elem = $tree->look_down(id => 'lucky_number');
$number_elem->delete_content;
$number_elem->push_content($number);
print $tree->as_HTML(undef, ' ');
There's a convenience function in HTML::Element::Library which makes it easy to replace all the content of an element. This will make our script shorter. If we simply use Seamstress, its new_from_file()
method will bless the HTML tree into a class which inherits from HTML::Element::Library, making it easy for us to shorten our program.
Base bones Seamstress rework
Since we used HTML::Seamstress instead of HTML::TreeBuilder, our $tree
was blessed as an instance of HTML::Seamstress
. Since HTML::Seamstress
inherits from HTML::TreeBuilder
and HTML::Element::Library
, we have a $tree
which can use the methods of both.
We will take advantage of the replace_content
method in HTML::Element::Library to shorten our program:
use strict;
use warnings;
use HTML::Seamstress;
my $name = 'Redd Foxx';
my $number = 887;
my $tree = HTML::Seamstress->new_from_file('html/greeting.html');
my $elem = $tree->look_down(id => 'name');
$elem->replace_content($name);
$elem = $tree->look_down(id => 'lucky_number');
$elem->replace_content($number);
print $tree->as_HTML(undef, ' ');
Now of course, this program is just itching to not repeat itself, so we will clean it up just a tad:
use strict;
use warnings;
use HTML::Seamstress;
my $name = 'Redd Foxx';
my $number = 887;
my $tree = HTML::Seamstress->new_from_file('html/greeting.html');
my %replace = (
name => $name,
lucky_number => $number
);
$tree->look_down(id => $_)->replace_content($replace{$_})
for (keys %replace) ;
print $tree->as_HTML(undef, ' ');
abstract the file and our operations on it in a Perl class
Ok sweet, we have a nice tight program. But is this really application-level code? As the user of ultra-scaffolded frameworks such as Class::DBI and Catalyst, I can say no. As one who has perused the Template and HTML::Mason::HTML::Mason docs, I can say no. Our inline code must be much tighter. It must do no more than use
, new
, and $op
whatever $op
may be in this case. In other words it must be this:
use html::Greeting;
my $tree = html::Greeting->new;
$tree->process;
print $tree->as_HTML(undef, ' ');
which gives us an html::Greeting
module like this:
package html::Greeting;
use strict;
use warnings;
use base qw(HTML::Seamstress);
sub new {
my $tree = __PACKAGE__->new_from_file('html/greeting.html');
$tree;
}
sub process {
my $tree = shift;
my %replace = (
name => 'Jim Rays',
lucky_number => 222
);
$tree->look_down(id => $_)->replace_content($replace{$_})
for (keys %replace) ;
}
1;
Cleaning up our Perl class
We are flowing smoothly now with nice tight code in our application. But should we be happy with this module? I see a few drawbacks which require improvement:
our file name is given as a relative path name
Relative paths are fine as long as we are certain to start in the same directory, but we cannot be sure of that when building applications, so we need an absolute path.
we had to manually create this package
Let's fix the first problem first.
Make path to HTML file absolute
Again, Seamstress just happens to have a subroutine which guesses the name of the HTML file associated with a Seamstress-style Perl module. It is called html()
and here we see it in use to give us the path to our file in absolute fashion:
package html::GreetingAbs;
use strict;
use warnings;
use base qw(HTML::Seamstress);
use Data::Dumper;
print Dumper \%INC;
our $html = __PACKAGE__->html(__FILE__ , 'html');
{
last;
# The stuff in these braces is not for the first reading of this!
# $html is
# /ernest/dev/seamstress/lib/HTML/Seamstress/Quickstart/html/GreetingAbs.html
# but the real HTML file is greeting.html not GreetingAbs.html
$html =~ s!Abs!!;
# change Greeting to greeting since file is greeting.html not Greeting.html
$html =~ s!Greeting!greeting!;
}
sub new {
my $tree = __PACKAGE__->new_from_file($html);
$tree;
}
sub process {
my $tree = shift;
my %replace = (
name => 'Jim Rays',
lucky_number => 222
);
$tree->look_down(id => $_)->replace_content($replace{$_})
for (keys %replace) ;
}
1;
and main code body is still the same:
use html::GreetingAbs;
my $tree = html::GreetingAbs->new;
$tree->process;
print $tree->as_HTML(undef, ' ');
Automated creation of Seamstress-style packages
Instead of manually creating or copying and pasting packages to create Seamstress-style packages, the spkg.pl script in the Seamstress distribution can be of use. But I won't discuss it now.
use subroutines and Params::Validate to "componentize" your operations
The final phase in Seamstress best practices is to break each tree manipulation down into a separate subroutine whose parameters are specified by Params::Validate.
If you do this, then you can control the dynamic HTML generation by parameterizing your subs properly. This advice will make more sense as you do more complex things with Seamstress
Now you're ready for the big time! Have fun!
COPYRIGHT AND LICENSE
Copyright 2002-2006 by Terrence Brannon.
This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.