summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJesse Luehrs <doy@tozt.net>2012-10-02 12:16:42 -0500
committerJesse Luehrs <doy@tozt.net>2012-10-02 12:16:42 -0500
commit0722287d6c04831cdb40b64bae2ca55c24c2f555 (patch)
tree751d92348e4635bf845e1edc1df027fa32b3c4c2
parent2986df9f1eef1112b2221a52bf0a025611ec4e09 (diff)
downloadtext-handlebars-0722287d6c04831cdb40b64bae2ca55c24c2f555.tar.gz
text-handlebars-0722287d6c04831cdb40b64bae2ca55c24c2f555.zip
handle inverted sections
-rw-r--r--lib/Text/Handlebars.pm4
-rw-r--r--lib/Text/Handlebars/Compiler.pm10
-rw-r--r--lib/Text/Xslate/Syntax/Handlebars.pm88
3 files changed, 70 insertions, 32 deletions
diff --git a/lib/Text/Handlebars.pm b/lib/Text/Handlebars.pm
index bad8c64..aa239a0 100644
--- a/lib/Text/Handlebars.pm
+++ b/lib/Text/Handlebars.pm
@@ -12,6 +12,10 @@ sub default_functions {
my ($val) = @_;
return ref($val) && ref($val) eq 'ARRAY';
},
+ '(is_empty_array)' => sub {
+ my ($val) = @_;
+ return @$val == 0;
+ },
'(make_array)' => sub {
my ($length) = @_;
return [(undef) x $length];
diff --git a/lib/Text/Handlebars/Compiler.pm b/lib/Text/Handlebars/Compiler.pm
index 2150bba..5f112fc 100644
--- a/lib/Text/Handlebars/Compiler.pm
+++ b/lib/Text/Handlebars/Compiler.pm
@@ -11,10 +11,12 @@ sub _generate_block {
my $self = shift;
my ($node) = @_;
- return (
- $self->_localize_vars($node->first),
- (map { $self->compile_ast($_) } @{ $node->second }),
- );
+ my @compiled = map { $self->compile_ast($_) } @{ $node->second };
+
+ unshift @compiled, $self->_localize_vars($node->first)
+ if $node->first;
+
+ return @compiled;
}
if (0) {
diff --git a/lib/Text/Xslate/Syntax/Handlebars.pm b/lib/Text/Xslate/Syntax/Handlebars.pm
index 4741d7f..ab46d52 100644
--- a/lib/Text/Xslate/Syntax/Handlebars.pm
+++ b/lib/Text/Xslate/Syntax/Handlebars.pm
@@ -111,7 +111,7 @@ sub preprocess {
elsif ($type eq 'code') {
$code .= qq{$content;\n};
$suppress_newline = 1
- if $content =~ m{^[#/]};
+ if $content =~ m{^[#^/]};
}
elsif ($type eq 'raw_code') {
$code .= qq{mark_raw $content;\n};
@@ -144,6 +144,7 @@ sub init_symbols {
$self->infix('/', 256, $self->can('led_dot'));
$self->symbol('#')->set_std($self->can('std_block'));
+ $self->symbol('^')->set_std($self->can('std_block'));
$self->prefix('/', 0)->is_block_end(1);
}
@@ -186,6 +187,8 @@ sub std_block {
my $self = shift;
my ($symbol) = @_;
+ my $inverted = $symbol->id eq '^';
+
if ($self->token->arity ne 'name') {
$self->_unexpected("block name", $self->token);
}
@@ -206,38 +209,67 @@ sub std_block {
$self->advance;
- my $iterations = $self->make_ternary(
- $self->call('(is_array)', $name->clone),
- $name->clone,
- $self->make_ternary(
- $name->clone,
- $self->call(
- '(make_array)',
- $self->symbol('(literal)')->clone(id => 1),
- ),
- $self->call(
- '(make_array)',
- $self->symbol('(literal)')->clone(id => 0),
- ),
- ),
- );
+ my $iterations = $inverted
+ ? ($self->make_ternary(
+ $self->call('(is_array)', $name->clone),
+ $self->make_ternary(
+ $self->call('(is_empty_array)', $name->clone),
+ $self->call(
+ '(make_array)',
+ $self->symbol('(literal)')->clone(id => 1),
+ ),
+ $self->call(
+ '(make_array)',
+ $self->symbol('(literal)')->clone(id => 0),
+ ),
+ ),
+ $self->make_ternary(
+ $name->clone,
+ $self->call(
+ '(make_array)',
+ $self->symbol('(literal)')->clone(id => 0),
+ ),
+ $self->call(
+ '(make_array)',
+ $self->symbol('(literal)')->clone(id => 1),
+ ),
+ ),
+ ))
+ : ($self->make_ternary(
+ $self->call('(is_array)', $name->clone),
+ $name->clone,
+ $self->make_ternary(
+ $name->clone,
+ $self->call(
+ '(make_array)',
+ $self->symbol('(literal)')->clone(id => 1),
+ ),
+ $self->call(
+ '(make_array)',
+ $self->symbol('(literal)')->clone(id => 0),
+ ),
+ ),
+ ));
my $loop_var = $self->symbol('(variable)')->clone(id => '(block)');
my $body_block = [
$symbol->clone(
- arity => 'block',
- first => [
- $self->call(
- '(new_vars_for)',
- $self->symbol('(vars)')->clone(arity => 'vars'),
- $name->clone,
- $self->symbol('(iterator)')->clone(
- id => '$~(block)',
- first => $loop_var,
- ),
- ),
- ],
+ arity => 'block',
+ first => ($inverted
+ ? (undef)
+ : ([
+ $self->call(
+ '(new_vars_for)',
+ $self->symbol('(vars)')->clone(arity => 'vars'),
+ $name->clone,
+ $self->symbol('(iterator)')->clone(
+ id => '$~(block)',
+ first => $loop_var,
+ ),
+ ),
+ ])
+ ),
second => $body,
),
];