summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGianni Ceccarelli <dakkar@dechirico.(none)>2009-04-21 15:25:44 +0200
committerGianni Ceccarelli <dakkar@dechirico.(none)>2009-04-21 15:25:44 +0200
commitca60f18e9906e84355287ac427f5f9e6e6b36b41 (patch)
tree40f5fd9a1cd904ff4b1fbc62cb6ddd378736102a
parentdoc about importing (diff)
downloadTree-Template-Declare-ca60f18e9906e84355287ac427f5f9e6e6b36b41.tar.gz
Tree-Template-Declare-ca60f18e9906e84355287ac427f5f9e6e6b36b41.tar.bz2
Tree-Template-Declare-ca60f18e9906e84355287ac427f5f9e6e6b36b41.zip
docs, and changed the export-munging methods for builders
-rw-r--r--lib/Tree/Template/Declare.pm117
-rw-r--r--lib/Tree/Template/Declare/DAG_Node.pm28
-rw-r--r--lib/Tree/Template/Declare/HTML_Element.pm48
-rw-r--r--lib/Tree/Template/Declare/LibXML.pm31
-rw-r--r--t/03-html.t4
5 files changed, 217 insertions, 11 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
diff --git a/t/03-html.t b/t/03-html.t
index 08ad9c3..9cb196e 100644
--- a/t/03-html.t
+++ b/t/03-html.t
@@ -17,7 +17,7 @@ my $tree=tree {
name 'head';
node {
name 'title';
- node { name '~text'; attribs text => 'Page title' };
+ text_node 'Page title';
}
};
node {
@@ -26,7 +26,7 @@ my $tree=tree {
name 'p';
attribs id => 'p1';
attribs class => 'para';
- node { name '~text'; attribs text => 'Page para' };
+ text_node 'Page para';
};
};
};