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 <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.