in reply to (OT) Styling WebSite

Oh, okay. I decided to take a whack at it. Normal HTML caveats apply, edge cases and all that, but this should work pretty well. It even tries to determine if the font tag is alone in a parent so that the style can be bumped to the parent. In cases like-

<td><font size="6">Pretty BIG</font></td> # we'll get (updated typo in "larg") <td style="font-size:x-large">Pretty BIG</td>

Barely tested though I think it's pretty solid. Improvements welcome. (Update: tested a bit and found 2 bugs, fixed now with inline test case.)

use strict; use warnings; no warnings 'uninitialized'; use HTML::TreeBuilder; use HTML::Element; my %size_convert = qw( 1 xx-small 2 x-small 3 small 4 medium 5 large 6 x-large 7 xx-large -6 40% -5 50% -4 60% -3 70% -2 80% -1 90% -0 100% +0 100% +1 120% +2 140% +3 160% +4 180% +5 200% +6 250% ); # Program proper #===================================================================== my $file = shift; $file or warn "No file given, using test HTML!\n"; $file = \*DATA; my $tree = HTML::TreeBuilder->new(); # empty tree $tree->parse_file($file); for my $node ( $tree->descendants() ) { next unless $node->tag() eq 'font'; my $font_style = extract_style( $node ); $font_style->{"font-size"} = $size_convert{ $node->attr('size') } if $size_convert{ $node->attr('size') }; $font_style->{"font-family"} = $node->attr('face') if $node->attr('face'); $font_style->{color} = $node->attr('color') if $node->attr('color'); if ( $node->parent() and $node->parent->content_list() == 1 ) { my $parent = $node->parent; my $parent_style = extract_style( $parent ); $font_style = { %{$parent_style}, %{$font_style}, }; my $style = generate_style_string($font_style); $parent->attr("style", $style); $parent->push_content( $node->as_text() ); $node->delete(); } else # replace font with span { my $style = generate_style_string($font_style); my $span = HTML::Element->new('span', style => $style ); $node->replace_with($span); } } print $tree->as_HTML(); exit 0; # Subroutines #===================================================================== sub generate_style_string { my $style_hash = shift; my @style; while ( my ( $k, $v ) = each %{$style_hash} ) { push @style, join(":", $k, $v); } return join "; ", @style; } sub extract_style { my $node = shift; my %style; %style = map { split /:/ } split /;/, $node->attr('style') if $node->attr('style'); return \%style } __DATA__ <table><tr> <td style="border:solid 1px black;"><font size="+2">Some text</font></ +td> </tr> </table> <p>Something with <font color="#ffee98" size="7" face="Times">3 style points</font></p> <p style="color:#aaa"><font color="red" face="Times">3 style points</f +ont></p>