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">© 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">© 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 <firstname.lastname@example.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.