summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJesse Luehrs <doy@tozt.net>2012-10-05 10:39:27 -0500
committerJesse Luehrs <doy@tozt.net>2012-10-05 10:39:27 -0500
commit1a010552eeb2a965c92fab007c45f8e59ac60b02 (patch)
tree1c384604ddc6a5101302edce2ced26e66bafc8d4
parentd94b450ad15be78a1ead0b614b853e659370119b (diff)
downloadtext-handlebars-1a010552eeb2a965c92fab007c45f8e59ac60b02.tar.gz
text-handlebars-1a010552eeb2a965c92fab007c45f8e59ac60b02.zip
implement else blocks
-rw-r--r--lib/Text/Handlebars.pm15
-rw-r--r--lib/Text/Xslate/Syntax/Handlebars.pm57
-rw-r--r--t/block-helper-builtins.t2
-rw-r--r--t/block-helpers.t2
4 files changed, 60 insertions, 16 deletions
diff --git a/lib/Text/Handlebars.pm b/lib/Text/Handlebars.pm
index c1afc32..cf2a8f1 100644
--- a/lib/Text/Handlebars.pm
+++ b/lib/Text/Handlebars.pm
@@ -85,14 +85,14 @@ sub options {
if ($conditional) {
return $options->{fn}->($context);
}
- return '';
+ return $options->{inverse} ? $options->{inverse}->($context) : '';
},
unless => sub {
my ($context, $conditional, $options) = @_;
unless ($conditional) {
return $options->{fn}->($context);
}
- return '';
+ return $options->{inverse} ? $options->{inverse}->($context) : '';
},
},
@@ -119,14 +119,19 @@ sub _register_builtin_methods {
return 0;
};
$funcs->{'(run_block_helper)'} = sub {
- my ($code, $raw_text, $vars, @args) = @_;
+ my ($code, $raw_text, $else_raw_text, $vars, @args) = @_;
- my $recurse = sub {
+ my $options = {};
+ $options->{fn} = sub {
my ($new_vars) = @_;
return $weakself->render_string($raw_text, $new_vars);
};
+ $options->{inverse} = sub {
+ my ($new_vars) = @_;
+ return $weakself->render_string($else_raw_text, $new_vars);
+ };
- return $code->($vars, @args, { fn => $recurse });
+ return $code->($vars, @args, $options);
};
}
diff --git a/lib/Text/Xslate/Syntax/Handlebars.pm b/lib/Text/Xslate/Syntax/Handlebars.pm
index c575702..4b88f4f 100644
--- a/lib/Text/Xslate/Syntax/Handlebars.pm
+++ b/lib/Text/Xslate/Syntax/Handlebars.pm
@@ -65,7 +65,7 @@ sub split_tags {
my @extra;
- my $autochomp = $code =~ m{^[!#^/=>]};
+ my $autochomp = $code =~ m{^[!#^/=>]} || $code eq 'else';
if ($code =~ s/^=\s*([^\s]+)\s+([^\s]+)\s*=$//) {
($tag_start, $tag_end) = ($1, $2);
@@ -89,7 +89,7 @@ sub split_tags {
$standalone = 0;
}
- if ($code =~ m{^/}) {
+ if ($code =~ m{^/} || $code eq 'else') {
push @extra, pop @raw_text;
push @extra, pop @delimiters;
if (@raw_text) {
@@ -99,7 +99,7 @@ sub split_tags {
if (@raw_text) {
$raw_text[-1] .= $tag_start . $code . $tag_end;
}
- if ($code =~ m{^[#^]}) {
+ if ($code =~ m{^[#^]} || $code eq 'else') {
push @raw_text, '';
push @delimiters, [$tag_start, $tag_end];
}
@@ -187,6 +187,17 @@ sub preprocess {
. '"';
$code .= qq{/$extra $content;\n};
}
+ elsif ($content eq 'else') {
+ # XXX fix duplication
+ $chunk->[2] =~ s/(["\\])/\\$1/g;
+ $chunk->[3][0] =~ s/(["\\])/\\$1/g;
+ $chunk->[3][1] =~ s/(["\\])/\\$1/g;
+
+ $extra = '"'
+ . join('" "', $chunk->[2], @{ $chunk->[3] })
+ . '"';
+ $code .= qq{$content $extra;\n};
+ }
else {
$code .= qq{$content;\n};
}
@@ -224,6 +235,7 @@ sub init_symbols {
$self->symbol('#')->set_std($self->can('std_block'));
$self->symbol('^')->set_std($self->can('std_block'));
$self->prefix('/', 0)->is_block_end(1);
+ $self->symbol('else')->is_block_end(1);
$self->symbol('>')->set_std($self->can('std_partial'));
@@ -368,15 +380,31 @@ sub std_block {
$self->advance(';');
- my $body = $self->statements;
+ my %block;
+ my $context = 'if';
+ $block{$context}{body} = $self->statements;
+
+ if ($self->token->id eq 'else') {
+ $self->advance;
+
+ $block{$context}{raw_text} = $self->token;
+ $self->advance;
+ $block{$context}{open_tag} = $self->token;
+ $self->advance;
+ $block{$context}{close_tag} = $self->token;
+ $self->advance;
+
+ $context = 'else';
+ $block{$context}{body} = $self->statements;
+ }
$self->advance('/');
- my $raw_text = $self->token;
+ $block{$context}{raw_text} = $self->token;
$self->advance;
- my $open_tag = $self->token;
+ $block{$context}{open_tag} = $self->token;
$self->advance;
- my $close_tag = $self->token;
+ $block{$context}{close_tag} = $self->token;
$self->advance;
my $closing_name = $self->expression(0);
@@ -400,13 +428,26 @@ sub std_block {
$self->call(
'(run_block_helper)',
$self->symbol($name->first->id)->clone,
- $raw_text->clone,
+ $block{if}{raw_text}->clone,
+ ($block{else}
+ ? $block{else}{raw_text}->clone
+ : $self->symbol('(literal)')->clone(id => '')),
$self->vars,
@{ $name->second },
),
);
}
+ if ($block{else}) {
+ $self->_error("else block unsupported except with a block helper, "
+ . "and $name_string is not a block helper");
+ }
+
+ my $body = $block{if}{body};
+ my $raw_text = $block{if}{raw_text};
+ my $open_tag = $block{if}{open_tag};
+ my $close_tag = $block{if}{close_tag};
+
my $iterations = $inverted
? ($self->make_ternary(
$self->call('(is_array)', $name->clone),
diff --git a/t/block-helper-builtins.t b/t/block-helper-builtins.t
index 9540b27..fe1763b 100644
--- a/t/block-helper-builtins.t
+++ b/t/block-helper-builtins.t
@@ -94,7 +94,6 @@ RENDERED
"if helper (true)"
);
-{ local $TODO = "unimplemented";
render_ok(
<<'TEMPLATE',
<div class="entry">
@@ -136,7 +135,6 @@ TEMPLATE
RENDERED
"if/else helper (true)"
);
-}
render_ok(
<<'TEMPLATE',
diff --git a/t/block-helpers.t b/t/block-helpers.t
index 50f3fe0..961b2dc 100644
--- a/t/block-helpers.t
+++ b/t/block-helpers.t
@@ -227,7 +227,6 @@ RENDERED
"if helper (false)"
);
-{ local $TODO = "unimplemented"; local $SIG{__WARN__} = sub { };
render_ok(
{
function => {
@@ -288,6 +287,7 @@ RENDERED
"if/else helper (false)"
);
+{ local $TODO = "unimplemented"; local $SIG{__WARN__} = sub { };
render_ok(
{
function => {