use 5.006; use warnings; use strict; #use Smart::Comments; #use Smart::Comments '####'; package Template::Declare::Tags; our $VERSION = '0.27'; use Template::Declare; use vars qw( @EXPORT_OK $PRIVATE $self @TagSubs ); use base 'Exporter'; use Carp qw(carp croak); use Symbol 'qualify_to_ref'; our @EXPORT = qw( with template private show show_page attr outs outs_raw in_isolation $self under get_current_attr xml_decl smart_tag_wrapper current_template create_wrapper ); our @TAG_SUB_LIST; *TagSubs = \@TAG_SUB_LIST; # For backward compatibility only our %ATTRIBUTES = (); our %ELEMENT_ID_CACHE = (); our $TAG_NEST_DEPTH = 0; our @TEMPLATE_STACK; our $SKIP_XML_ESCAPING = 0; sub import { my $self = shift; my @set_modules; if (!@_) { push @_, 'HTML'; } ### @_ ### caller: caller() # XXX We can't reset @TAG_SUB_LIST here since # use statements always run at BEGIN time. # A better approach may be install such lists # directly into the caller's namespace... #undef @TAG_SUB_LIST; while (@_) { my $lang = shift; my $opts; if (ref $_[0] and ref $_[0] eq 'HASH') { $opts = shift; $opts->{package} ||= $opts->{namespace}; # XXX TODO: carp if the derived package already exists? } $opts->{package} ||= scalar(caller); my $module = $opts->{from} || "Template::Declare::TagSet::$lang"; ### Loading tag set: $module eval "use $module"; if ($@) { warn $@; croak "Failed to load tagset module $module"; } ### TagSet options: $opts my $tagset = $module->new($opts); my $tag_list = $tagset->get_tag_list; Template::Declare::Tags::install_tag($_, $tagset) for @$tag_list; } __PACKAGE__->export_to_level(1, $self); } sub _install { my ($override, $package, $subname, $coderef) = @_; my $name = $package . '::' . $subname; my $slot = qualify_to_ref($name); return if !$override and *$slot{CODE}; no warnings 'redefine'; *$slot = $coderef; } =head1 NAME Template::Declare::Tags - Build and install XML Tag subroutines for Template::Declare =head1 SYNOPSIS package MyApp::Templates; use base 'Template::Declare'; use Template::Declare::Tags 'HTML'; template main => sub { link {} table { row { cell { "Hello, world!" } } } img { attr { src => 'cat.gif' } } img { src is 'dog.gif' } }; # Produces: # # # # # #
Hello, world!
# # package MyApp::Templates; use base 'Template::Declare'; use Template::Declare::Tags 'XUL', HTML => { namespace => 'html' }; template main => sub { groupbox { caption { attr { label => 'Colors' } } html::div { html::p { 'howdy!' } } html::br {} } }; # Produces: # # # # howdy! # # # =head1 DESCRIPTION C is used to generate and install subroutines for tags into the user's namespace. You can specify the tag sets used by providing a list of module list in the C statement: use Template::Declare::Tags qw/ HTML XUL /; By default, it uses the tag set provided by L. So use Template::Declare::Tags; is equivalent to use Template::Declare::Tags 'HTML'; Currently L bundles the following tag sets: L, L, L, and L. You can certainly specify your own tag set classes, as long as they subclass L and implement the corresponding methods (e.g. C). If you implement a custom tag set module named C. use Template::Declare::Tags 'Foo'; If you give the your tag set module a different name, say, C, then you use the C option: use Template::Declare::Tags Foo => { from => 'MyTag::Foo' }; Then C will no longer try to load C and C will be loaded instead. XML namespaces are emulated by Perl packages. For example, you can embed HTML tags within XUL using the C namespace: package MyApp::Templates; use base 'Template::Declare'; use Template::Declare::Tags 'XUL', HTML => { namespace => 'html' }; template main => sub { groupbox { caption { attr { label => 'Colors' } } html::div { html::p { 'howdy!' } } html::br {} } }; This will give you howdy! Behind the scene, C will generate a Perl package named C and install HTML tag subroutines into that package. On the other hand, XUL tag subroutines are installed into the current package, namely, C in the previous example. There are cases when you want to specify a different Perl package for a perticular XML namespace name. For instance, the C Perl package has already been used for other purposes in your application and you don't want to install subs there and mess things up, then the C option can come to rescue: package MyApp::Templates; use base 'Template::Declare'; use Template::Declare::Tags 'XUL', HTML => { namespace => 'htm', package => 'MyHtml' }; template main => sub { groupbox { caption { attr { label => 'Colors' } } MyHtml::div { MyHtml::p { 'howdy!' } } MyHtml::br {} } }; This code snippet will still generate something like the following: howdy! =head1 METHODS AND SUBROUTINES =head2 template TEMPLATENAME => sub { 'Implementation' }; C