use strict;
use Carp ;
+use Data::Dumper ;
use Scalar::Util qw( reftype ) ;
use File::Slurp ;
-use Data::Dumper ;
our $VERSION = '0.03';
my $code_body = $self->_compile_chunk( '', "${$tmpl_ref}", "\t" ) ;
my $source = <<CODE ;
-
no warnings ;
sub {
my( \$data ) = \@_ ;
- my \$out = $code_body ;
+ my \$out ;
+$code_body
return \\\$out ;
}
CODE
$self->{source_cache}{$template_name} = $source ;
}
-sub get_source {
+sub _compile_chunk {
- my( $self, $template_name ) = @_ ;
+ my( $self, $chunk_name, $template, $indent ) = @_ ;
- return $self->{source_cache}{$template_name} ;
-}
+ return '' unless length $template ;
+# generate a lookup in data for this chunk name (unless it is the top
+# level). this descends down the data tree during rendering
-sub _compile_chunk {
+ my $data_init = $chunk_name ? "\$data->{$chunk_name}" : '$data' ;
- my( $self, $chunk_name, $template, $indent ) = @_ ;
+ my $code = <<CODE ;
+${indent}my \@data = $data_init ;
+${indent}while( defined( my \$data = shift \@data ) ) {
- return '' unless length $template ;
+${indent} if ( ref \$data eq 'ARRAY' ) {
+${indent} push \@data, \@{\$data} ;
+${indent} next ;
+${indent} }
- my @parts ;
+CODE
+
+ $indent .= "\t" ;
# loop all nested chunks and the text separating them
while( $template =~ m{$self->{chunk_re}} ) {
-# grab the pre-match text and compile its scalars and save all of its parts
+# get the pre-match text and compile its scalars and text. append to the code
- push @parts, $self->_compile_scalars(
- substr( $template, 0, $-[0] ) ) ;
+ $code .= $self->_compile_scalars(
+ substr( $template, 0, $-[0] ), $indent ) ;
# print "OFF: $-[0] $+[0]\n" ;
# print "PRE: [", substr( $template, 0, $-[0] ), "]\n\n" ;
# print "TRUNC: [", substr( $template, 0, $+[0] ), "]\n\n" ;
# print "LEFT: [$template]\n\n" ;
-# compile the nested chunk and save its parts
+# compile the nested chunk and append to the code
- push @parts, $self->_compile_chunk( $1, $2, "$indent\t\t" ) ;
+ $code .= $self->_compile_chunk( $1, $2, $indent ) ;
# chop off the pre-match and the chunk
substr( $template, 0, $+[0], '' ) ;
-
-# print "LEFT2: [$template]\n\n" ;
-# print Dumper \@parts ;
-
}
-# compile trailing text for scalars and save all of its parts
-
- push @parts, $self->_compile_scalars( $template ) ;
+# compile trailing text for scalars and append to the code
-# generate the code for this chunk
-
-# start it with a do{} block open
-
- my $code = <<CODE ;
-do {
-CODE
-
- $indent .= "\t" ;
-
-# generate a lookup in data for this chunk name (unless it is the top
-# level). this descends down the data tree during rendering
-
- $code .= <<CODE if $chunk_name ;
-${indent}my \$data = \$data->{$chunk_name} ;
-CODE
-
-# add the loop code to handle a scalar or an array
-
- $code .= <<CODE ;
-${indent}my \$out ;
-
-${indent}my \@data = \$data ;
-${indent}while( defined( my \$data = shift \@data ) ) {
-
-${indent} if ( ref \$data eq 'ARRAY' ) {
-${indent} push \@data, \@{\$data} ;
-${indent} next ;
-${indent} }
-
- ${indent}\$out .= ref \$data ne 'HASH' ? \$data :
-CODE
-
-#${indent}foreach my \$data ( ref \$data eq 'ARRAY' ? \@{\$data} : \$data ) {
-
-
-
- $indent .= "\t" ;
-
-# now generate the code to output all the parts of this chunk. they
-# are all concatentated by the . operator
-
- $code .= $indent . join( "\n$indent.\n$indent", @parts ) ;
+ $code .= $self->_compile_scalars( $template, $indent ) ;
chop $indent ;
-# now we end the .= statement, the loop and the do block for this chunk
+# now we end the loop for this chunk
$code .= <<CODE ;
- ;
$indent}
-$indent\$out ;
CODE
- chop $indent ;
- $code .= "$indent}" ;
-
return $code ;
}
sub _compile_scalars {
- my( $self, $template ) = @_ ;
+ my( $self, $template, $indent ) = @_ ;
# if the template is empty return no parts
- return unless length $template ;
+ return '' unless length $template ;
my @parts ;
while( $template =~ m{$self->{scalar_re}}g ) {
-# keep the text before the scalar markup and the code to access the scalar
+# get the pre-match text before the scalar markup and generate code to
+# access the scalar
push( @parts,
dump_text( substr( $template, 0, $-[0] ) ),
push @parts, dump_text( $template ) ;
- return @parts ;
+ my $parts_code = join( "\n$indent.\n$indent", @parts ) ;
+
+ return <<CODE ;
+
+${indent}\$out .= ref \$data ne 'HASH' ? \$data :
+${indent}$parts_code ;
+
+CODE
}
-use Data::Dumper ;
sub dump_text {
return $dumped ;
}
+sub get_source {
+
+ my( $self, $template_name ) = @_ ;
+
+ return $self->{source_cache}{$template_name} ;
+}
+
sub render {
my( $self, $template_name, $data ) = @_ ;