10Sstevel@tonic-gatepackage CGI::Pretty; 20Sstevel@tonic-gate 30Sstevel@tonic-gate# See the bottom of this file for the POD documentation. Search for the 40Sstevel@tonic-gate# string '=head'. 50Sstevel@tonic-gate 60Sstevel@tonic-gate# You can run this file through either pod2man or pod2html to produce pretty 70Sstevel@tonic-gate# documentation in manual or html file format (these utilities are part of the 80Sstevel@tonic-gate# Perl 5 distribution). 90Sstevel@tonic-gate 100Sstevel@tonic-gateuse strict; 110Sstevel@tonic-gateuse CGI (); 120Sstevel@tonic-gate 130Sstevel@tonic-gate$CGI::Pretty::VERSION = '1.08'; 140Sstevel@tonic-gate$CGI::DefaultClass = __PACKAGE__; 150Sstevel@tonic-gate$CGI::Pretty::AutoloadClass = 'CGI'; 160Sstevel@tonic-gate@CGI::Pretty::ISA = qw( CGI ); 170Sstevel@tonic-gate 180Sstevel@tonic-gateinitialize_globals(); 190Sstevel@tonic-gate 200Sstevel@tonic-gatesub _prettyPrint { 210Sstevel@tonic-gate my $input = shift; 220Sstevel@tonic-gate return if !$$input; 230Sstevel@tonic-gate return if !$CGI::Pretty::LINEBREAK || !$CGI::Pretty::INDENT; 240Sstevel@tonic-gate 250Sstevel@tonic-gate# print STDERR "'", $$input, "'\n"; 260Sstevel@tonic-gate 270Sstevel@tonic-gate foreach my $i ( @CGI::Pretty::AS_IS ) { 280Sstevel@tonic-gate if ( $$input =~ m{</$i>}si ) { 290Sstevel@tonic-gate my ( $a, $b, $c ) = $$input =~ m{(.*)(<$i[\s/>].*?</$i>)(.*)}si; 300Sstevel@tonic-gate next if !$b; 310Sstevel@tonic-gate $a ||= ""; 320Sstevel@tonic-gate $c ||= ""; 330Sstevel@tonic-gate 340Sstevel@tonic-gate _prettyPrint( \$a ) if $a; 350Sstevel@tonic-gate _prettyPrint( \$c ) if $c; 360Sstevel@tonic-gate 370Sstevel@tonic-gate $b ||= ""; 380Sstevel@tonic-gate $$input = "$a$b$c"; 390Sstevel@tonic-gate return; 400Sstevel@tonic-gate } 410Sstevel@tonic-gate } 420Sstevel@tonic-gate $$input =~ s/$CGI::Pretty::LINEBREAK/$CGI::Pretty::LINEBREAK$CGI::Pretty::INDENT/g; 430Sstevel@tonic-gate} 440Sstevel@tonic-gate 450Sstevel@tonic-gatesub comment { 460Sstevel@tonic-gate my($self,@p) = CGI::self_or_CGI(@_); 470Sstevel@tonic-gate 480Sstevel@tonic-gate my $s = "@p"; 490Sstevel@tonic-gate $s =~ s/$CGI::Pretty::LINEBREAK/$CGI::Pretty::LINEBREAK$CGI::Pretty::INDENT/g if $CGI::Pretty::LINEBREAK; 500Sstevel@tonic-gate 510Sstevel@tonic-gate return $self->SUPER::comment( "$CGI::Pretty::LINEBREAK$CGI::Pretty::INDENT$s$CGI::Pretty::LINEBREAK" ) . $CGI::Pretty::LINEBREAK; 520Sstevel@tonic-gate} 530Sstevel@tonic-gate 540Sstevel@tonic-gatesub _make_tag_func { 550Sstevel@tonic-gate my ($self,$tagname) = @_; 560Sstevel@tonic-gate 570Sstevel@tonic-gate # As Lincoln as noted, the last else clause is VERY hairy, and it 580Sstevel@tonic-gate # took me a while to figure out what I was trying to do. 590Sstevel@tonic-gate # What it does is look for tags that shouldn't be indented (e.g. PRE) 600Sstevel@tonic-gate # and makes sure that when we nest tags, those tags don't get 610Sstevel@tonic-gate # indented. 620Sstevel@tonic-gate # For an example, try print td( pre( "hello\nworld" ) ); 630Sstevel@tonic-gate # If we didn't care about stuff like that, the code would be 640Sstevel@tonic-gate # MUCH simpler. BTW: I won't claim to be a regular expression 650Sstevel@tonic-gate # guru, so if anybody wants to contribute something that would 660Sstevel@tonic-gate # be quicker, easier to read, etc, I would be more than 670Sstevel@tonic-gate # willing to put it in - Brian 680Sstevel@tonic-gate 690Sstevel@tonic-gate my $func = qq" 700Sstevel@tonic-gate sub $tagname {"; 710Sstevel@tonic-gate 720Sstevel@tonic-gate $func .= q' 730Sstevel@tonic-gate shift if $_[0] && 740Sstevel@tonic-gate (ref($_[0]) && 750Sstevel@tonic-gate (substr(ref($_[0]),0,3) eq "CGI" || 760Sstevel@tonic-gate UNIVERSAL::isa($_[0],"CGI"))); 770Sstevel@tonic-gate my($attr) = ""; 780Sstevel@tonic-gate if (ref($_[0]) && ref($_[0]) eq "HASH") { 790Sstevel@tonic-gate my(@attr) = make_attributes(shift()||undef,1); 800Sstevel@tonic-gate $attr = " @attr" if @attr; 810Sstevel@tonic-gate }'; 820Sstevel@tonic-gate 830Sstevel@tonic-gate if ($tagname=~/start_(\w+)/i) { 840Sstevel@tonic-gate $func .= qq! 850Sstevel@tonic-gate return "<\L$1\E\$attr>\$CGI::Pretty::LINEBREAK";} !; 860Sstevel@tonic-gate } elsif ($tagname=~/end_(\w+)/i) { 870Sstevel@tonic-gate $func .= qq! 880Sstevel@tonic-gate return "<\L/$1\E>\$CGI::Pretty::LINEBREAK"; } !; 890Sstevel@tonic-gate } else { 900Sstevel@tonic-gate $func .= qq# 910Sstevel@tonic-gate return ( \$CGI::XHTML ? "<\L$tagname\E\$attr />" : "<\L$tagname\E\$attr>" ) . 920Sstevel@tonic-gate \$CGI::Pretty::LINEBREAK unless \@_; 930Sstevel@tonic-gate my(\$tag,\$untag) = ("<\L$tagname\E\$attr>","</\L$tagname>\E"); 940Sstevel@tonic-gate 950Sstevel@tonic-gate my \%ASIS = map { lc("\$_") => 1 } \@CGI::Pretty::AS_IS; 960Sstevel@tonic-gate my \@args; 970Sstevel@tonic-gate if ( \$CGI::Pretty::LINEBREAK || \$CGI::Pretty::INDENT ) { 980Sstevel@tonic-gate if(ref(\$_[0]) eq 'ARRAY') { 990Sstevel@tonic-gate \@args = \@{\$_[0]} 1000Sstevel@tonic-gate } else { 1010Sstevel@tonic-gate foreach (\@_) { 1020Sstevel@tonic-gate \$args[0] .= \$_; 1030Sstevel@tonic-gate \$args[0] .= \$CGI::Pretty::LINEBREAK if \$args[0] !~ /\$CGI::Pretty::LINEBREAK\$/ && 0; 1040Sstevel@tonic-gate chomp \$args[0] if exists \$ASIS{ "\L$tagname\E" }; 1050Sstevel@tonic-gate 1060Sstevel@tonic-gate \$args[0] .= \$" if \$args[0] !~ /\$CGI::Pretty::LINEBREAK\$/ && 1; 1070Sstevel@tonic-gate } 1080Sstevel@tonic-gate chop \$args[0]; 1090Sstevel@tonic-gate } 1100Sstevel@tonic-gate } 1110Sstevel@tonic-gate else { 1120Sstevel@tonic-gate \@args = ref(\$_[0]) eq 'ARRAY' ? \@{\$_[0]} : "\@_"; 1130Sstevel@tonic-gate } 1140Sstevel@tonic-gate 1150Sstevel@tonic-gate my \@result; 1160Sstevel@tonic-gate if ( exists \$ASIS{ "\L$tagname\E" } ) { 1170Sstevel@tonic-gate \@result = map { "\$tag\$_\$untag\$CGI::Pretty::LINEBREAK" } 1180Sstevel@tonic-gate \@args; 1190Sstevel@tonic-gate } 1200Sstevel@tonic-gate else { 1210Sstevel@tonic-gate \@result = map { 1220Sstevel@tonic-gate chomp; 1230Sstevel@tonic-gate my \$tmp = \$_; 1240Sstevel@tonic-gate CGI::Pretty::_prettyPrint( \\\$tmp ); 1250Sstevel@tonic-gate \$tag . \$CGI::Pretty::LINEBREAK . 1260Sstevel@tonic-gate \$CGI::Pretty::INDENT . \$tmp . \$CGI::Pretty::LINEBREAK . 1270Sstevel@tonic-gate \$untag . \$CGI::Pretty::LINEBREAK 1280Sstevel@tonic-gate } \@args; 1290Sstevel@tonic-gate } 1300Sstevel@tonic-gate local \$" = "" if \$CGI::Pretty::LINEBREAK || \$CGI::Pretty::INDENT; 1310Sstevel@tonic-gate return "\@result"; 1320Sstevel@tonic-gate }#; 1330Sstevel@tonic-gate } 1340Sstevel@tonic-gate 1350Sstevel@tonic-gate return $func; 1360Sstevel@tonic-gate} 1370Sstevel@tonic-gate 1380Sstevel@tonic-gatesub start_html { 1390Sstevel@tonic-gate return CGI::start_html( @_ ) . $CGI::Pretty::LINEBREAK; 1400Sstevel@tonic-gate} 1410Sstevel@tonic-gate 1420Sstevel@tonic-gatesub end_html { 1430Sstevel@tonic-gate return CGI::end_html( @_ ) . $CGI::Pretty::LINEBREAK; 1440Sstevel@tonic-gate} 1450Sstevel@tonic-gate 1460Sstevel@tonic-gatesub new { 1470Sstevel@tonic-gate my $class = shift; 1480Sstevel@tonic-gate my $this = $class->SUPER::new( @_ ); 1490Sstevel@tonic-gate 1500Sstevel@tonic-gate if ($CGI::MOD_PERL) { 1510Sstevel@tonic-gate if ($CGI::MOD_PERL == 1) { 152*667Sps156622 my $r = Apache->request; 1530Sstevel@tonic-gate $r->register_cleanup(\&CGI::Pretty::_reset_globals); 1540Sstevel@tonic-gate } 1550Sstevel@tonic-gate else { 156*667Sps156622 my $r = Apache2::RequestUtil->request; 1570Sstevel@tonic-gate $r->pool->cleanup_register(\&CGI::Pretty::_reset_globals); 1580Sstevel@tonic-gate } 1590Sstevel@tonic-gate } 1600Sstevel@tonic-gate $class->_reset_globals if $CGI::PERLEX; 1610Sstevel@tonic-gate 1620Sstevel@tonic-gate return bless $this, $class; 1630Sstevel@tonic-gate} 1640Sstevel@tonic-gate 1650Sstevel@tonic-gatesub initialize_globals { 1660Sstevel@tonic-gate # This is the string used for indentation of tags 1670Sstevel@tonic-gate $CGI::Pretty::INDENT = "\t"; 1680Sstevel@tonic-gate 1690Sstevel@tonic-gate # This is the string used for seperation between tags 1700Sstevel@tonic-gate $CGI::Pretty::LINEBREAK = $/; 1710Sstevel@tonic-gate 1720Sstevel@tonic-gate # These tags are not prettify'd. 1730Sstevel@tonic-gate @CGI::Pretty::AS_IS = qw( a pre code script textarea td ); 1740Sstevel@tonic-gate 1750Sstevel@tonic-gate 1; 1760Sstevel@tonic-gate} 1770Sstevel@tonic-gatesub _reset_globals { initialize_globals(); } 1780Sstevel@tonic-gate 1790Sstevel@tonic-gate1; 1800Sstevel@tonic-gate 1810Sstevel@tonic-gate=head1 NAME 1820Sstevel@tonic-gate 1830Sstevel@tonic-gateCGI::Pretty - module to produce nicely formatted HTML code 1840Sstevel@tonic-gate 1850Sstevel@tonic-gate=head1 SYNOPSIS 1860Sstevel@tonic-gate 1870Sstevel@tonic-gate use CGI::Pretty qw( :html3 ); 1880Sstevel@tonic-gate 1890Sstevel@tonic-gate # Print a table with a single data element 1900Sstevel@tonic-gate print table( TR( td( "foo" ) ) ); 1910Sstevel@tonic-gate 1920Sstevel@tonic-gate=head1 DESCRIPTION 1930Sstevel@tonic-gate 1940Sstevel@tonic-gateCGI::Pretty is a module that derives from CGI. It's sole function is to 1950Sstevel@tonic-gateallow users of CGI to output nicely formatted HTML code. 1960Sstevel@tonic-gate 1970Sstevel@tonic-gateWhen using the CGI module, the following code: 1980Sstevel@tonic-gate print table( TR( td( "foo" ) ) ); 1990Sstevel@tonic-gate 2000Sstevel@tonic-gateproduces the following output: 2010Sstevel@tonic-gate <TABLE><TR><TD>foo</TD></TR></TABLE> 2020Sstevel@tonic-gate 2030Sstevel@tonic-gateIf a user were to create a table consisting of many rows and many columns, 2040Sstevel@tonic-gatethe resultant HTML code would be quite difficult to read since it has no 2050Sstevel@tonic-gatecarriage returns or indentation. 2060Sstevel@tonic-gate 2070Sstevel@tonic-gateCGI::Pretty fixes this problem. What it does is add a carriage 2080Sstevel@tonic-gatereturn and indentation to the HTML code so that one can easily read 2090Sstevel@tonic-gateit. 2100Sstevel@tonic-gate 2110Sstevel@tonic-gate print table( TR( td( "foo" ) ) ); 2120Sstevel@tonic-gate 2130Sstevel@tonic-gatenow produces the following output: 2140Sstevel@tonic-gate <TABLE> 2150Sstevel@tonic-gate <TR> 2160Sstevel@tonic-gate <TD> 2170Sstevel@tonic-gate foo 2180Sstevel@tonic-gate </TD> 2190Sstevel@tonic-gate </TR> 2200Sstevel@tonic-gate </TABLE> 2210Sstevel@tonic-gate 2220Sstevel@tonic-gate 2230Sstevel@tonic-gate=head2 Tags that won't be formatted 2240Sstevel@tonic-gate 2250Sstevel@tonic-gateThe <A> and <PRE> tags are not formatted. If these tags were formatted, the 2260Sstevel@tonic-gateuser would see the extra indentation on the web browser causing the page to 2270Sstevel@tonic-gatelook different than what would be expected. If you wish to add more tags to 2280Sstevel@tonic-gatethe list of tags that are not to be touched, push them onto the C<@AS_IS> array: 2290Sstevel@tonic-gate 2300Sstevel@tonic-gate push @CGI::Pretty::AS_IS,qw(CODE XMP); 2310Sstevel@tonic-gate 2320Sstevel@tonic-gate=head2 Customizing the Indenting 2330Sstevel@tonic-gate 2340Sstevel@tonic-gateIf you wish to have your own personal style of indenting, you can change the 2350Sstevel@tonic-gateC<$INDENT> variable: 2360Sstevel@tonic-gate 2370Sstevel@tonic-gate $CGI::Pretty::INDENT = "\t\t"; 2380Sstevel@tonic-gate 2390Sstevel@tonic-gatewould cause the indents to be two tabs. 2400Sstevel@tonic-gate 2410Sstevel@tonic-gateSimilarly, if you wish to have more space between lines, you may change the 2420Sstevel@tonic-gateC<$LINEBREAK> variable: 2430Sstevel@tonic-gate 2440Sstevel@tonic-gate $CGI::Pretty::LINEBREAK = "\n\n"; 2450Sstevel@tonic-gate 2460Sstevel@tonic-gatewould create two carriage returns between lines. 2470Sstevel@tonic-gate 2480Sstevel@tonic-gateIf you decide you want to use the regular CGI indenting, you can easily do 2490Sstevel@tonic-gatethe following: 2500Sstevel@tonic-gate 2510Sstevel@tonic-gate $CGI::Pretty::INDENT = $CGI::Pretty::LINEBREAK = ""; 2520Sstevel@tonic-gate 2530Sstevel@tonic-gate=head1 BUGS 2540Sstevel@tonic-gate 2550Sstevel@tonic-gateThis section intentionally left blank. 2560Sstevel@tonic-gate 2570Sstevel@tonic-gate=head1 AUTHOR 2580Sstevel@tonic-gate 2590Sstevel@tonic-gateBrian Paulsen <Brian@ThePaulsens.com>, with minor modifications by 2600Sstevel@tonic-gateLincoln Stein <lstein@cshl.org> for incorporation into the CGI.pm 2610Sstevel@tonic-gatedistribution. 2620Sstevel@tonic-gate 2630Sstevel@tonic-gateCopyright 1999, Brian Paulsen. All rights reserved. 2640Sstevel@tonic-gate 2650Sstevel@tonic-gateThis library is free software; you can redistribute it and/or modify 2660Sstevel@tonic-gateit under the same terms as Perl itself. 2670Sstevel@tonic-gate 2680Sstevel@tonic-gateBug reports and comments to Brian@ThePaulsens.com. You can also write 2690Sstevel@tonic-gateto lstein@cshl.org, but this code looks pretty hairy to me and I'm not 2700Sstevel@tonic-gatesure I understand it! 2710Sstevel@tonic-gate 2720Sstevel@tonic-gate=head1 SEE ALSO 2730Sstevel@tonic-gate 2740Sstevel@tonic-gateL<CGI> 2750Sstevel@tonic-gate 2760Sstevel@tonic-gate=cut 277