
=encoding UTF-8

=head1 NAME

HTML::Make - A flexible HTML generator

=head1 SYNOPSIS

    
    # Make a table.
    use HTML::Make;
    my $table = HTML::Make->new ('table');
    # Can add elements as text
    $table->add_text ('<tr><th>Item<th>Cost');
    my %items = (
        compressor => 12800,
        heater => 'free',
        camera => 1080,
    );
    for my $k (sort keys %items) {
        # Add an element using "push". The return value is the new element.
        my $tr = $table->push ('tr');
        # Can add element to $tr using "push"
        $tr->push ('td', text => $k);
        # Can also make a new element then "push" it.
        my $td = HTML::Make->new ('td', text => $items{$k},
                                  attr => {style => 'padding:1em'});
        $tr->push ($td);
    }
    # Get the output
    print $table->text ();


produces output

    <table>
    <tr><th>Item<th>Cost<tr><td>camera</td>
    <td style="padding:1em">1080</td>
    </tr>
    <tr><td>compressor</td>
    <td style="padding:1em">12800</td>
    </tr>
    <tr><td>heater</td>
    <td style="padding:1em">free</td>
    </tr>
    </table>


=begin HTML

<p>
As HTML, this looks like
</p>

<table>
<tr><th>Item<th>Cost<tr><td>camera</td>
<td style="padding:1em">1080</td>
</tr>
<tr><td>compressor</td>
<td style="padding:1em">12800</td>
</tr>
<tr><td>heater</td>
<td style="padding:1em">free</td>
</tr>
</table>


=end HTML

