PrettyPrinter(3pm)
π PrettyPrinter(3pm) π
User Contributed Perl Documentation β the manual name up top is PrettyPrinter(3pm), and bestie, this page is literally your glow-up guide for HTML output π
β¨
πΈ NAME πΈ
HTML::PrettyPrinter β generate nice HTML files from HTML syntax trees π
β¨ SYNOPSIS β¨
okay so here's the entire plot in one code block, no cap:
use HTML::TreeBuilder;
# generate a HTML syntax tree
my $tree = new HTML::TreeBuilder;
$tree->parse_file($file_name);
# modify the tree if you want
use HTML::PrettyPrinter;
my $hpp = new HTML::PrettyPrinter ('linelength' => 130,
'quote_attr' => 1);
# configure
$tree->address("0.1.0")->attr(_hpp_indent,0); # for an individual element
$hpp->set_force_nl(1,qw(body head)); # for tags
$hpp->set_force_nl(1,qw(@SECTIONS)); # as above
$hpp->set_nl_inside(0,'default!'); # for all tags
# format the source
my $linearray_ref = $hpp->format($tree);
print @$linearray_ref;
# alternative: print directly to filehandle
use FileHandle;
my $fh = new FileHandel ">$filenaem2";
if (defined $fh) {
$hpp->select($fh);
$hpp->format();
undef $fh;
$hpp->select(undef),
}
π¦ DESCRIPTION π¦
okay so real talk: HTML::PrettyPrinter produces nicely formatted HTML code from a HTML syntax tree. It is especially useful if the produced HTML file shall be read or edited manually afterwards β hi, that's you, bestie, you deserve readable markup π. And there's a whole pile of parameters that let you adapt the output to different styles and requirements. Customize away. π
Now, if you genuinely don't care how the HTML source looks as long as it is valid and readable by browsers? Then you should use the as_HTML() method of HTML::Element instead of the pretty printer. It is about five times faster. That's the tradeoff, fr fr β pretty or speedy, pick your vibe. β‘
The pretty printer will handle line wrapping, indention and structuring by the way the whitespace in the tree is represented in the output. Furthermore, all of these are configurable: upper/lowercase markup and markup minimization, quoting of attribute values, the encoding of entities, and the presence of optional end tags. So many knobs, so little time. π
There are two types of parameters to influence the output:
- individual parameters β set on a per element and per tag basis
- common parameters β set only once for each instance of a pretty printer
In order to faciliate the configuration, a mechanism to handle tag groups is provided. Thus, it is possible to modify a parameter for a group of tags (e.g. all known block elements) without writing each tag name explicitly. (Heads up though: perhaps the code for tag groups will move to another Perl module in the future. π)
For HTML::Elements that require a special treatment β like <PRE>, <XMP>, <SCRIPT>, comments and declarations β pretty printer will fall back to the method "as_HTML()" of the HTML elements. It knows when to hand it off. Periodt. π«Ά
π INDIVIDUAL PARAMETERS π
Following individual parameters exist. These are the per-element / per-tag ones, iykyk:
indentn β the indent of new lines inside the element is increased by n coloumns. Default is 2 for all tags. πΈskipbool β if true, the element and its content is skipped from output. Default is false. πnl_beforen β number of newlines before the start tag. Default is 0 for inline elements and 1 for other elements. π«nl_insiden β number of newlines between the tags and the contents of an element. Default is 0.nl_aftern β number of newlines after an element. Default is 0 for inline elements and 1 for other elements. β¨force_nlbool β force linebreaks before and after an element even if the HTML tree does not contain whitespace at this place. Default is false for inline elements and true for all other elements. This parameter is superseded if the common parameterallow_forced_nlis set to false. β οΈendtagbool β print an optional endtag. Default is true.
π Access Methods π
Following access methods exist for each individual paramenter. Just replace parameter by the respective name, bestie β the pattern is the same every time:
$hpp->parameter($element)β takes a reference to an HTML element as argument. Returns the value of the parameter for that element. The priority to retrieve the value is:- The value of the element's internal attribute
"_hpp_parameter". - The value specified inside the pretty printer for the tag of the element.
- The value specified inside the pretty printer for
'default!'.
- The value of the element's internal attribute
$hpp->parameter('tag')β like"parameter($element)", except that only priorities 2 and 3 are evaluated. π$hpp->set_parameter($value,'tag1','tag2',...)β sets the parameter for each tag in the list to $value.
If $value is undefined, the entries for the tags are deleted.
Beside individual tags the list may include tag groups like '@BLOCK' (see below) and '"default!"'. Individual tag names are written in lower case, the names of tag groups start with an '@' and are written in upper case letters. Tag groups are expanded during the call of "set_parameter()". '"default!"' sets the default value, which is retrived if no value is defined for the individual element or tag. π
$hpp->set_parameter($value,'all!')β deletes all existing settings for parameter inside the pretty printer and sets the default to $value. Like a factory reset but cute. π
π COMMON PARAMETERS π
These ones you set once, on the pretty printer itself. Iconic behaviour only:
tabifyn β if non zero, each n spaces at the beginnig of a line are converted into one TAB. Default is 8.linelengthn β the maximum number of character a line should have. Default is 80.
The linelength may be exceeded if there is no proper way to break a line without modifying the content, e.g. inside <PRE> and other special elements or if there is no whitespace. It's not being dramatic, it's just out of options. π
min_bool_attrbool β minimize boolean attributes, e.g. print<UL COMPACT>instead of<UL COMPACT=COMPACT>. Default is true.quote_attrbool β always quote attribute values. If false, attribute values consisting entirely of letters, digits, periods and hyphens only are not put into quotes. Default is false. πentitiesstring β the string contains all characters that are escaped to their entity names. Default is the bare minimum of"&<>"plus the non breaking space'nbsp'(because otherwise it is difficult for the human eye to distiguish it from a normal space in most editors). πwrap_at_tagendNEVER|AFTER_ATTR|ALWAYS β may pretty printer wrap lines before the closing ankle of a start tag? Supported values are the predifined constants:NEVERβ allow line wraps at white space onlyAFTER_ATTRβ allow line wraps at the end of tags that contain attributes onlyALWAYSβ allow line wraps at the end of every start tag
Default is AFTER_ATTR.
allow_forced_nlbool β allow the addition of white space, that is not in the HTML tree. If set to false (the default) theforce_nlparameter is ignored. It is recomended to set this parameter to true if the HTML tree was generated withignore_ignorable_whitespaceset to true. β οΈuppercasebool β use uppercase letters for markup. Default is the value of$HTML::Element::html_ucat the time the constructor is called.
π Access Method π
$hpp->paramter([value])β retrieves and optionaly sets the parameter. One method to rule them all, bestie. π
π OTHER METHODS π
$hpp = HTML::PrettyPrinter->new(%common_paremeters)β this class method creates a newHTML::PrettyPrinterand returns it. Key/value pair arguments may be provided to overwrite the default settings of common parameters. There is currently no mechanism to overwrite the default values for individual parameters at construction. Use the$hpp->set_parameter()methods instead. π«Ά$hpp->select($fh)β select aFileHandleobject for output.
If a FileHandle is selected the generated HTML is printed directly to that file. With $hpp->select(undef) you can switch back to the default behaviour. Easy come, easy go. π«
$line_array_ref = $hpp->format($tree,[$indent],[$line_array_ref])β format the HTML syntax (sub-) tree. π
$tree is not restricted to the root of the HTML syntax tree. A reference to any HTML::Element will do.
The optional $indent indents the first element by n characters.
Return value is the reference to an array with the generated lines. If such a reference is provided as third argument, the lines will be appended to that array. Otherwise a new array will be created.
If a FileHandle is selected by a previous call of the $hpp->select($fh) method, the lines are printed to the FileHandle object directly. The array of lines is not changed in this case. π
β¨ TAG GROUPS β¨
okay so tag groups?? they're literally just lists that hold the names of tags and other tag groups, and everything in there counts as a subset. it's giving very much the way allowed content gets specified in HTML DTDs β like how %flow is made up of all the %block and %inline elements, and %inline itself covers a bunch of subsets like %phrase. π
here's the tea: if you add a tag name to a group A, it shows up in every group that contains group A. so maintaining groups of tags with similar properties is actually so easy, bestie β and so is configuring the HTML pretty printer for those tags. π«Ά
naming convention, no cap: tag group names are UPPER CASE with a leading '@' (like '@BLOCK'), and plain simple tags are all lowercase.
π Functions
every single function that handles or modifies tag groups lives in the @EXPORT_OK list of "HTML::PrettyPrinter". periodt.
@tag_groups = list_groups()β hands you a list with the names of all the defined tag groups. π@tags = group_expand('tag_or_tag_group0',['tag_or_tag_group1',...])β gives you a list of every tag inside the tag groups and their subgroups. each tag appears once only, and the order of the list is not specified β do not come for the ordering, it's not that girl. β¨@tag_groups = sub_group('tag_group0',['tag_group1',...])β returns a list of every tag group and subgroup in the list. again, each group is listed once only and the order is not specified. π¦group_get('@NAME')β returns the (unexpanded) contents of a tag group. raw. unfiltered. iconic. πgroup_set('@NAME',['tag_or_tag_group0',...])β sets a tag group. π«group_add('@NAME','tag_or_tag_group0',['tag_or_tag_group1',...])β adds tags and tag groups to a group. πgroup_remove('@NAME','tag_or_tag_group0',['tag_or_tag_group1',...])β removes tags or tag groups from a group. and here's the important part, bestie: subgroups are not expanded. sogroup_remove('@A','@B')will remove'@B'from'@A'if it's included directly. tags that live inside'@B'will not be removed from'@A'. and'@A'won't change either if'@B'is included in a subgroup of'@A'but not directly in'@A'itself. iykyk π
π Predefined Tag Groups
there are a couple of predefined tag groups already chilling in there. run this
foreach my $tg (list_groups()) {
print "'$tg' => qw(".join(',',group_get($tg)).")\n";
}
to get yourself a list. π
πΈ Examples for tag groups
- create some groups π
group_set('@A',qw(a1 a2 a3));
group_set('@B',qw(b1 b2));
group_set('@C',qw(@A @B c1 @D));
# @D needs to be defined when @C is expannded
group_set('@D',qw(d1 @B));
group_set('@E',qw(e1 @D));
group_set('@F',qw(f1 @A));
- add tags π
group_add('@A',qw(a4 a5)); # @A contains (a1 a2 a3 a4 a5)
group_add('@D',qw(d1)); # @D contains (d1 @B d1)
group_add('@F',group_exapand('@B'),'@F');
# @F contains (f1 @A b1 b2 f1 @F)
- evaluate β
group_exapand('@E'); # returns e1, d1, b1, b2
sub_groups('@E'); # returns @B, @D
sub_groups(qw(@E @F)); # returns @A, @B, @D
group_get('@F')); # returns f1, @A, b1, b2, f1, @F
- remove tags π
group_remove('@E','@C'); # @E not changed, because it doesn't
contain @C
group_remove('@E','@D'); # @D removed from @E
group_remove('@D','d1'); # all d1's are removed. Now @D contains
@B only
group_remove('@C','@B'); # @C now contains (@a c1 @D), Thus
sub_groups('@C'); # still returns @A, @B, @D,
# because @B is included in @D, too
- application π¦
# set the indent for tags b1, b2, e1, g1 to 0
$hpp->set_indent(0,qw(@D @E g1));
and if the groups @D or @E get modified afterwards, the configuration of the pretty printer is not affected β because set_indent() expands the tag groups. so it already took a screenshot of that config and moved on. π
β¨ EXAMPLE β¨
Okay bestie, let's see this in action! Picture this HTML tree:
<html> @0
<head> @0.0
<title> @0.0.0
"Demonstrate HTML::PrettyPrinter"
<body> @0.1
<h1> @0.1.0
"Headline"
<p align="JUSTIFY"> @0.1.1
"Some text in "
<b> @0.1.1.1
"bold"
" and "
<i> @0.1.1.3
"italics"
" and with 'οΏ½' & 'οΏ½'."
<table align="LEFT" border=0> @0.1.2
<tr> @0.1.2.0
<td align="RIGHT"> @0.1.2.0.0
"top right"
<tr> @0.1.2.1
<td align="LEFT"> @0.1.2.1.0
"bottom left"
<hr noshade="NOSHADE" size=5> @0.1.3
<address> @0.1.4
<a href="mailto:schotten@gmx.de"> @0.1.4.0
"ClausοΏ½Schotten"
And if we run:
and "
$hpp = HTML::PrettyPrinter-"new('uppercase' => 1);
print @{$hpp->format($tree)}; >
it will print:
<HTML><HEAD><TITLE>Demonstrate
HTML::PrettyPrinter</TITLE></HEAD><BODY><H1>Headline</H1><P
ALIGN=JUSTIFY>Some text in <B>bold</B> and
<I>italics</I> and with 'οΏ½' & 'οΏ½'.</P><TABLE
ALIGN=LEFT BORDER=0><TR><TD ALIGN=RIGHT>top
right</TD></TR><TR><TD ALIGN=LEFT>bottom
left</TD></TR></TABLE><HR NOSHADE SIZE=5
><ADDRESS><A HREF="mailto:schotten@gmx.de"
>Claus Schotten</A></ADDRESS></BODY></HTML>
Hmm, that's not giving. π What went wrong? By default, HTML::PrettyPrinter is super conservative about whitespace. It will grow whitespace that's already there, but it won't add new whitespace outside of tags, because that could change how a browser renders the HTML document. But this HTML tree was built with ignore_ignorable_whitespace turned on. So there's zero whitespace between block elements for the pretty printer to work with. That means it can only do line wrapping and indentation. For example, the title is at the third level of the tree, so the second line gets indented by six characters. The table cells at the fifth level are indented by ten characters. Also, notice there's a whitespace inserted after the last attribute of the <A> tag.
Let's set $hpp->allow_forced_nl(1);. Now the forced_nl parameters are enabled. By default, they're set for all non-inline tags. That gives us:
<HTML>
<HEAD>
<TITLE>Demonstrate HTML::PrettyPrinter</TITLE>
</HEAD>
<BODY>
<H1>Headline</H1>
<P ALIGN=JUSTIFY>Some text in <B>bold</B> and
<I>italics</I> and with 'οΏ½' & 'οΏ½'.</P>
<TABLE ALIGN=LEFT BORDER=0>
<TR>
<TD ALIGN=RIGHT>top right</TD>
</TR>
<TR>
<TD ALIGN=LEFT>bottom left</TD>
</TR>
</TABLE>
<HR NOSHADE SIZE=5>
<ADDRESS><A HREF="mailto:schotten@gmx.de"
>Claus Schotten</A></ADDRESS>
</BODY>
</HTML>
Much better, right? π Now let's level up the structuring.
$hpp->set_nl_before(2,qw(body table));
$hpp->set_nl_after(2,qw(table));
This will require two new lines in front of <body> and <table> tags and after <table> tags.
<HTML>
<HEAD>
<TITLE>Demonstrate HTML::PrettyPrinter</TITLE>
</HEAD>
<BODY>
<H1>Headline</H1>
<P ALIGN=JUSTIFY>Some text in <B>bold</B> and
<I>italics</I> and with 'οΏ½' & 'οΏ½'.</P>
<TABLE ALIGN=LEFT BORDER=0>
<TR>
<TD ALIGN=RIGHT>top right</TD>
</TR>
<TR>
<TD ALIGN=LEFT>bottom left</TD>
</TR>
</TABLE>
<HR NOSHADE SIZE=5>
<ADDRESS><A HREF="mailto:schotten@gmx.de"
>Claus Schotten</A></ADDRESS>
</BODY>
</HTML>
Right now the mail address is the only attribute value that's quoted. The quotes are required because of the '@' character. For all other attribute values, quotes are optional and therefore omitted by default. $hpp->quote_attr(1); will turn the quotes on.
$hpp->set_endtag(0,'all!') turns all optional endtags off. This affects the </p> (and should affect </tr> and </td>, see below). Alternatively, we could use $hpp->set_endtag(0,'default!'). That would turn the default off too. But it wouldn't delete settings for individual tags that supersede the default.
$hpp->set_nl_after(3,'head') requires three new lines after the <head> element. Since there are already two new lines required by the start of <body>, only one additional line is added.
$hpp->set_force_nl(0,'td') will inhibit the introduction of whitespace around <td>. So the table cells are now on the same line as the table rows.
<HTML>
<HEAD>
<TITLE>Demonstrate HTML::PrettyPrinter</TITLE>
</HEAD>
<BODY>
<H1>Headline</H1>
<P ALIGN="JUSTIFY">Some text in <B>bold</B> and
<I>italics</I> and with 'οΏ½' & 'οΏ½'.
<TABLE ALIGN="LEFT" BORDER="0">
<TR><TD ALIGN="RIGHT">top right</TD></TR>
<TR><TD ALIGN="LEFT">bottom left</TD></TR>
</TABLE>
<HR NOSHADE SIZE="5">
<ADDRESS><A HREF="mailto:schotten@gmx.de"
>Claus Schotten</A></ADDRESS>
</BODY>
</HTML>
The end tags </td> and </tr> are printed because HTML::Tagset says they are mandatory.
map {$HTML::Tagset::optionalEndTag{$_}=1} qw(td tr th); will fix that.
That extra new line after </head> doesn't look nice. With $hpp->set_nl_after(undef,'head') we can reset the parameter for the <head> tag.
$hpp->entities($hpp->entities().'οΏ½'); will enforce the entity encoding of 'οΏ½'.
$hpp->min_bool_attr(0); will inhibit the minimization of the NOSHADE attribute to <hr>.
Let's fiddle with the indentation:
$hpp->set_indent(8,'@TEXTBLOCK');
$hpp->set_indent(0,'html');
New lines inside text blocks (here inside <h1>, <p>, and <address>) will be indented by 8 characters instead of two, whereas the code directly under <html> will not be indented.
<HTML>
<HEAD>
<TITLE>Demonstrate HTML::PrettyPrinter</TITLE>
</HEAD>
<BODY>
<H1>Headline</H1>
<P ALIGN="JUSTIFY">Some text in <B>bold</B> and
<I>italics</I> and with 'ä' & 'οΏ½'.
<TABLE ALIGN="LEFT" BORDER="0">
<TR><TD ALIGN="RIGHT">top right
<TR><TD ALIGN="LEFT">bottom left
</TABLE>
<HR NOSHADE="NOSHADE" SIZE="5">
<ADDRESS><A HREF="mailto:schotten@gmx.de"
>Claus Schotten</A></ADDRESS>
</BODY>
</HTML>
$hpp->wrap_at_tagend(HTML::PrettyPrinter::NEVER); will disable the line wrap between the attribute and the '>' of the <a> tag. The resulting line exceeds the target line length by far, but there's no point left where the pretty printer could legally break this line.
$hpp->set_endtag(1,'tr') will overwrite the default. So the </tr> appears in the code, while the other optional endtags are still omitted.
Finally, we customize some individual elements:
"$tree-"address('0.1.1')->attr('_hpp_skip',1)>
will skip the <p> and its content from the output
"$tree-"address('0.1.2.1.0')->attr('_hpp_force_nl',1)>
will force new lines arround the second <td>, but will not affect
the first. <td>.
<HTML>
<HEAD>
<TITLE>Demonstrate HTML::PrettyPrinter</TITLE>
</HEAD>
<BODY>
<H1>Headline</H1>
<TABLE ALIGN="LEFT" BORDER="0">
<TR><TD ALIGN="RIGHT">top right</TR>
<TR>
<TD ALIGN="LEFT">bottom left
</TR>
</TABLE>
<HR NOSHADE="NOSHADE" SIZE="5">
<ADDRESS><A
HREF="mailto:schotten@gmx.de">Claus Schotten</A></ADDRESS>
</BODY>
</HTML>
π KNOWN BUGS π
- This is early alpha code, bestie. The interfaces are subject to changes. π
- The module is tested with perl 5.005_03 only. It should work with perl 5.004 though.
- The predefined tag groups are incomplete. Several tags need to be added.
- Attribute values from a fixed set given in the DTD (e.g.
ALIGN=LEFT|RIGHTetc.) should be converted to upper or lower case depending on the value of theuppercaseparameter. Currently, they are printed as given in the HTML tree. - No optimization for performance was done.
π SEE ALSO π
HTML::TreeBuilder, HTML::Element, HTML::Tagset
π COPYRIGHT π
Copyright 2000 Claus Schotten schotten@gmx.de
This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
π AUTHOR π
Claus Schotten <schotten@gmx.de>
and that's the tea! this page is from perl v5.36.0 on 2022-11-19 β PrettyPrinter(3pm) β bye bestie π
π¦ where this page comes from
- debian bookworm: libhtml-prettyprinter-perl 0.03-5 Β· Artistic-1.0-Perl OR GPL-1.0-or-later
- debian trixie: libhtml-prettyprinter-perl 0.03-5 Β· Artistic-1.0-Perl OR GPL-1.0-or-later
- ubuntu noble: libhtml-prettyprinter-perl 0.03-5 Β· Artistic-1.0-Perl OR GPL-1.0-or-later
- ubuntu resolute: libhtml-prettyprinter-perl 0.03-5 Β· Artistic-1.0-Perl OR GPL-1.0-or-later
- ubuntu stonking: libhtml-prettyprinter-perl 0.03-5 Β· Artistic-1.0-Perl OR GPL-1.0-or-later
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms