diff options
Diffstat (limited to 'lib/Tree')
-rw-r--r-- | lib/Tree/Template/Declare.pm | 117 | ||||
-rw-r--r-- | lib/Tree/Template/Declare/DAG_Node.pm | 28 | ||||
-rw-r--r-- | lib/Tree/Template/Declare/HTML_Element.pm | 48 | ||||
-rw-r--r-- | lib/Tree/Template/Declare/LibXML.pm | 31 |
4 files changed, 215 insertions, 9 deletions
diff --git a/lib/Tree/Template/Declare.pm b/lib/Tree/Template/Declare.pm index 4d410f3..1c4a53a 100644 --- a/lib/Tree/Template/Declare.pm +++ b/lib/Tree/Template/Declare.pm @@ -47,14 +47,9 @@ sub _build_group { } } - my $additional_exports={}; - if ($builder->can('_additional_exports')) { - $additional_exports=$builder->_additional_exports(); - } - my @current_node=(undef); - return { + my $normal_exports= { tree => sub(&) { my $tree=$builder->new_tree(); { @@ -83,8 +78,13 @@ sub _build_group { $builder->set_node_attributes($current_node[0],\%attrs); return; }, - %$additional_exports, }; + if ($builder->can('_munge_exports')) { + return $builder->_munge_exports($normal_exports); + } + else { + return $normal_exports; + } } 1; @@ -113,6 +113,109 @@ Tree::Template::Declare - easily build tree structures }; }; +=head1 FUNCTIONS + +For details on the implementation of these functions, see the +L</BUILDER> section, and the documentation of your chosen builder. + +=head2 C<tree> + +This function takes a code ref or a block, inside which calls to +C<node> should be made, and returns a properly constructed tree +containing those nodes. + +Uses the builder's C<new_tree> and C<finalize_tree>. + +=head2 C<node> + +This function takes a code ref or a block, inside which calls to +C<name>, C<attribs>, and C<node> should be made, and adds the node to +the "calling" node or tree. It also returns the node. + +Uses the builder's C<new_node> and C<add_child_node>. + +=head2 C<name> + +This function takes a scalar, and sets the name of the current node to +the value of that scalar. + +Uses the builder's C<set_node_name>. + +=head2 C<attribs> + +This function takes a hash (not a hash ref), and sets the attributes +of the current node. + +Uses the builder's C<set_node_attributes>. + +=head1 BUILDER + +To actually create nodes and trees, this module uses helper classes +called "builders". You must always specify a builder package, class or +object with the C<builder> option in the C<use> line. + +If the builder is an object, the methods discussed below will be +called on it; if it's a class (i.e. a package that has a C<new> +function), they will be called on an instance created by calling +C<new> without parameters; otherwise they will be called as class +methods. + +The builder must implement these methods: + +=over + +=item C<new_tree> + + $tree = $current_node = $builder->new_tree(); + +returns a tree object; that object will be set as the current node +within the code passed to the C<tree> function + +=item C<finalize_tree> + + return $builder->finalize_tree($tree); + +this function will be passed the object returned by C<new_tree>, after +the code passed to C<tree> has been executed; the result of +C<finalize_tree> will be the result of C<tree> + +=item C<new_node> + + $current_node=$builder->new_node(); + +returns a new, unattached node + +=item C<set_node_name> + + $builder->set_node_name($current_node, $name); + +sets the name of the node (e.g. for SGML-like trees, this is the "tag +name") + +=item C<set_node_attributes> + + $builder->set_node_attributes($current_node, \%attribs); + +sets attributes of the node; it should not remove previously-set attributes + +=item C<add_child_node> + + $builder->add_child_node($parent_node, $child_node); + +adds the second node at the end of the children list of the first node + +=back + +The builder can also implement an C<_munge_exports> method. If it +does, C<_munge_exports> will be called with a hash ref consisting of +the methods that C<Tree::Template::Declare> wants to export, and it +should return a hash ref with the methods that will actually be +exported. + +See L<Sub::Exporter>, in particular the section on group builders, for +details. See L<Tree::Template::Declare::HTML_Element> and +L<Tree::Template::Declare::LibXML> for examples. + =head1 IMPORTING This module uses L<Sub::Exporter>, although it munges the C<use> list diff --git a/lib/Tree/Template/Declare/DAG_Node.pm b/lib/Tree/Template/Declare/DAG_Node.pm index 806413d..2736a5f 100644 --- a/lib/Tree/Template/Declare/DAG_Node.pm +++ b/lib/Tree/Template/Declare/DAG_Node.pm @@ -54,3 +54,31 @@ sub set_node_attributes { } 1; +__END__ + +=head1 NAME + +Tree::Template::Declare::DAG_Node + +=head1 SYNOPSIS + +See L<Tree::Template::Declare>. + +=head1 SPECIFICITIES + +This module will build trees using L<Tree::DAG_Node>. You can make it +use another module (assuming it has the same interface, for example +L<Tree::DAG_Node::XPath>) by passing the class name to the C<new> +method. + + use Tree::Template::Declare builder => '+DAG_Node'; # default + + use Tree::Template::Declare builder => + Tree::Template::Declare::DAG_Node->new('Tree::DAG_Node::XPath'); + # custom class + +=head1 AUTHOR + +Gianni Ceccarelli <dakkar@thenautilus.net> + +=cut diff --git a/lib/Tree/Template/Declare/HTML_Element.pm b/lib/Tree/Template/Declare/HTML_Element.pm index 1480987..c2dd87c 100644 --- a/lib/Tree/Template/Declare/HTML_Element.pm +++ b/lib/Tree/Template/Declare/HTML_Element.pm @@ -10,6 +10,21 @@ sub new { return bless {},$class; } +sub _munge_exports { + my ($self,$exports)=@_; + + return { + %$exports, + text_node => sub($) { + $exports->{node}->( + sub { + $exports->{name}->('~text'); + $exports->{attribs}->(text => $_[0]); + }); + }, + }; +} + sub new_tree { my ($self)=@_; @@ -57,3 +72,36 @@ sub set_node_attributes { } 1; +__END__ + +=head1 NAME + +Tree::Template::Declare::HTML_Element + +=head1 SYNOPSIS + +See L<Tree::Template::Declare>. + +=head1 SPECIFICITIES + +This module will build trees using L<HTML::Element>. + +To create text nodes, you would be forced to say: + + node { + name '~text'; + attribs text => 'some text'; + } + +which is too cumbersone. You can instead use: + + text_node 'some text'; + +HTML::Element's C<deobjectify_text> method will be called by +C<finalize_tree> before returning the tree object. + +=head1 AUTHOR + +Gianni Ceccarelli <dakkar@thenautilus.net> + +=cut diff --git a/lib/Tree/Template/Declare/LibXML.pm b/lib/Tree/Template/Declare/LibXML.pm index f8c0e01..d5e208c 100644 --- a/lib/Tree/Template/Declare/LibXML.pm +++ b/lib/Tree/Template/Declare/LibXML.pm @@ -10,10 +10,11 @@ sub new { return bless {ns=>{':default'=>undef}},$class; } -sub _additional_exports { - my ($self)=@_; +sub _munge_exports { + my ($self,$exports)=@_; return { + %$exports, xmlns => sub($$) { $self->{ns}->{$_[0]}=$_[1]; return; @@ -95,3 +96,29 @@ sub set_node_attributes { } 1; +__END__ + +=head1 NAME + +Tree::Template::Declare::LibXML + +=head1 SYNOPSIS + +See L<Tree::Template::Declare>. + +=head1 SPECIFICITIES + +A function C<xmlns> is exported, so that you can declare XML namespaces: + + xmlns test => 'http://test/'; + + node { name 'test:elem'; attribs id => 1, 'test:attr' => 5 }; + +You I<can> create nodes with qualified names with undeclared prefixes, +but it's probably not a good idea. + +=head1 AUTHOR + +Gianni Ceccarelli <dakkar@thenautilus.net> + +=cut |