FU
view release on metacpan or search on metacpan
FU/XMLWriter.pm view on Meta::CPAN
package FU::XMLWriter 1.4;
use v5.36;
use Carp 'confess';
use Exporter 'import';
our $XSPRINT;
BEGIN { require FU::XS unless $XSPRINT }
my @NORMAL_TAGS = qw/
a_ abbr_ address_ article_ aside_ audio_ b_ bb_ bdo_ blockquote_ body_
button_ canvas_ caption_ cite_ code_ colgroup_ datagrid_ datalist_ dd_ del_
details_ dfn_ dialog_ div_ dl_ dt_ em_ fieldset_ figure_ footer_ form_ h1_
h2_ h3_ h4_ h5_ h6_ head_ header_ i_ iframe_ ins_ kbd_ label_ legend_ li_
main_ map_ mark_ menu_ meter_ nav_ noscript_ object_ ol_ optgroup_ option_
output_ p_ pre_ progress_ q_ rp_ rt_ ruby_ samp_ script_ section_ select_
small_ span_ strong_ style_ sub_ summary_ sup_ table_ tbody_ td_ textarea_
tfoot_ th_ thead_ time_ title_ tr_ ul_ var_ video_
/;
my @SELFCLOSE_TAGS = qw/
area_ base_ br_ col_ command_ embed_ hr_ img_ input_ link_ meta_ param_
source_
/;
# Used by FU.xs to generate an XS function for each tag.
# (Wrapping tag_() within Perl is slow, using ALIAS is possible but still benefits from code gen)
if ($XSPRINT) {
sub f($name, $selfclose) {
my $tag = $name =~ s/_$//r;
my $len = length $tag;
printf <<~_;
void $name(...)
CODE:
if (!fuxmlwr_tail) fu_confess("No active FU::XMLWriter instance");
fuxmlwr_tag(aTHX_ fuxmlwr_tail, ax, 0, items, $selfclose, "$tag", $len);
_
}
f $_, 0 for @NORMAL_TAGS;
f $_, 1 for @SELFCLOSE_TAGS;
}
our %EXPORT_TAGS = (
html5_ => [ qw/tag_ html_ lit_ txt_/, @NORMAL_TAGS, @SELFCLOSE_TAGS ],
xml_ => [ qw/xml_ tag_ lit_ txt_/ ],
);
our @EXPORT_OK = (
qw/fragment xml_ xml_escape/,
@{$EXPORT_TAGS{html5_}},
);
my %XML = qw/& & < < " "/;
sub xml_escape($s) {
return '' if !defined $s;
$s =~ s/([&<"])/$XML{$1}/gr;
}
sub fragment :prototype(&) ($f) {
my $wr = _new();
$f->();
$wr->_done;
}
sub html_(@arg) {
fragment {
lit_("<!DOCTYPE html>\n");
tag_('html', @arg);
}
}
sub xml_ :prototype(&) ($f) {
FU/XMLWriter.pm view on Meta::CPAN
This is the meat of this module. Output an XML element with the given C<$name>.
C<$content> can either be C<undef> to create a self-closing tag:
tag_ 'br', undef;
# <br />
Or a string:
tag_ 'title', 'My title & stuff';
# <title>My title & stuff</title>
Or a subroutine:
tag_ 'div', sub {
tag_ 'br', undef;
};
# <div><br /></div>
Attributes can be given as key/value pairs:
tag_ 'a', href => '/?f&c', title => 'Homepage', 'link';
# <a href="/f&c" title="Homepage">link</a>
An C<undef> value causes the attribute to be ignored:
tag_ 'option', selected => time % 2 == 0 ? 'selected' : undef, '';
# Depending on the time:
# <option></option>
# Or
# <option selected="selected"></option>
A C<'+'> attribute name can be used to append a string to the previously given
attribute:
tag_ 'div', class => $is_hidden ? 'hidden' : undef,
'+' => $is_warning ? 'warning' : undef, 'Text';
# Results in either:
# <div>Text</div>
# <div class="hidden">Text</div>
# <div class="warning">Text</div>
# <div class="hidden warning">Text</div>
=item txt_($string)
Takes a Unicode string and outputs it, escaping any special XML characters in
the process.
=item lit_($string)
Takes a Unicode string and outputs it literally, i.e. without any XML escaping.
=item <html-tag>_(@attrs, $content)
This module provides a short-hand function for every HTML5 tag. Using these is
less typing and also slightly more performant than calling C<tag_()>. The
following C<tag_()>-like wrapper functions are provided:
a_ abbr_ address_ article_ aside_ audio_ b_ bb_ bdo_ blockquote_ body_
button_ canvas_ caption_ cite_ code_ colgroup_ datagrid_ datalist_ dd_ del_
details_ dfn_ dialog_ div_ dl_ dt_ em_ fieldset_ figure_ footer_ form_ h1_
h2_ h3_ h4_ h5_ h6_ head_ header_ i_ iframe_ ins_ kbd_ label_ legend_ li_
main_ map_ mark_ menu_ meter_ nav_ noscript_ object_ ol_ optgroup_ option_
output_ p_ pre_ progress_ q_ rp_ rt_ ruby_ samp_ script_ section_ select_
small_ span_ strong_ style_ sub_ summary_ sup_ table_ tbody_ td_ textarea_
tfoot_ th_ thead_ time_ title_ tr_ ul_ var_ video_
Additionally, the following self-closing-tag functions are provided:
area_ base_ br_ col_ command_ embed_ hr_ img_ input_ link_ meta_ param_
source_
The self-closing functions do not require a C<$content> argument; if none is
provided it defaults to C<undef>.
=back
=head1 Utility function
=over
=item xml_escape($string)
Return the XML-escaped version of C<$string>. The characters C<&>, C<E<lt>>,
and C<"> are replaced with their XML entity.
=back
=head1 Import options
All of the functions mentioned in this document can be imported individually.
There are also two import groups:
use FU::XMLWriter ':html5_';
Exports C<tag_()>, C<html_()>, C<lit_()>, C<txt_()> and all of the C<<
<html-tag>_ >> functions mentioned above.
use FU::XMLWriter ':xml_';
Exports C<xml_()>, C<tag_()>, C<lit_()> and C<txt_()>.
=head1 SEE ALSO
This module is part of the L<FU> framework, although it can be used
independently of it.
This module was based on L<TUWF::XML>, which was in turn inspired by
L<XML::Writer>, which is more powerful but less convenient.
There's also L<DSL::HTML>, a slightly more featureful, heavyweight and
opinionated HTML-templating-inside-Perl module, based on L<HTML::Tree>.
And there's L<HTML::Declare>, which is conceptually simpler than both this and
L<DSL::HTML>, but its syntax isn't quite as nice.
And there's also L<HTML::FromArrayref>, L<HTML::Tiny>, L<HTML::Untidy> and many
more modules on CPAN. In fact I don't know why you should use this module
instead of whatever is available on CPAN.
=head1 COPYRIGHT
( run in 1.736 second using v1.01-cache-2.11-cpan-39bf76dae61 )