From 6d3b76546c92f15aadc2a9c4b7568411e49ccfbe Mon Sep 17 00:00:00 2001 From: Jesse Luehrs Date: Mon, 8 Oct 2012 13:33:45 -0500 Subject: implement hash parameters for block helpers --- lib/Text/Handlebars.pm | 7 ++++++- lib/Text/Handlebars/Compiler.pm | 31 +++++++++++++++++++++++++++++++ lib/Text/Xslate/Syntax/Handlebars.pm | 18 +++++++++++++++++- t/block-helpers.t | 10 +++++----- 4 files changed, 59 insertions(+), 7 deletions(-) diff --git a/lib/Text/Handlebars.pm b/lib/Text/Handlebars.pm index 4a66fe6..f8d1692 100644 --- a/lib/Text/Handlebars.pm +++ b/lib/Text/Handlebars.pm @@ -55,6 +55,10 @@ sub default_functions { my ($length) = @_; return [(undef) x $length]; }, + '(make_hash)' => sub { + my (%hash) = @_; + return \%hash; + }, '(is_code)' => sub { my ($val) = @_; return ref($val) && ref($val) eq 'CODE'; @@ -122,7 +126,7 @@ sub _register_builtin_methods { return 0; }; $funcs->{'(make_block_helper)'} = sub { - my ($code, $raw_text, $else_raw_text) = @_; + my ($code, $raw_text, $else_raw_text, $hash) = @_; my $options = {}; $options->{fn} = sub { @@ -133,6 +137,7 @@ sub _register_builtin_methods { my ($new_vars) = @_; return $weakself->render_string($else_raw_text, $new_vars); }; + $options->{hash} = $hash; return sub { $code->(@_, $options); }; }; diff --git a/lib/Text/Handlebars/Compiler.pm b/lib/Text/Handlebars/Compiler.pm index 8c89b06..a358d2e 100644 --- a/lib/Text/Handlebars/Compiler.pm +++ b/lib/Text/Handlebars/Compiler.pm @@ -79,6 +79,37 @@ sub _generate_include { return $self->SUPER::_generate_include($node); } +sub _generate_call { + my $self = shift; + my ($node) = @_; + + if ($node->is_helper) { + my @args; + my @hash; + for my $arg (@{ $node->second }) { + if ($arg->arity eq 'pair') { + push @hash, $arg->first, $arg->second; + } + else { + push @args, $arg; + } + } + + my $parser = $self->parser; + + my $make_hash = $parser->symbol('(name)')->clone( + arity => 'name', + id => '(make_hash)', + line => $node->line, + ); + + push @{ $node->first->second }, $parser->call($make_hash, @hash); + $node->second(\@args); + } + + return $self->SUPER::_generate_call($node); +} + __PACKAGE__->meta->make_immutable; no Any::Moose; diff --git a/lib/Text/Xslate/Syntax/Handlebars.pm b/lib/Text/Xslate/Syntax/Handlebars.pm index 3edab0a..7d28824 100644 --- a/lib/Text/Xslate/Syntax/Handlebars.pm +++ b/lib/Text/Xslate/Syntax/Handlebars.pm @@ -16,7 +16,7 @@ my $nl = qr/\x0d?\x0a/; my $bracket_string = qr/\[ [^\]]* \]/xms; my $STRING = qr/(?: $Text::Xslate::Util::STRING | $bracket_string )/xms; -my $single_char = '[.#^/>&;]'; +my $single_char = '[.#^/>&;=]'; my $OPERATOR_TOKEN = sprintf( "(?:%s|$single_char)", join('|', map{ quotemeta } qw(..)) @@ -260,6 +260,8 @@ sub init_symbols { $self->symbol('&')->set_nud($self->can('nud_mark_raw')); $self->symbol('..')->set_nud($self->can('nud_uplevel')); + + $self->infix('=', 20, $self->can('led_equals')); } # copied from Text::Xslate::Parser, but using different definitions of @@ -417,6 +419,7 @@ sub std_block { ? $block{else}{raw_text}->clone : $self->literal('')), ), + is_helper => 1, ); return $self->print_raw($name); } @@ -515,6 +518,19 @@ sub std_partial { ); } +sub led_equals { + my $self = shift; + my ($symbol, $left) = @_; + + my $right = $self->expression($symbol->lbp); + + return $symbol->clone( + arity => 'pair', + first => $left->clone(arity => 'literal'), + second => $right, + ); +} + sub undefined_name { my $self = shift; my ($name) = @_; diff --git a/t/block-helpers.t b/t/block-helpers.t index 4b68d1e..3cd6cb8 100644 --- a/t/block-helpers.t +++ b/t/block-helpers.t @@ -287,26 +287,25 @@ RENDERED "if/else helper (false)" ); -{ local $TODO = "unimplemented"; local $SIG{__WARN__} = sub { }; render_ok( { helpers => { list => sub { my ($context, $items, $options) = @_; - my $attrs = join ' ', map { $_ => $options->{hash}{$_} } + my $attrs = join ' ', map { "$_=\"$options->{hash}{$_}\"" } sort keys %{ $options->{hash} }; return ""; + . "\n"; }, }, }, <<'TEMPLATE', -{{list nav id="nav-bar" class="top"}} +{{#list nav id="nav-bar" class="top"}} {{title}} {{/list}} TEMPLATE @@ -325,12 +324,13 @@ TEMPLATE <<'RENDERED', RENDERED "helper arguments" ); +{ local $TODO = "unimplemented"; local $SIG{__WARN__} = sub { }; # XXX this is almost certainly not what the api should be like, but i don't # understand the purpose for this feature well enough to come up with anything # more reasonable. feedback welcome! -- cgit v1.2.3