[Jifty-commit] r7543 - in Template-Declare/branches/mixmaster: . lib/Template/Declare

Jifty commits jifty-commit at lists.jifty.org
Sat Oct 10 21:07:33 EDT 2009


Author: theory
Date: Sat Oct 10 21:07:32 2009
New Revision: 7543

Modified:
   Template-Declare/branches/mixmaster/   (props changed)
   Template-Declare/branches/mixmaster/lib/Template/Declare.pm
   Template-Declare/branches/mixmaster/lib/Template/Declare/Tags.pm

Log:
Merged doc shuffling from the mixmaster_shuffle branch.

Modified: Template-Declare/branches/mixmaster/lib/Template/Declare.pm
==============================================================================
--- Template-Declare/branches/mixmaster/lib/Template/Declare.pm	(original)
+++ Template-Declare/branches/mixmaster/lib/Template/Declare.pm	Sat Oct 10 21:07:32 2009
@@ -1,7 +1,6 @@
 use 5.006;
 use warnings;
 use strict;
-use Carp;
 
 package Template::Declare;
 use Template::Declare::Buffer;
@@ -35,7 +34,7 @@
     return $ref->buffer;
 };
 
-use vars qw/$TEMPLATE_VARS/;
+our $TEMPLATE_VARS;
 
 # Backwards-compatibility support.
 sub roots {
@@ -45,27 +44,6 @@
     return [ reverse @{ $class->dispatch_to } ];
 }
 
-# Removed methods that no longer work (and were never documented anyway).
-# Remove these no-ops after a few releases (added for 0.41).
-
-=begin comment
-
-=head3 aliases
-
-=head3 alias_metadata
-
-=cut
-
-sub aliases {
-    require Carp;
-    Carp::cluck( 'aliases() is a deprecated no-op' );
-}
-
-sub alias_metadata {
-    require Carp;
-    Carp::cluck( 'alias_metadata() is a deprecated no-op' );
-}
-
 =head1 NAME
 
 Template::Declare - Perlish declarative templates
@@ -147,7 +125,7 @@
 
 =head2 Basic usage
 
-A simple HTML example is in the L<SYNOPSIS/SYNOPSIS>. So let's do XUL!
+A simple HTML example is in the L</SYNOPSIS>. So let's do XUL!
 
     package MyApp::Templates;
     use base 'Template::Declare';
@@ -357,10 +335,6 @@
  <h1>Hello</h1>
  <div>first post</div>
 
-=head2 Aliasing and Mixins
-
-=head2 Class Search Dispatching
-
 =head1 METHODS
 
 =head2 init
@@ -424,109 +398,139 @@
 
 }
 
-=head2 buffer
+=head2 show TEMPLATE_NAME
 
-Gets or sets the L<String::BufferStack> object; this is a class method. You
-can use it to manipulate the output from tags as they are output. It's used
-internally to make the tags nest correctly, and be output to the right place.
-We're not sure if there's ever a need for you to frob it by hand, but it does
-enable things like the following:
+    Template::Declare->show( 'howdy', name => 'Larry' );
+    my $output = Template::Declare->show('index');
 
-    template simple => sub {
-       html {
-           head {}
-           body {
-               Template::Declare->buffer->set_filter( sub {uc shift} );
-               p { 'Whee!' }
-               p { 'Hello, world wide web!' }
-               Template::Declare->buffer->clear_top if rand() < 0.5;
-           }
-       }
-    };
+Call C<show> with a C<template_name> and C<Template::Declare> will render that
+template. Subsequent arguments will be passed to the template. Content
+generated by C<show()> can be accessed via the C<output()> method if the
+output method you've chosen returns content instead of outputting it directly.
 
-...which outputs, with equal regularity, either:
+If called in scalar context, this method will also just return the content
+when available.
 
- <html>
-  <head></head>
-  <body>
-   <P>WHEE!</P>
-   <P>HELLO, WORLD WIDE WEB!</P>
-  </body>
- </html>
+=cut
 
-...or:
+sub show {
+    my $class    = shift;
+    my $template = shift;
+    local %Template::Declare::Tags::ELEMENT_ID_CACHE = ();
+    return Template::Declare::Tags::show_page($template => @_);
+}
 
- <html>
-  <head></head>
-  <body></body>
- </html>
+=head2 Mixing templates
 
-We'll leave it to you to judge whether or not that's actually useful.
+Sometimes you want to mix templates from one class into another class;
+C<mix()> is your key to doing so.
 
-=head2 new_buffer_frame
+=head3 mix
 
-  $td->new_buffer_frame();
+    mix Some::Clever::Mixin      under '/mixin';
+    mix Some::Other::Mixin       under '/otmix', setting { name => 'Larry' };
+    mix My::Mixin into My::View, under '/mymix';
 
-Creates a new buffer frame, using L<String::BufferStack/push> with C<private>.
-This use is deprecated in favor of dealing with L</buffer> directly.
+In the first example, if Some::Clever::Mixin
+creates templates named C<foo> and C<bar>, they will be mixed into the calling
+template class as C<mixin/foo> and C<mixin/bar>.
 
