From 1a010552eeb2a965c92fab007c45f8e59ac60b02 Mon Sep 17 00:00:00 2001 From: Jesse Luehrs Date: Fri, 5 Oct 2012 10:39:27 -0500 Subject: implement else blocks --- lib/Text/Handlebars.pm | 15 ++++++---- lib/Text/Xslate/Syntax/Handlebars.pm | 57 +++++++++++++++++++++++++++++++----- t/block-helper-builtins.t | 2 -- t/block-helpers.t | 2 +- 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',
@@ -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 => { -- cgit v1.2.3-54-g00ecf