Acme-AsciiArt2HtmlTable
view release on metacpan or search on metacpan
lib/Acme/AsciiArt2HtmlTable.pm view on Meta::CPAN
"ggggggggrrrrrrrrrrrrrr\n" .
"ggggggggrrrrrrrrrrrrrr\n" .
"ggggggggrrrrrrrrrrrrrr\n" .
"ggggggyyyyrrrrrrrrrrrr\n" .
"ggggggyyyyrrrrrrrrrrrr\n" .
"gggggyyyyyyrrrrrrrrrrr\n" .
"gggggyyyyyyrrrrrrrrrrr\n" .
"ggggggyyyyrrrrrrrrrrrr\n" .
"ggggggyyyyrrrrrrrrrrrr\n" .
"ggggggggrrrrrrrrrrrrrr\n" .
"ggggggggrrrrrrrrrrrrrr\n" .
"ggggggggrrrrrrrrrrrrrr\n" .
"ggggggggrrrrrrrrrrrrrr\n" ;
my $html = aa2ht( { td => { width => 3 , height => 3 } } , $table);
# $html now holds a table with a color representation of your
# ascii art. In this case, the Portuguese flag.
=cut
our %default_configuration;
=head1 FUNCTIONS
=head2 aa2ht
Gets ascii text and converts it to an HTML table. This is how it works:
=over 4
=item * each line is a C<tr> element
=item * each letter is a C<td> element
=item * each C<td> has background of a specific color, which is
defined by the letter that created it
=back
=cut
sub aa2ht {
# default configuration
my %config = _clone_hash( \%default_configuration );
=head3 OPTIONS
You can pass a reference to a hash before the text you want to
convert.
=cut
if ( ref($_[0]) eq 'HASH' ) {
my $new_config = shift;
=head4 id
In order to save space in the output, C<td> and C<tr> elements'
attributes are not in each element, but rather in a C<style> element.
This causes a problem if you want to put two different outputs with
different attributes on the same page.
To solve this problem: C<id>.
When creating a table, use the parameter C<id> to make sure it doesn't
end up mixed up with something else.
my $html = aa2ht( { 'id' => 'special' } $ascii );
The result will be something like this:
<style>
.special td { width:1; height:1; }
.special tr { }
</style>
<table class="special" cellspacing="0" cellpadding="0" border="0">
=cut
if (defined $new_config->{'id'}) { $config{'id'} = $new_config->{'id'} }
=head4 use-default-colors
If set to a false value, no default mappings are used.
my $html = aa2ht( { 'use-default-colors' => 0 }, $ascii);
Behind the curtains, there is still a mapping: the default mapping to
white.
=cut
if ( defined $new_config->{'use-default-colors'} ) {
if ( not $new_config->{'use-default-colors'}) {
$config{'colors'} = { 'default' => 'ffffff' } # everything is now white
}
}
=head4 colors
You can override color definitions or specify your own.
my $html = aa2ht( { 'colors' => { '@' => 'ffddee',
'g' => '00ffff' } }, $ascii);
=cut
if ( ref($new_config->{'colors'}) eq 'HASH' ) {
for (keys %{$new_config->{'colors'}}) {
$config{'colors'}{$_} = $new_config->{'colors'}{$_};
}
}
=head4 randomize-new-colors
If set to a true value, letters with no mappings are assigned a
random one.
my $html = aa2ht( { 'randomize-new-colors' => 1 }, $ascii);
You might want to remove the default mappings if you're really
interested in a completely random effect:
my $html = aa2ht( { 'use-default-colors' => 0,
'randomize-new-colors' => 1 }, $ascii);
You might also want to keep the white space as a white block:
my $html = aa2ht( { 'use-default-colors' => 0,
'colors' => { ' ' => 'ffffff'},
'randomize-new-colors' => 1 }, $ascii);
=cut
if ( defined $new_config->{'randomize-new-colors'} ) {
$config{'randomize-new-colors'} = $new_config->{'randomize-new-colors'}
}
=head4 table
With the parameter C<table> you can specify specific values for fields
like C<border>, C<cellpadding> and C<cellspacing> (all these have
value "0" by default).
my $html = aa2ht( { 'table' => { 'border' => '1' } }, $ascii );
These attributes go directly into the C<table> tag.
=head4 tr
With the C<tr> parameter you can specify specific values for C<tr>'s
attributes.
These attributes go into a C<style> tag. The table class uses that
style.
=head4 td
With the C<td> parameter you can specify specific values for C<td>'s
attributes, like C<width> or C<height>.
my $html = aa2ht( { 'td' => { 'width' => '2px',
'height' => '2px' } }, $ascii);
These attributes go into a C<style> tag. The table class uses that
style.
=cut
for my $elem ( qw/table tr td/ ) {
defined $new_config->{$elem} or next;
ref ($new_config->{$elem}) eq 'HASH' or next;
for ( keys %{$new_config->{$elem}} ) {
$config{$elem}{$_} = $new_config->{$elem}{$_};
}
}
if (defined $new_config->{'optimization'}) {
$config{'optimization'} = $new_config->{'optimization'};
}
}
##############
# prepare the table, tr and td attributes
my $table = join ' ', map { "$_=\"$config{'table'}{$_}\"" } sort keys %{$config{'table'}};
my $tr = join ' ', map { "$_:$config{'tr'}{$_};" } sort keys %{$config{'tr' }};
my $td = join ' ', map { "$_:$config{'td'}{$_};" } sort keys %{$config{'td' }};
# our ascii text
my $text = shift;
# where we'll store our html
my $html = '';
# style (td and tr elements' attributes)
$html .= "<style>\n" .
".$config{'id'} td { $td }\n.$config{'id'} tr { $tr }" .
"\n</style>\n";
# table header
$html .= "<table class=\"$config{'id'}\" $table>\n";
# prepare the cells
my @lines = map { [ split //, $_ ] } split /\n/, $text;
# just to make sure an optimized table has the same width as the normal one
my $opt_fix = '';
if ( $config{'optimization'} ) {
my $width = 0;
for my $l ( 0 .. $#lines ) {
if ( $width < $#{$lines[$l]} ) {
$width = $#{$lines[$l]};
}
}
$opt_fix = '<tr>' . ( '<td></td>' x $width ) . '</tr>';
}
for my $line ( 0 .. $#lines ) {
for my $cell ( 0 .. $#{$lines[$line]} ) {
next if $lines[$line]->[$cell] eq '';
# randomizing new colors
if ( $config{'randomize-new-colors'} ) {
if ( not defined $config{'colors'}{ $lines[$line]->[$cell] } ) {
$config{'colors'}{ $lines[$line]->[$cell] } = _random_color();
}
}
# optimization
my $optimization = '';
# debugging messages were kept for future reference
# remember that lines and cells are not the exact values, as
# arrays start at index 0 and both lines and cells start at
# position 1
#my $debug = "line $line, cell $cell, ";
if ( $config{'optimization'} ) {
#$debug .= "\nthis is line $line, cell $cell";
# check how many cells we could have on each line from the line we're
# in to the last one
my %we_could_have;
for ( $line .. $#lines ) {
$we_could_have{$_} = _count_in_the_beginning(
$lines[$line]->[$cell],
@{$lines[$_]}[$cell .. $#{$lines[$_]}]
);
#$debug .= "\nwe could have $we_could_have{$_} on line $_";
}
# check, for each line, how many cells an area up to that line would have
my %area;
my %area_width;
for ( $line .. $#lines ) {
my $min = _min( @we_could_have{$line .. $_} );
( run in 0.675 second using v1.01-cache-2.11-cpan-c966e8aa7e8 )