-=cut
+The second example mixes in the templates defined in Some::Other::Mixin into
+into the calling class under the C</mymix> path. Furthermore, those mixed-in
+templates have package variables set for them that are accessible only from
+their mixed-in paths. For example, if this template was defined in
+Some::Other::Mixin:
 
-sub new_buffer_frame {
-    __PACKAGE__->buffer->push( private => 1 );
-}
+    template howdy => sub {
+        my $self = shift;
+        outs "Howdy, " . $self->package_variable('name') || 'Jesse';
+    };
+
+Then C<show('mymixin/howdy')> will output "Howdy, Larry", while the output
+from C<show('howdy')> will output "Howdy, Jesse". In other words, package
+variables defined for the mixed-in templates are available only to the mixins
+and not to the original.
+
+In either case, ineritance continues to work. A template package that inherits
+from Some::Other::Mixin, for example, will be able to access both
+C<mymixin/howdy> and C<howdy>.
+
+By default, C<mix()> will mix templates into the class from which it's called.
+But sometimes you might want to mix templates into some other template class.
+Such might be useful for end users to compose template structures from
+collections of template classes. In such a case, use the C<into> keyword to
+specify into what class the templates should be mixed in. The third example
+demonstrates this, where My::Mixin templates are mixed into My::View. Of
+course, you can still specify variables to set for those mixins.
 
-=head2 end_buffer_frame
+If you should happen to forget to pass the C<into> argument before C<under>,
+worry not, C<mix()> will figure it out and do the right thing.
 
-  my $buf = $td->end_buffer_frame();
+For those who prefer a direct OO syntax for mixins, just call C<mix()> as a
+method on the class to be mixed in. To replicate the above three exmaples
+without the use of the sugar:
 
-Deletes and returns the topmost buffer, using L<String::BufferStack/pop>. This
-use is deprecated in favor of dealing with L</buffer> directly..
+    Some::Clver::Mixin->mix( '/mixin' );
+    Some::Other::Mixin->mix( '/otmix', { name => 'Larry' } );
+    My::Mixin->mix('My::View', '/mymix');
 
 =cut
 
-sub end_buffer_frame {
-    __PACKAGE__->buffer->pop;
+sub mix {
+    my $mixin = shift;
+    my ($into, $under);
+    if ( eval { $_[0]->isa(__PACKAGE__) } ) {
+        ($into, $under) = (shift, shift);
+    } elsif ( eval { $_[1]->isa(__PACKAGE__) } ) {
+        ($under, $into) = (shift, shift);
+    } else {
+        $into  = caller(0);
+        $under = shift;
+    }
+    $mixin->_import($into, $under, @_);
 }
 
-=head2 show TEMPLATE_NAME
-
-    Template::Declare->show( 'howdy', name => 'Larry' );
-    my $output = Template::Declare->show('index');
+=head3 package_variable( VARIABLE )
 
-Call C<show> with a C<template_name> and C<Template::Declare> will render that
-template. Subsequent arguments will be passed to the template. Content
-generated by C<show()> can be accessed via the C<output()> method if the
-output method you've chosen returns content instead of outputting it directly.
+  $td->package_variable( $varname => $value );
+  $value = $td->package_variable( $varname );
 
-If called in scalar context, this method will also just return the content
-when available.
+Returns a value set for a mixed-in template's variable, if any were specified
+when the template was mixed-in. See L</mix> for details.
 
 =cut
 
-sub show {
-    my $class    = shift;
-    my $template = shift;
-    local %Template::Declare::Tags::ELEMENT_ID_CACHE = ();
-    return Template::Declare::Tags::show_page($template => @_);
+sub package_variable {
+    my $self = shift;
+    my $var  = shift;
+    if (@_) {
+        $TEMPLATE_VARS->{$self}->{$var} = shift;
+    }
+    return $TEMPLATE_VARS->{$self}->{$var};
 }
 
-=head2 path_for $template
+=head3 package_variables( VARIABLE )
 
-    my $path = Template::Declare->path_for('index');
+    $td->package_variables( $variables );
+    $variables = $td->package_variables;
 
-Returns the path for the template name to be used for show, adjusted with
-paths used in C<mix>.
+Get or set a hash reference of variables for a mixed-in template. See
+L</mix> for details.
 
 =cut
 
-sub path_for {
-    my $class = shift;
-    my $template = shift;
-    return ($class->imported_into ||'') . '/' . $template;
+sub package_variables {
+    my $self = shift;
+    if (@_) {
+        %{ $TEMPLATE_VARS->{$self} } = shift;
+    }
+    return $TEMPLATE_VARS->{$self};
 }
 
-=head2 resolve_template TEMPLATE_PATH INCLUDE_PRIVATE_TEMPLATES
+
+=head2 Templates registration and lookup
+
+=head3 resolve_template TEMPLATE_PATH INCLUDE_PRIVATE_TEMPLATES
 
     my $code = Template::Declare->resolve_template($template);
     my $code = Template::Declare->has_template($template, 1);
@@ -539,10 +543,6 @@
 C<dispatch_to>. For each class, it looks to see if it has a template called
 $template_name directly (or via a mixin).
 
-=head2 has_template TEMPLATE_PATH INCLUDE_PRIVATE_TEMPLATES
-
-An alias for C<resolve_template>.
-
 =cut
 
 sub resolve_template {
@@ -568,9 +568,15 @@
     }
 }
 
+=head3 has_template TEMPLATE_PATH INCLUDE_PRIVATE_TEMPLATES
+
+An alias for C<resolve_template>.
+
+=cut
+
 sub has_template { resolve_template(@_) }
 
-=head2 register_template( TEMPLATE_NAME, CODEREF )
+=head3 register_template( TEMPLATE_NAME, CODEREF )
 
     MyApp::Templates->register_template( howdy => sub { ... } );
 
@@ -589,7 +595,7 @@
     _register_template( $class, _template_name_to_sub($template_name), $code )
 }
 
-=head2 register_private_template( TEMPLATE_NAME, CODEREF )
+=head3 register_private_template( TEMPLATE_NAME, CODEREF )
 
     MyApp::Templates->register_private_template( howdy => sub { ... } );
 
@@ -613,142 +619,161 @@
 
 }
 
