NAME
    HTML::Inject - inject content from one HTML file into another

SYNOPSIS
     use HTML::Inject;
 
     my $template = HTML::Inject::->new(dom => <<'TARGET');
     <!doctype html>
     <html>
        <head></head>
        <body>
           <div id="content"></div>
           <p class="copyright">&copy; 2012 Acme Inc</p>
        </body>
     </html>
     TARGET
 
     my $result = $template->inject(<<'SOURCE');
     <!doctype html>
     <html>
        <head>
           <title>Hello World</title>
        </head>
        <body>
           <div id="content">A greeting to the planet!</div>
        </body>
     </html>
     SOURCE
 
     print $result->toString;
     # <!doctype html>
     # <html>
     #    <head>
     #       <title>Hello World</title>
     #    </head>
     #    <body>
     #       <div id="content">A greeting to the planet!</div>
     #       <p class="copyright">&copy; 2012 Acme Inc</p>
     #    </body>
     # </html>

DESCRIPTION
    "HTML::Inject" is a "template system lite". It allows you to inject
    content from one HTML file (the "source") into another HTML file (the
    "target") that has placeholders for that content.

  Constructor
    "new(%attr)"
        Moose-style constructor, accepting a hash of attributes. (Actually
        this package uses Moo.)

  Attributes
    "target"
        The target HTML to inject. May be provided as an
        XML::LibXML::Document object, a file handle, a URL, a filename or a
        plain string of HTML. (To disambiguate between a string of HTML, and
        a filename/URL which is also a string, strings of HTML must contain
        at least one line break character!!) Whatever is provided, it will
        be coerced into an XML::LibXML::Document.

    "head_element_test"
        A coderef which takes an XML::LibXML::Element object and returns a
        boolean. The default is probably fairly sane, matching all
        "<title>", "<link>", "<meta>" and "<style>" elements.

        See "Injection Technique" for an explanation of the head element
        test.

    "body_element_test"
        A coderef which takes an XML::LibXML::Element object and returns a
        boolean. The default is probably fairly sane, matching all
        "<script>" and "<map>" elements.

        See "Injection Technique" for an explanation of the body element
        test.

    "missing_nodes"
        An arrayref of XML::LibXML::Node objects. You should probably not
        set this attribute in the constructor, or indeed at all. It's
        intended as a place for HTML::Inject to pass back problem nodes to
        the caller.

  Methods
    "inject($source)"
        Injects content from the source into the target returning an
        XML::LibXML::Document as the result. The result is generated by deep
        cloning the target, thus the same target can be reused again and
        again with different source data.

        Like the target passed to the constructor, the source data can be
        provided as an XML::LibXML::Document object, a file handle, a URL, a
        filename or a plain string of HTML. It may also be an arrayref of
        any of the above.

        See "Injection Technique" for more details.

    "inject_and_new($source)"
        As per "inject", but returns the result as a new HTML::Inject
        target. That is, this:

         my $template2 = $template->inject_and_new($content);

        is equivlent to:

         my $template2 = HTML::Inject::->new(
            $template->inject($content),
         );

        This is vaguely useful for some chanined operations.

  Injection Technique
    Before beginning the injection, the "missing_nodes" list is cleared.

    As a first step, HTML::Inject finds a list of potentially injectable
    nodes in the source document. Potentially injectable things are any
    nodes which are direct children of the HTML "<head>" and "<body>"
    elements.

    It then loops through the potentially injectable nodes.

    For elements which have an @id attribute, the injection technique is to
    find the element with the corresponding @id in the target document, and
    then clone the source element's contents and attributes onto the target
    element. If the target element already has contents, these will not be
    removed, and the new content is added after the existing content.

    Nodes without an @id attribute are handled differently: they are added
    to the *end* of the target document's HTML "<head>" or "<body>" element,
    but only if the element passes the "head_element_test" or
    "body_element_test". (Elements which pass both tests will be added to
    the "<head>".) This allows certain elements from the source document
    like "<meta>", "<title>" and "<script>" to be injected to the target
    document without having to worry too much about exactly where they're
    injected. They won't be injected in any especially predictable order.

    Any potentially injectable nodes which have not been injected will be
    pushed onto the "missing_nodes" list. You may wish to loop through this
    list yourself, adding them to the result document using some sort of
    logic of your choice.

  HTML Parsing
    HTML parsing is via HTML::HTML5::Parser which supports some nicely
    idiomatic HTML. The example in the "SYNOPSIS" could have used:

     my $result = $template->inject(<<'SOURCE');
     <title>Hello World</title>
     <div id="content">A greeting to the planet!</div>
     SOURCE

    That is, for the source content, you only really need to include the
    actual elements that you wish to inject. You can ignore the "skeletal
    parts" of the HTML.

  HTML Output
    The result of "inject" is an XML::LibXML::Document element. This can be
    stringified using its "toString" method. See XML::LibXML::Node for
    details.

    If serving the output as "text/html", then you may be better off
    stringifying it using HTML::HTML5::Writer which makes special effort to
    stringify documents in a way browsers can actually cope with.

    If you want your HTML nicely indented, try XML::LibXML::PrettyPrint.
    (Indenting is nice when you're debugging, but you may wish to switch it
    off for deployment, as it imposes a performance penalty.)

BUGS
    Please report any bugs to
    <http://rt.cpan.org/Dist/Display.html?Queue=HTML-Inject>.

SEE ALSO
    Cindy, Apache2::Layout, Template::Semantic.

AUTHOR
    Toby Inkster <tobyink@cpan.org>.

COPYRIGHT AND LICENCE
    This software is copyright (c) 2012 by Toby Inkster.

    This is free software; you can redistribute it and/or modify it under
    the same terms as the Perl 5 programming language system itself.

DISCLAIMER OF WARRANTIES
    THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
    WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
    MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.

