package Data::Formatter::Html; use strict; use warnings; our $VERSION = 0.02; use base qw(Data::Formatter); ###################################### # Constructor # ###################################### sub new { my ($class, $outputHandle, %options) = @_; # Maintain a list of handles to output to my $self = bless {__OUTPUT_HANDLE => $outputHandle, __CONTENT_ONLY => $options{CONTENT_ONLY}}, $class; if (!$options{CONTENT_ONLY}) { # Append the HTML preamble $self->_write( ' Test log '); } return $self; } ###################################### # Destructor # ###################################### sub DESTROY { my ($self) = @_; if (!$self->{__CONTENT_ONLY}) { # Append the HTML ending tags $self->_write(''); } } ###################################### # Public Methods # ###################################### sub heading { my ($self, $text) = @_; return ("

$text

"); } sub emphasized { my ($self, $text) = @_; return ("$text"); } ###################################### # Protected methods # ###################################### sub _write { my ($self, $text) = @_; my $handle = $self->{__OUTPUT_HANDLE} or return; print $handle ($text); } sub _paragraph { my ($self, $arg, %options) = @_; return map { ('

', $self->_format($_),'

') } (@{$arg}); } sub _text { my ($self, $text) = @_; return ($text); } sub _table { my ($self, $rows, %options) = @_; my $border = defined $options{'tableBorder'} ? $options{'tableBorder'} : 1; my $spacing = $options{'tableSpacing'} || 1; my $width = $options{'tableWidth'} || ''; my $expandRightCol = $options{'tableExpandRightCol'}; my @buffer = (''); foreach my $row (@{$rows}) { push(@buffer, ''); foreach my $cellIdx (0 .. $#{$row}) { my $cell = $row->[$cellIdx]; # A referenced scalar in a table's cell indicates a header cell my $cellType; if (ref($cell) && ref($cell) =~ /SCALAR/) { $cellType = 'th'; my $temp = ${$cell}; $cell = $temp; } else { $cellType = 'td'; } if ($cellIdx == $#{$row} && $expandRightCol) { push(@buffer, "<$cellType" . ' valign="top" width="100%">'); } else { push(@buffer, "<$cellType" . ' valign="top">'); } push(@buffer, $self->_format($cell, %options), ""); } push(@buffer, ''); } push(@buffer, '
'); return @buffer; } sub _list { my ($self, $list, %options) = @_; my @buffer; foreach my $element (@{$list}) { # Nested lists are not contained in an item as other nested elements are. # If they were, it would look weird. if ($self->_getStructType($element) =~ /\w+_LIST/) { push(@buffer, $self->_format($element, %options)); } else { push(@buffer, '
  • ', $self->_format($element, %options), '
  • '); } } return @buffer; } sub _unorderedList { my ($self, $list, %options) = @_; return (''); } sub _orderedList { my ($self, $list, %options) = @_; return ('
      ', $self->_list($list, %options), '
    '); } sub _definitionList { my ($self, $pairs, %options) = @_; # Output the pairs in alphabetical order with respect to the key my @keys = sort (keys %{$pairs}); # Each item maps to a
    term element followed by a
    definition element my @items = map { ("
    $_
    ", '
    ', $self->_format($pairs->{$_}, %options), '
    '); } @keys; return ('
    ', @items, '
    '); } 1; =head1 NAME Data::Formatter::Html - Perl extension for formatting data stored in scalars, hashes, and arrays into strings, definition lists, and bulletted lists, etc. using HTML. =head1 SYNOPSIS use Data::Formatter::Html; my $text = new Data::Formatter::Html(\*STDOUT); $text->out('The following foods are tasty:', ['Pizza', 'Pumpkin pie', 'Sweet-n-sour Pork']); # Outputs, # # The following foods are tasty: # # $text->out('Do these things to eat an orange:', \['Peal it', 'Split it', 'Eat it']); # Outputs, # # Do these things to eat an orange: #
      #
    1. Peal it #
    2. Split it #
    3. Eat it #
    # # If you don't need to output to a file, you can also use the format() class method # instead of the out() instance method. my $nums = Data::Formatter::Html->format( 'Phone numbers' => { Pat => '123-4567', Joe => '999-9999', Xenu => '000-0000', }); # Stores in $nums: # # Phone numbers #
    #
    Joe
    999-9999
    #
    Pat
    123-4567
    #
    Xenu
    000-0000
    #
    # =head1 DESCRIPTION A module that converts Perl data structures into HTML code, formatting the data nicely for presentation to a human. For instance, refs to arrays are converted into bulleted lists, refs to arrays that contain only refs to arrays are converted into tables, and refs to hashes are converted to definition lists. All in all, data structures are mapped to display elements as follows: SCALAR => Text, REF to an ARRAY of ARRAYs => Table REF to an ARRAY => Unordered (bulleted) list Ref to a REF to an ARRAY => Ordered (numbered) list Ref to a HASH => Definition list Elements can be nested, so, for instance, you may have an array that contains one or more references to arrays, and it will be translated into a nested bulletted list. =head2 Methods =over 4 =item I->new() Returns a newly created C object. =item I->format(I) Returns the string representation of the arguments, formatted nicely. =item I<$OBJ>->out(I) Outputs the string representation of the arguments to the file stream specified in the constructor. =item I<$OBJ>->heading(I) Returns a new data-structure containing the same data as I, but which will be displayed as a heading if passed to out(). Headings are center aligned, made all uppercase, and surrounded by a thick border. For example, $text->out($text->heading("Test Results"), "All is well!"); =item I<$OBJ>->emphasized(I) Returns a new data-structure containing the same data as I, but which will be displayed as emphasized text if passed to out(). Emphasized text is made all uppercase and surrounded by a thin border. For example, $text->out($text->emphasized("Cannot find file!")); =back =head2 Example $formatter->out('Recipes', { "Zack's Kickin' Bannana Milkshake" => [ ['Ingredient', 'Amount', 'Preparation'], ['1% milk', '1 L', ''], ['Ripe Banana', '2 peeled', \['Peel bananas', 'Chop into quarters for blender']], ['Organic eggs', '1 whole', \['Crack', 'Pour']], ['Wheat germ', '1 tablespoon', ''], ['Honey', 'To taste', 'Mix it in well!'], ], "Peanutbutter and Jam Sandwich" => [ ['Ingredient', 'Amount', 'Preparation'], ['Bread', '2 slices', ''], ['Jam', 'Enough to cover inner face of slice 1', ''], ['Peanutbutter', 'Enough to cover inner face of slice 2', ''] ] } ); The code above will output the HTML: =begin html Recipes
    Peanutbutter and Jam Sandwich
    Ingredient Amount Preparation
    Bread 2 slices
    Jam Enough to cover inner face of slice 1
    Peanutbutter Enough to cover inner face of slice 2
    Zack's Kickin' Bannana Milkshake
    Ingredient Amount Preparation
    1% milk 1 L
    Ripe Banana 2 peeled
    1. Peel bananas
    2. Chop into quarters for blender
    Organic eggs 1 whole
    1. Crack
    2. Pour
    Wheat germ 1 tablespoon
    Honey To taste Mix it in well!
    =end html Note that the order of elements in a hash is not necessarily the same as the order the elements are printed in; instead, hash elements are sorted alphabetically by their keys before being output. =head1 SEE ALSO Data::Formatter::Text - A compatible module that outputs formatted information using ASCII text, rather than HTML. =head1 AUTHOR Zachary Blair, Ezack_blair@hotmail.comE =head1 COPYRIGHT AND LICENSE Copyright (C) 2008 by Zachary Blair This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself, either Perl version 5.8.8 or, at your option, any later version of Perl 5 you may have available. =cut