-=head2 mix
-
-    mix Some::Clever::Mixin      under '/mixin';
-    mix Some::Other::Mixin       under '/otmix', setting { name => 'Larry' };
-    mix My::Mixin into My::View, under '/mymix';
+=head3 buffer
 
-Sometimes you want to mix templates from one class into another class;
-C<mix()> is your key to doing so. In the first example, if Some::Clever::Mixin
-creates templates named C<foo> and C<bar>, they will be mixed into the calling
-template class as C<mixin/foo> and C<mixin/bar>.
+Gets or sets the L<String::BufferStack> object; this is a class method.
 
-The second example mixes in the templates defined in Some::Other::Mixin into
-into the calling class under the C</mymix> path. Furthermore, those mixed-in
-templates have package variables set for them that are accessible only from
-their mixed-in paths. For example, if this template was defined in
-Some::Other::Mixin:
+You can use it to manipulate the output from tags as they are output. It's used
+internally to make the tags nest correctly, and be output to the right place.
+We're not sure if there's ever a need for you to frob it by hand, but it does
+enable things like the following:
 
-    template howdy => sub {
-        my $self = shift;
-        outs "Howdy, " . $self->package_variable('name') || 'Jesse';
+    template simple => sub {
+       html {
+           head {}
+           body {
+               Template::Declare->buffer->set_filter( sub {uc shift} );
+               p { 'Whee!' }
+               p { 'Hello, world wide web!' }
+               Template::Declare->buffer->clear_top if rand() < 0.5;
+           }
+       }
     };
 
-Then C<show('mymixin/howdy')> will output "Howdy, Larry", while the output
-from C<show('howdy')> will output "Howdy, Jesse". In other words, package
-variables defined for the mixed-in templates are available only to the mixins
-and not to the original.
-
-In either case, ineritance continues to work. A template package that inherits
-from Some::Other::Mixin, for example, will be able to access both
-C<mymixin/howdy> and C<howdy>.
+...which outputs, with equal regularity, either:
 
-By default, C<mix()> will mix templates into the class from which it's called.
-But sometimes you might want to mix templates into some other template class.
-Such might be useful for end users to compose template structures from
-collections of template classes. In such a case, use the C<into> keyword to
-specify into what class the templates should be mixed in. The third example
-demonstrates this, where My::Mixin templates are mixed into My::View. Of
-course, you can still specify variables to set for those mixins.
+ <html>
+  <head></head>
+  <body>
+   <P>WHEE!</P>
+   <P>HELLO, WORLD WIDE WEB!</P>
+  </body>
+ </html>
 
-If you should happen to forget to pass the C<into> argument before C<under>,
-worry not, C<mix()> will figure it out and do the right thing.
+...or:
 
-For those who prefer a direct OO syntax for mixins, just call C<mix()> as a
-method on the class to be mixed in. To replicate the above three exmaples
-without the use of the sugar:
+ <html>
+  <head></head>
+  <body></body>
+ </html>
 
-    Some::Clver::Mixin->mix( '/mixin' );
-    Some::Other::Mixin->mix( '/otmix', { name => 'Larry' } );
-    My::Mixin->mix('My::View', '/mymix');
+We'll leave it to you to judge whether or not that's actually useful.
 
-=cut
+=head2 Helpers
 
-sub mix {
-    my $mixin = shift;
-    my ($into, $under);
-    if ( eval { $_[0]->isa(__PACKAGE__) } ) {
-        ($into, $under) = (shift, shift);
-    } elsif ( eval { $_[1]->isa(__PACKAGE__) } ) {
-        ($under, $into) = (shift, shift);
-    } else {
-        $into  = caller(0);
-        $under = shift;
-    }
-    $mixin->_import($into, $under, @_);
-}
+You don't need to call any of this directly.
 
-=head2 into
+=head3 into
 
-  $class = into $class;
+    $class = into $class;
 
-C<into> is a helper method providing semantic sugar for the C<mix()> method.
+C<into> is a helper method providing semantic sugar for the L</mix> method.
 All it does is return the name of the class on which it was called.
 
 =cut
 
 sub into { shift }
 
-=head2 alias
+=head2 Old, deprecated or just better to avoid
+
+=head3 alias
 
     alias Some::Clever::Mixin under '/mixin';
     alias Some::Other::Mixin  under '/mymix', { name => 'Larry' };
 
 Like C<mix()>, but without support for the C<into> keyword. That is, it mixes
-templates into the calling template class. Deprecated in favor of C<mix()>.
+templates into the calling template class.
+
+B<Deprecated> in favor of L</mix>. Will be supported for a long time, but
+new code should use C<mix()>.
 
 =cut
 
 sub alias { shift->_import(scalar caller(0), @_) }
 
-=head2 import_templates
+=head3 import_templates
 
     import_templates MyApp::Templates under '/something';
 
 Like C<mix()>, but without support for the C<into> or C<setting> keywords.
 That is, it mixes templates into the calling template class and does not
-support package variables for those mixins. Deprecated in favor of C<mix()>.
+support package variables for those mixins.
+
+B<Deprecated> in favor of L</mix>. Will be supported for a long time, but
+new code should use C<mix()>.
 
 =cut
 
 sub import_templates { shift->_import(scalar caller(0), @_) }
 
-=head2 package_variable( VARIABLE )
+=head3 new_buffer_frame
 
-  $td->package_variable( $varname => $value );
-  $value = $td->package_variable( $varname );
+    $td->new_buffer_frame;
+    # same as 
+    $td->buffer->push( private => 1 );
 
-Returns a value set for a mixed-in template's variable, if any were specified
-when the template was mixed-in. See L<mix/mix> for details.
+Creates a new buffer frame, using L<String::BufferStack/push> with C<private>.
+
+B<Deprecated> in favor of dealing with L</buffer> directly.
 
 =cut
 
-sub package_variable {
-    my $self = shift;
-    my $var  = shift;
-    if (@_) {
-        $TEMPLATE_VARS->{$self}->{$var} = shift;
-    }
-    return $TEMPLATE_VARS->{$self}->{$var};
+sub new_buffer_frame {
+    __PACKAGE__->buffer->push( private => 1 );
 }
 
-=head2 package_variables( VARIABLE )
+=head3 end_buffer_frame
 
-  $td->package_variables( $variables );
-  $variables = $td->package_variables( );
+    my $buf = $td->end_buffer_frame;
+    # same as
+    my $buf = $td->buffer->pop;
 
-Get or set a hash reference of variables for a mixed-in template. See
-L<mix/mix> for details.
+Deletes and returns the topmost buffer, using L<String::BufferStack/pop>.
+
+B<Deprecated> in favor of dealing with L</buffer> directly.
 
 =cut
 
-sub package_variables {
-    my $self = shift;
-    if (@_) {
-        %{ $TEMPLATE_VARS->{$self} } = shift;
-    }
-    return $TEMPLATE_VARS->{$self};
+sub end_buffer_frame {
+    __PACKAGE__->buffer->pop;
+}
+
+=head3 path_for $template
+
+    my $path = Template::Declare->path_for('index');
+
+Returns the path for the template name to be used for show, adjusted with
+paths used in C<mix>.
+
+=cut
+
+# Removed methods that no longer work (and were never documented anyway).
+# Remove these no-ops after a few releases (added for 0.41).
+
+=begin comment
+
+=head3 aliases
+
+=head3 alias_metadata
+
+=end comment
+
+=cut
+
+sub aliases {
+    require Carp;
+    Carp::cluck( 'aliases() is a deprecated no-op' );
+}
+
+sub alias_metadata {
+    require Carp;
+    Carp::cluck( 'alias_metadata() is a deprecated no-op' );
+}
+
+sub path_for {
+    my $class = shift;
+    my $template = shift;
+    return ($class->imported_into ||'') . '/' . $template;
 }
 
 sub _templates_for {
@@ -845,7 +870,8 @@
 sub _import_code {
     my ($tname, $from, $to, $vars) = @_;
     my $code = $from->_find_template_sub( _template_name_to_sub($tname) );
-    return $to eq $from ? $code : sub { $code->($to, @_) } unless $vars;
+    return $to eq $from ? $code : sub { $code->($to, @_) }
+        unless $vars;
     return sub {
         # XXX This does not seem to be needed.
         # shift @_;  # Get rid of the passed-in "$self" class.
@@ -971,7 +997,7 @@
 
 Crawling all over, baby. Be very, very careful. This code is so cutting edge,
 it can only be fashioned from carbon nanotubes. But we're already using this
-thing in production :) Make sure you have read the L<PITFALLS/PITFALLS>
+thing in production :) Make sure you have read the L</PITFALLS>
 section above :)
 
 Some specific bugs and design flaws that we'd love to see fixed.

Modified: Template-Declare/branches/mixmaster/lib/Template/Declare/Tags.pm
==============================================================================
--- Template-Declare/branches/mixmaster/lib/Template/Declare/Tags.pm	(original)
+++ Template-Declare/branches/mixmaster/lib/Template/Declare/Tags.pm	Sat Oct 10 21:07:32 2009
@@ -116,14 +116,14 @@
 
 Produces:
 
- <link />
- <table>
-  <tr>
-   <td>Hello, world!</td>
-  </tr>
- </table>
- <img src="cat.gif" />
- <img src="dog.gif" />
+    <link />
+    <table>
+     <tr>
+      <td>Hello, world!</td>
+     </tr>
+    </table>
+    <img src="cat.gif" />
+    <img src="dog.gif" />
 
 Using XUL templates with a namespace:
 
@@ -143,13 +143,13 @@
 
 Produces:
 
- <groupbox>
-  <caption label="Colors" />
-  <html:div>
-   <html:p>howdy!</html:p>
-  </html:div>
-  <html:br></html:br>
- </groupbox>
+    <groupbox>
+     <caption label="Colors" />
+     <html:div>
+      <html:p>howdy!</html:p>
+     </html:div>
+     <html:br></html:br>
+    </groupbox>
 
 =head1 DESCRIPTION
 
@@ -209,13 +209,13 @@
 
 This will output:
 
- <groupbox>
-  <caption label="Colors" />
-  <html:div>
-   <html:p>howdy!</html:p>
-  </html:div>
-  <html:br></html:br>
- </groupbox>
+    <groupbox>
+     <caption label="Colors" />
+     <html:div>
+      <html:p>howdy!</html:p>
+     </html:div>
+     <html:br></html:br>
+    </groupbox>
 
 Behind the scenes, C<Template::Declare::Tags> generates a Perl package named
 C<html> and installs the HTML tag subroutines into that package. On the other
@@ -245,17 +245,19 @@
 
 This code will generate something like the following:
 
- <groupbox>
-  <caption label="Colors" />
-  <htm:div>
-   <htm:p>howdy!</htm:p>
-  </htm:div>
-  <htm:br></htm:br>
- </groupbox>
+    <groupbox>
+     <caption label="Colors" />
+     <htm:div>
+      <htm:p>howdy!</htm:p>
+     </htm:div>
+     <htm:br></htm:br>
+    </groupbox>
 
 =head1 METHODS AND SUBROUTINES
 
-=head2 template TEMPLATENAME => sub { 'Implementation' };
+=head2 Declaring templates
+
+=head3 template TEMPLATENAME => sub { 'Implementation' };
 
     template select_list => sub {
         my $self = shift;
@@ -306,99 +308,94 @@
             $codesub,
         );
     }
-
 }
 
-=head2 create_wrapper WRAPPERNAME => sub { 'Implementation' };
+=head3 private template TEMPLATENAME => sub { 'Implementation' };
 
-    create_wrapper basics => sub {
-        my $code = shift;
-        html {
-            head { title { 'Welcome' } };
-            body { $code->() }
+    private template select_list => sub {
+        my $self = shift;
+        select {
+            option { $_ } for @_;
         }
     };
 
-C<create_wrapper> declares a wrapper subroutine that can be called like a tag
-sub, but can optionally take arguments to be passed to the wrapper sub. For
-example, if you wanted to wrap all of the output of a template in the usual
-HTML headers and footers, you can do something like this:
+Declares that a template isn't available to be called directly from client
+code. The resulting template can instead only be called from the package in
+which it's created.
 
-    package MyApp::Templates;
-    use Template::Declare::Tags;
-    use base 'Template::Declare';
+=cut
 
-    BEGIN {
-        create_wrapper wrap => sub {
-            my $code = shift;
-            my %params = @_;
-            html {
-                head { title { outs "Hello, $params{user}!"} };
-                body {
-                    $code->();
-                    div { outs 'This is the end, my friend' };
-                };
-            }
-        };
-    }
+sub private (@) {
+    my $class   = shift;
+    my $subname = shift;
+    my $code    = shift;
+    Template::Declare::register_private_template( $class, $subname, $code );
+}
 
-    template inner => sub {
-        wrap {
-            h1 { outs "Hello, Jesse, s'up?" };
-        } user => 'Jesse';
-    };
+=head2 Showing templates
 
-Note how the C<wrap> wrapper function is available for calling after it has
-been declared in a C<BEGIN> block. Also note how you can pass arguments to the
-function after the closing brace (you don't need a comma there!).
+=head3 show [$template_name or $template_coderef], args
 
-The output from the "inner" template will look something like this:
+    show( main => { user => 'Bob' } );
 
- <html>
-  <head>
-   <title>Hello, Jesse!</title>
-  </head>
-  <body>
-   <h1>Hello, Jesse, s&#39;up?</h1>
-   <div>This is the end, my friend</div>
-  </body>
- </html>
+Displays templates. The first agument is the name of the template to be
+displayed. Any additional arguments will be passed directly to the template.
+
+C<show> can either be called with a template name or a package/object and a
+template. (It's both functional and OO.)
+
+If called from within a Template::Declare subclass, then private templates are
+accessible and visible. If called from something that isn't a
+Template::Declare, only public templates wil be visible.
+
+From the outside world, users can either call C<< Template::Declare->show() >>,
+C<< show() >> exported from Template::Declare::Tags or
+C<Template::Declare::Tags::show()> directly to render a publicly visible template.
+
+Private templates may only be called from within the C<Template::Declare>
+package.
 
 =cut
 
-sub create_wrapper ($$) {
-    my $wrapper_name   = shift;
-    my $coderef        = shift;
-    my $template_class = caller;
+sub show {
+    my $template = shift;
+
+    # if we're inside a template, we should show private templates
+    if ( caller->isa('Template::Declare') ) {
+        _show_template( $template, 1, \@_ );
+        return Template::Declare->buffer->data;
+    } else {
+        show_page( $template, @_);
+    }
 
-    # Shove the code ref into the calling class.
-    no strict 'refs';
-    *{"$template_class\::$wrapper_name"} = sub (&;@) { goto $coderef };
 }
 
-=head2 private template TEMPLATENAME => sub { 'Implementation' };
+=head3 show_page
 
-    private template select_list => sub {
-        my $self = shift;
-        select {
-            option { $_ } for @_;
-        }
-    };
+    show_page( main => { user => 'Bob' } );
 
-Declares that a template isn't available to be called directly from client
-code. The resulting template can instead only be called from the package in
-which it's created.
+Like C<show()>, but does not dispatch to private templates. It's used
+internally by C<show()> when when that method is called from outside a
+template class.
 
 =cut
 
-sub private (@) {
-    my $class   = shift;
-    my $subname = shift;
-    my $code    = shift;
-    Template::Declare::register_private_template( $class, $subname, $code );
+sub show_page {
+    my $template = shift;
+    my $args = \@_;
+
+    Template::Declare->buffer->push(
+        private => defined wantarray,
+        from => "T::D path $template",
+    );
+    _show_template( $template, 0, $args );
+    %ELEMENT_ID_CACHE = ();
+    return Template::Declare->buffer->pop;
 }
 
-=head2 attr HASH
+=head2 Attributes
+
+=head3 attr HASH
 
     attr { src => 'logo.png' };
 
@@ -413,14 +410,6 @@
        'This is a welcoming paragraph';
     }
 
-Attributes can also be specified by using C<is>, as in
-
-    p {
-       class is 'greeting text';
-       id    is 'welcome';
-       'This is a welcoming paragraph';
-    }
-
 =cut
 
 sub attr (&;@) {
@@ -434,36 +423,60 @@
     return @_;
 }
 
-=head2 xml_decl HASH
+=head3 ATTR is VALUE
 
-    xml_decl { 'xml', version => '1.0' };
+Attributes can also be specified by using C<is>, as in
 
-Emits an XML declaration. For example:
+    p {
+       class is 'greeting text';
+       id    is 'welcome';
+       'This is a welcoming paragraph';
+    }
 
-    xml_decl { 'xml', version => '1.0' };
-    xml_decl { 'xml-stylesheet',  href => "chrome://global/skin/", type => "text/css" };
+A few tricks work for 'is':
 
-Produces:
+    http_equiv is 'foo'; # => http-equiv="foo"
+    xml__lang is 'foo';  # => xml:lang="foo"
 
- <?xml version="1.0"?>
- <?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
+So double underscore replaced with colon and single underscore with dash.
 
 =cut
 
-sub xml_decl (&;$) {
-    my $code = shift;
-    my @rv   = $code->();
-    my $name = shift @rv;
-    outs_raw("<?$name");
-    while ( my ( $field, $val ) = splice( @rv, 0, 2 ) ) {
-        # only defined whle in a tag context
-        outs_raw(qq/ $field="$val"/);
+# 'is' is declared later, when needed, using 'local *is::AUTOLOAD = sub {};'
+
+=head3 with
+
+    with ( id => 'greeting', class => 'foo' ),
+        p { 'Hello, World wide web' };
+
+An alternative way to specify attributes for a tag, just for variation. The
+standard way to do the same as this example using C<attr> is:
+
+    p { attr { id => 'greeting', class => 'foo' }
+        'Hello, World wide web' };
+
+=cut
+
+sub with (@) {
+    %ATTRIBUTES = ();
+    while ( my ( $key, $val ) = splice( @_, 0, 2 ) ) {
+        no warnings 'uninitialized';
+        $ATTRIBUTES{$key} = $val;
+
+        if ( lc($key) eq 'id' ) {
+            if ( $ELEMENT_ID_CACHE{$val}++ ) {
+                warn
+                    "HTML appears to contain illegal duplicate element id: $val";
+            }
+        }
+
     }
-    outs_raw("?>\n");
-    return @_;
+    wantarray ? () : '';
 }
 
-=head2 outs STUFF
+=head2 Displaying text and raw data
+
+=head3 outs STUFF
 
     p { outs 'Grettings & welcome pyoonie hyoomon.' }
 
@@ -473,7 +486,7 @@
 
     p { outs 'hello'; em { 'world' } }
 
-=head2 outs_raw STUFF
+=head3 outs_raw STUFF
 
    p { outs_raw "That's what <em>I'm</em> talking about!' }
 
@@ -485,40 +498,9 @@
 sub outs     { _outs( 0, @_ ); }
 sub outs_raw { _outs( 1, @_ ); }
 
-sub _outs {
-    my $raw     = shift;
-    my @phrases = (@_);
-
-    Template::Declare->buffer->push(
-        private => (defined wantarray and not wantarray), from => "T::D outs"
-    );
+=head2 Installing tags and wrapping stuff
 
-    foreach my $item ( grep {defined} @phrases ) {
-        my $returned = ref($item) eq 'CODE'
-            ? $item->()
-            : $raw
-                ? $item
-                : _postprocess($item);
-        Template::Declare->buffer->append( $returned );
-    }
-    return Template::Declare->buffer->pop;
-}
-
-=begin comment
-
-=head2 get_current_attr
-
-Deprecated.
-
-=end comment
-
-=cut
-
-sub get_current_attr ($) {
-    $ATTRIBUTES{ $_[0] };
-}
-
-=head2 install_tag TAGNAME, TAGSET
+=head3 install_tag TAGNAME, TAGSET
 
     install_tag video => 'Template::Declare::TagSet::HTML';
 
@@ -583,39 +565,9 @@
     );
 }
 
-=head2 with
-
-    with ( id => 'greeting', class => 'foo' ),
-        p { 'Hello, World wide web' };
-
-An alternative way to specify attributes for a tag, just for variation. The
-standard way to do the same as this example using C<attr> is:
-
-    p { attr { id => 'greeting', class => 'foo' }
-        'Hello, World wide web' };
-
-=cut
-
-sub with (@) {
-    %ATTRIBUTES = ();
-    while ( my ( $key, $val ) = splice( @_, 0, 2 ) ) {
-        no warnings 'uninitialized';
-        $ATTRIBUTES{$key} = $val;
-
-        if ( lc($key) eq 'id' ) {
-            if ( $ELEMENT_ID_CACHE{$val}++ ) {
-                warn
-                    "HTML appears to contain illegal duplicate element id: $val";
-            }
-        }
-
-    }
-    wantarray ? () : '';
-}
-
-=head2 smart_tag_wrapper
+=head3 smart_tag_wrapper
 
-    # create a tag that has access to the arguments set with with.
+    # create a tag that has access to the arguments set with L</with>.
     sub sample_smart_tag (&) {
         my $code = shift;
 
@@ -633,8 +585,8 @@
 
 The output would be
 
- keys: baz, foo
- Hello, World!
+    keys: baz, foo
+    Hello, World!
 
 The smart tag wrapper allows you to create code that has access to the
 attribute arguments specified via C<with>. It passes those arguments in to the
@@ -664,6 +616,147 @@
     return '';
 }
 
+=head3 create_wrapper WRAPPERNAME => sub { 'Implementation' };
+
+    create_wrapper basics => sub {
+        my $code = shift;
+        html {
+            head { title { 'Welcome' } };
+            body { $code->() }
+        }
+    };
+
+C<create_wrapper> declares a wrapper subroutine that can be called like a tag
+sub, but can optionally take arguments to be passed to the wrapper sub. For
+example, if you wanted to wrap all of the output of a template in the usual
+HTML headers and footers, you can do something like this:
+
+    package MyApp::Templates;
+    use Template::Declare::Tags;
+    use base 'Template::Declare';
+
+    BEGIN {
+        create_wrapper wrap => sub {
+            my $code = shift;
+            my %params = @_;
+            html {
+                head { title { outs "Hello, $params{user}!"} };
+                body {
+                    $code->();
+                    div { outs 'This is the end, my friend' };
+                };
+            }
+        };
+    }
+
+    template inner => sub {
+        wrap {
+            h1 { outs "Hello, Jesse, s'up?" };
+        } user => 'Jesse';
+    };
+
+Note how the C<wrap> wrapper function is available for calling after it has
+been declared in a C<BEGIN> block. Also note how you can pass arguments to the
+function after the closing brace (you don't need a comma there!).
+
+The output from the "inner" template will look something like this:
+
+    <html>
+     <head>
+      <title>Hello, Jesse!</title>
+     </head>
+     <body>
+      <h1>Hello, Jesse, s&#39;up?</h1>
+      <div>This is the end, my friend</div>
+     </body>
+    </html>
+
+=cut
+
+sub create_wrapper ($$) {
+    my $wrapper_name   = shift;
+    my $coderef        = shift;
+    my $template_class = caller;
+
+    # Shove the code ref into the calling class.
+    no strict 'refs';
+    *{"$template_class\::$wrapper_name"} = sub (&;@) { goto $coderef };
+}
+
+=head2 Helpers
+
+=head3 xml_decl HASH
+
+    xml_decl { 'xml', version => '1.0' };
+
+Emits an XML declaration. For example:
+
+    xml_decl { 'xml', version => '1.0' };
+    xml_decl { 'xml-stylesheet',  href => "chrome://global/skin/", type => "text/css" };
+
+Produces:
+
+    <?xml version="1.0"?>
+    <?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
+
+=cut
+
+sub xml_decl (&;$) {
+    my $code = shift;
+    my @rv   = $code->();
+    my $name = shift @rv;
+    outs_raw("<?$name");
+    while ( my ( $field, $val ) = splice( @rv, 0, 2 ) ) {
+        outs_raw(qq/ $field="$val"/);
+    }
+    outs_raw("?>\n");
+    return @_;
+}
+
+=head3 current_template
+
+    my $path = current_template();
+
+Returns the absolute path of the current template
+
+=cut
+
+sub current_template {
+    return $TEMPLATE_STACK[-1] || '';
+}
+
+=head3 under
+
+C<under> is a helper function providing semantic sugar for the C<mix> method
+of L<Template::Declare|Template::Declare/"mix">.
+
+=cut
+
+sub under ($) { return shift }
+
+=head3 setting
+
+C<setting> is a helper function providing semantic sugar for the C<mix> method
+of L<Template::Declare|Template::Declare/"mix">.
+
+=cut
+
+sub setting ($) { return shift }
+
+=begin comment
+
+=head2 get_current_attr
+
+Deprecated.
+
+=end comment
+
+=cut
+
+sub get_current_attr ($) {
+    $ATTRIBUTES{ $_[0] };
+}
+
 sub _tag {
     my $tagset    = shift;
     my $tag       = shift;
@@ -733,65 +826,6 @@
         : '';
 }
 
-=head2 show [$template_name or $template_coderef], args
-
-    show( main => { user => 'Bob' } );
-
-Displays templates. The first agument is the name of the template to be
-displayed. Any additional arguments will be passed directly to the template.
-
-C<show> can either be called with a template name or a package/object and a
-template. (It's both functional and OO.)
-
-If called from within a Template::Declare subclass, then private templates are
-accessible and visible. If called from something that isn't a
-Template::Declare, only public templates wil be visible.
-
-From the outside world, users can either call C<< Template::Declare->show() >>,
-C<< show() >> exported from Template::Declare::Tags or
-C<Template::Declare::Tags::show()> directly to render a publicly visible template.
-
-Private templates may only be called from within the C<Template::Declare>
-package.
-
-=cut
-
-sub show {
-    my $template = shift;
-
-    # if we're inside a template, we should show private templates
-    if ( caller->isa('Template::Declare') ) {
-        _show_template( $template, 1, \@_ );
-        return Template::Declare->buffer->data;
-    } else {
-        show_page( $template, @_);
-    }
-
-}
-
-=head2 show_page
-
-    show_page( main => { user => 'Bob' } );
-
-Like C<show()>, but does not dispatch to private templates. It's used
-internally by C<show()> when when that method is called from outside a
-template class.
-
-=cut
-
-sub show_page {
-    my $template = shift;
-    my $args = \@_;
-
-    Template::Declare->buffer->push(
-        private => defined wantarray,
-        from => "T::D path $template",
-    );
-    _show_template( $template, 0, $args );
-    %ELEMENT_ID_CACHE = ();
-    return Template::Declare->buffer->pop;
-}
-
 sub _resolve_template_path {
     my $template = shift;
 
@@ -816,19 +850,6 @@
     return join '/', @parts;
 }
 
-=head2 current_template
-
-  my $path = current_template();
-
-Returns the absolute path of the current template
-
-=cut
-
-sub current_template {
-    return $TEMPLATE_STACK[-1] || '';
-}
-
-
 sub _show_template {
     my $template        = shift;
     my $inside_template = shift;
@@ -864,6 +885,25 @@
     return;
 }
 
+sub _outs {
+    my $raw     = shift;
+    my @phrases = (@_);
+
+    Template::Declare->buffer->push(
+        private => (defined wantarray and not wantarray), from => "T::D outs"
+    );
+
+    foreach my $item ( grep {defined} @phrases ) {
+        my $returned = ref($item) eq 'CODE'
+            ? $item->()
+            : $raw
+                ? $item
+                : _postprocess($item);
+        Template::Declare->buffer->append( $returned );
+    }
+    return Template::Declare->buffer->pop;
+}
+
 sub _postprocess {
     my $val = shift;
     my $skip_postprocess = shift;
@@ -888,24 +928,6 @@
     return $val;
 }
 
-=head2 under
-
-C<under> is a helper function providing semantic sugar for the C<mix> method
-of L<Template::Declare|Template::Declare/"mix">.
-
-=cut
-
-sub under ($) { return shift }
-
-=head2 setting
-
-C<setting> is a helper function providing semantic sugar for the C<mix> method
-of L<Template::Declare|Template::Declare/"mix">.
-
-=cut
-
-sub setting ($) { return shift }
-
 =begin comment
 
 =head2 append_attr
@@ -957,11 +979,11 @@
 
 It generates
 
- <body>
-  <pre>
- <script src="foo.js"></script>
-  </pre>
- </body>
+    <body>
+     <pre>
+    <script src="foo.js"></script>
+     </pre>
+    </body>
 
 Note that now the C<script> tag has I<no> indentation and we've got what we
 want. ;)


More information about the Jifty-commit mailing list