(This example is included as L<F<synopsis.pl>|https://api.metacpan.org/source/BKB/C-Tokenize-0.07/examples/synopsis.pl> in the distribution.)  

=head1 VERSION

This documents HTML::Make version 0.07 corresponding to git
commit L<9ca145cd21545344c0f29b162dc1cf469f765d05|https://github.com/benkasminbullock/HTML-Make/commit/9ca145cd21545344c0f29b162dc1cf469f765d05>
released on Thu Jan 5 13:11:29 2017 +0900.

=head1 DESCRIPTION

HTML::Make is an HTML generator. It was designed for generating HTML
fragments rather than complete pages. A typical use would be for
automating generation of a list or table within an HTML document.

=head1 METHODS

=head2 new

    my $element = HTML::Make->new ('li');

Make a new HTML element of the specified type.

It is possible to add attributes or text to the item. To add
attributes, use the following syntax:

    my $element = HTML::Make->new ('li', attr => {class => 'biglist'});

To add text,

    my $element = HTML::Make->new ('li', text => "White punks on dope");

Both attributes and text may be added:

    my $element = HTML::Make->new ('li', attr => {id => 'ok'}, text => 'OK');

HTML::Make uses the list of known HTML tags from
L</HTML::Valid::Tagset>, and will issue a warning if the type given as
the first argument to L</new> is not on its list of tags. To switch
off this behaviour, use the C<nocheck> option:

    my $freaky = HTML::Make->new ('freaky', nocheck => 1);

=head2 add_attr

    $obj->add_attr (class => 'buggles');

Add attributes to the specified object, in other words

    my $obj = HTML::Make->new ('li');
    $obj->add_attr (class => 'beano');
    my $obj_text = $obj->text ();
    # <li class="beano"></li>

This issues a warning of the form B<"Overwriting attribute 'class' for
'li'"> if the object already contains an attribute of the specified
type.

This issues a warning if the attribute is not valid for the tag,
according to L<HTML::Valid::Tagset/tag_attr_ok>. This is restricted to
what is valid in HTML5.

=head2 add_text

    $element->add_text ('buggles');

Add text to C<$element>. For example,

    my $element = HTML::Make->new ('p');
    $element->add_text ('peanuts');
    print $element->text ();
    # <p>peanuts</p>

The text may contain HTML elements:

    my $element = HTML::Make->new ('p');
    $element->add_text ('peanuts <i>eggs</i>');
    print $element->text ();
    # <p>peanuts <i>eggs</i></p>

The return value is the added text object.

=head2 push

    my $child = $element->push ('tag');

Add child element of type <tag> to C<$element> and return the result
as a new C<HTML::Make> object. For example,

    
    use utf8;
    use HTML::Make;
    my $table = HTML::Make->new ('table');
    my $row = $table->push ('tr');
    my $cell = $row->push ('td', text => 'Cell');
    print $table->text ();
    
    


produces output

    <table>
    <tr><td>Cell</td>
    </tr>
    </table>


=begin HTML

<p>
As HTML, this looks like
</p>

<table>
<tr><td>Cell</td>
</tr>
</table>


=end HTML

(This example is included as L<F<table.pl>|https://api.metacpan.org/source/BKB/C-Tokenize-0.07/examples/table.pl> in the distribution.)  

An object created with HTML::Make may also be pushed:

    
    use utf8;
    use HTML::Make;
    my @colours = (
        daidai => 0xEE7800,
        murasaki => 0x884898,
        kimidori => 0xB9C42F,
        kogecha => 0x6A4D32,
        uguisuiro => 0x838B0D,
    );
    my $ul = HTML::Make->new ('ul');
    while (@colours) {
        my $colour = shift @colours;
        my $rgb = shift @colours;
        # Here we make a new element and then push it into $ul, rather
        # than using the return value of $ul->push ().
        my $li = HTML::Make->new (
            'li', text => $colour,
            attr => {
                style => sprintf ("background: #%06X", $rgb),
            });
        $ul->push ($li);
    }
    print $ul->text ();
    
    # Inspired by
    # https://www.amazon.co.jp/gp/product/B001D7WIFY/
    # http://irocore.com/read-list/


produces output

    <ul>
    <li style="background: #EE7800">daidai</li>
    <li style="background: #884898">murasaki</li>
    <li style="background: #B9C42F">kimidori</li>
    <li style="background: #6A4D32">kogecha</li>
    <li style="background: #838B0D">uguisuiro</li>
    </ul>


=begin HTML

<p>
As HTML, this looks like
</p>

<ul>
<li style="background: #EE7800">daidai</li>
<li style="background: #884898">murasaki</li>
<li style="background: #B9C42F">kimidori</li>
<li style="background: #6A4D32">kogecha</li>
<li style="background: #838B0D">uguisuiro</li>
</ul>


=end HTML

(This example is included as L<F<push-new.pl>|https://api.metacpan.org/source/BKB/C-Tokenize-0.07/examples/push-new.pl> in the distribution.)  

It's also possible to add all of the same arguments as L</new>, for
example

    $element->push ('a', attr => {href => 'http://www.example.org/'});

This warns if you add some types of elements to possibly inappropriate
parent elements. For example if you add an <li> tag to a <tr> or
something.

=head2 opening_tag

    my $tag = $obj->opening_tag ();

Returns the text value of the HTML tag opening, complete with
attributes.

=head2 text

    $element->text ();

This function returns the element as text.

    my $p = HTML::Make->new ('p');
    print $p->text ();
    # <p></p>

=head2 multiply

    my @elements = $obj->multiply ('li', \@contents);

Create multiple child elements of C<$obj> of type given by the first
argument, with text contents given by C<\@contents>.

    
    use HTML::Make;
    my $ol = HTML::Make->new ('ol');
    $ol->multiply ('li', ['one', 'two', 'three']);
    print $ol->text ();


produces output

    <ol><li>one</li>
    <li>two</li>
    <li>three</li>
    </ol>


=begin HTML

<p>
As HTML, this looks like
</p>

<ol><li>one</li>
<li>two</li>
<li>three</li>
</ol>


=end HTML

(This example is included as L<F<multiply.pl>|https://api.metacpan.org/source/BKB/C-Tokenize-0.07/examples/multiply.pl> in the distribution.)  

=head1 EXTENDED EXAMPLES

=head2 JSON to HTML

This script converts arbitrary JSON to HTML:

    
    use utf8;
    use JSON::Parse 'parse_json';
    use HTML::Make;
    my $json =<<EOF;
    {"words":[{"j_pron_only":"パイプ","word":"pipe"},{"word":"cutting","j_pron_only":"カティング"},{"word":"implement","j_pron_only":"インプリムント"}]}
    EOF
    my $p = parse_json ($json);
    my $html = json_to_html ($p);
    print $html->text ();
    exit;
    
    sub json_to_html
    {
        my ($input) = @_;
        my $element;
        if (ref $input eq 'ARRAY') {
            $element = HTML::Make->new ('ol');
            for my $k (@$input) {
                my $li = $element->push ('li');
                $li->push (json_to_html ($k));
            }
        }
        elsif (ref $input eq 'HASH') {
            $element = HTML::Make->new ('table');
            for my $k (sort keys %$input) {
                my $tr = $element->push ('tr');
                $tr->push ('th', text => $k);
                my $td = $tr->push ('td');
                $td->push (json_to_html ($input->{$k}));
            }
        }
        else {
            $element = HTML::Make->new ('span', text => $input);
        }
        return $element;
    }


produces output

    <table>
    <tr><th>words</th>
    <td><ol>
    <li><table>
    <tr><th>j_pron_only</th>
    <td><span>パイプ</span>
    </td>
    </tr>
    <tr><th>word</th>
    <td><span>pipe</span>
    </td>
    </tr>
    </table>
    </li>
    <li><table>
    <tr><th>j_pron_only</th>
    <td><span>カティング</span>
    </td>
    </tr>
    <tr><th>word</th>
    <td><span>cutting</span>
    </td>
    </tr>
    </table>
    </li>
    <li><table>
    <tr><th>j_pron_only</th>
    <td><span>インプリムント</span>
    </td>
    </tr>
    <tr><th>word</th>
    <td><span>implement</span>
    </td>
    </tr>
    </table>
    </li>
    </ol>
    </td>
    </tr>
    </table>


=begin HTML

<p>
As HTML, this looks like
</p>

<table>
<tr><th>words</th>
<td><ol>
<li><table>
<tr><th>j_pron_only</th>
<td><span>パイプ</span>
</td>
</tr>
<tr><th>word</th>
<td><span>pipe</span>
</td>
</tr>
</table>
</li>
<li><table>
<tr><th>j_pron_only</th>
<td><span>カティング</span>
</td>
</tr>
<tr><th>word</th>
<td><span>cutting</span>
</td>
</tr>
</table>
</li>
<li><table>
<tr><th>j_pron_only</th>
<td><span>インプリムント</span>
</td>
</tr>
<tr><th>word</th>
<td><span>implement</span>
</td>
</tr>
</table>
</li>
</ol>
</td>
</tr>
</table>


=end HTML

(This example is included as L<F<json-to-html.pl>|https://api.metacpan.org/source/BKB/C-Tokenize-0.07/examples/json-to-html.pl> in the distribution.)  

=head1 BUGS

This module assumes you want to make HTML5.

There is no way to control the whitespace in the output HTML.

There is no way to add HTML comments to the output except by adding
them as text.

=head1 DEPENDENCIES

This module depends on the following Perl modules.

=over

=item Carp

L<Carp> is used to report errors.

=item HTML::Valid::Tagset

L<HTML::Valid::Tagset> is used to validate tags and tag/attribute pairs.

=back

=head1 SEE ALSO

=over

=item L<CGI>

The CGI module contains HTML generation.

=item L<HTML::Generator|http://cleancode.sourceforge.net/api/perl/HTML/Generator.html>

This project is on the SourceForge site, not CPAN.

=item L<HTML::Native>

Generate and manipulate HTML as native Perl data structures

=item L<HTML::TagTree>

An HTML generator via a tree of 'tag' objects

=item L<HTML::Template>

HTML-like templating language

=item L<HTML::Tiny>

This is similar to the HTML generation which is in L<CGI>. Its last
update, version 1.05, was in 2009, and it doesn't include HTML5 tags.

=item L<HTML::FromArrayref>

Output HTML described by a Perl data structure

=back


=head1 AUTHOR

Ben Bullock, <bkb@cpan.org>

=head1 COPYRIGHT & LICENCE

This package and associated files are copyright (C) 
2012-2016
Ben Bullock.

You can use, copy, modify and redistribute this package and associated
files under the Perl Artistic Licence or the GNU General Public
Licence.



