HTML::Blitz::Builder - create HTML code dynamically and safely
use HTML::Blitz::Builder qw( mk_doctype mk_comment mk_elem to_html fuse_fragment );
This module is useful for creating snippets of HTML code (or entire documents) programmatically. It takes care of automatically escaping any strings you pass to it, which prevents the injection of HTML and script code (XSS).
To use it, call the mk_elem, mk_comment, and mk_doctype constructor functions as needed to create the document structure you want. At the very end, pass everything to to_html to obtain the corresponding HTML code.
mk_elem
mk_comment
mk_doctype
to_html
The basic data structure used by this module is the document fragment, which in Perl is represented as a list of (zero or more) node values. A node value is one of the following:
A text node, represented by a plain string.
An element node, represented by an object returned from mk_elem.
A comment node, represented by an object returned from mk_comment.
A DOCTYPE declaration, represented by an object returned from mk_doctype.
DOCTYPE
See below for the list of public functions provided by this module, which are exportable on request.
Takes a list of node values (as described above) and returns the corresponding HTML code.
The list of elements can be empty: to_html() (which is the same as to_html(())) simply returns the empty string. More generally, to_html is a homomorphism from lists to strings in that it preserves concatenation:
to_html()
to_html(())
to_html(@A, @B) eq (to_html(@A) . to_html(@B))
Creates an element with the specified name, attributes, and child nodes.
The only required argument is the element name. The optional second argument is a reference to a hash of attribute name/value pairs; omitting it is equivalent to passing {} (an empty hashref), meaning no attributes. All remaining arguments are taken to be child nodes.
{}
For example:
to_html( mk_elem("div") ) # => '<div></div>' to_html( mk_elem("div", "I <3 U") ) # => '<div>I <3 U</div>'
mk_elem is aware of "void" (i.e. content-free) elements and will not generate closing tags for them:
to_html( mk_elem("br") ) # => '<br>'
If you attempt to create a void element with child nodes, an exception will be thrown:
to_html( mk_elem("br", "Hello!") ) # error!
The same is true for elements that cannot contain nested child elements (title, textarea, style, script):
title
textarea
style
script
to_html( mk_elem("title", "Hello!") ) # => '<title>Hello!</title>' to_html( mk_elem("title", mk_elem("span", "Hello!")) ) # error!
Because the contents of style and script elements do not follow the usual HTML parsing rules, not all values can be represented:
to_html( mk_elem("p", "</p>") ) # => '<p></p></p>' to_html( mk_elem("style", "</style>") ) # error! to_html( mk_elem("script", "</script>") ) # error!
All attributes and text nodes are properly HTML escaped:
to_html( mk_elem("a", { href => "/q?a=1&b=2&c=3" }, "things, stuff, &c.") ) # => '<a href="/q?a=1&b=2&c=3">things, stuff, &c.</a>'
The result of to_html is deterministic; in particular, attributes are always generated in the same order (despite being passed in the form of a hash).
Creates a comment with the specified contents.
to_html( mk_comment("a b c") ) # => '<!--a b c-->'
Certain strings (most notably -->) cannot appear in an HTML comment, so the following will throw an exception:
-->
to_html( mk_comment("A --> B") ) # error!
Creates a DOCTYPE declaration. It takes no arguments and always produces an html doctype:
html
to_html( mk_doctype() ) # => '<!DOCTYPE html>'
Sometimes you want to store a document fragment (a list of nodes) in a single Perl value without wrapping an extra element around it. This is what fuse_fragment does: It takes a list of node values and returns a single object representing that list.
fuse_fragment
fuse_fragment is idempotent:
fuse_fragment(fuse_fragment(@nodes)) # is equivalent to fuse_fragment(@nodes)
Another way of looking at it is that as far as fragment consumers (i.e. to_html, mk_elem, and fuse_fragment itself) are concerned, fuse_fragment is transparent:
to_html( fuse_fragment(@values) ) # is the same as to_html( @values ) mk_elem($name, $attrs, fuse_fragment(@values)) # is the same as mk_elem($name, $attrs, @values)
my @fragment = mk_elem('form', { method => 'POST', action => '/login' }, mk_elem('label', 'Username: ', mk_elem('input', { name => 'user' }), ), mk_elem('label', 'Password: ', mk_elem('input', { name => 'password', type => 'password' }), ), ); my @document = ( mk_doctype, mk_elem('title', 'Log in'), mk_comment('hello, world'), @fragment, ); my $html = to_html @document; # Equivalent to: # $html = # '<!DOCTYPE html>' # . '<title>Log in</title>' # . '<!--hello, world-->' # . '<form method="POST" action="/login">' # . '<label>Username: <input name="user"></label>' # . '<label>Password: <input name="password" type="password"></label>' # . '</form>';
Lukas Mai, <lmai at web.de>
<lmai at web.de>
Copyright 2022 Lukas Mai.
This module is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
HTML::Blitz
To install HTML::Blitz, copy and paste the appropriate command in to your terminal.
cpanm
cpanm HTML::Blitz
CPAN shell
perl -MCPAN -e shell install HTML::Blitz
For more information on module installation, please visit the detailed CPAN module installation guide.