From b6b1bd1936ea207c74ecf0993bd3b7c55c71ec57 Mon Sep 17 00:00:00 2001 From: Jesse Luehrs Date: Wed, 3 Oct 2012 15:05:25 -0500 Subject: make basic lambdas work (not block lambdas yet) --- lib/Text/Handlebars.pm | 15 +++++++++++++++ lib/Text/Xslate/Syntax/Handlebars.pm | 22 ++++++++++++++++++++-- t/mustache-spec.t | 25 +++++++++++++++++++++++-- 3 files changed, 58 insertions(+), 4 deletions(-) diff --git a/lib/Text/Handlebars.pm b/lib/Text/Handlebars.pm index 30a769c..fa9e32c 100644 --- a/lib/Text/Handlebars.pm +++ b/lib/Text/Handlebars.pm @@ -22,6 +22,10 @@ sub default_functions { my ($length) = @_; return [(undef) x $length]; }, + '(is_code)' => sub { + my ($val) = @_; + return ref($val) && ref($val) eq 'CODE'; + }, '(new_vars_for)' => sub { my ($vars, $value, $i) = @_; $i = 0 unless defined $i; # XXX @@ -62,4 +66,15 @@ sub options { return $options; } +sub _register_builtin_methods { + my $self = shift; + my ($funcs) = @_; + + weaken(my $weakself = $self); + $funcs->{'(run_code)'} = sub { + my ($code, $vars) = @_; + return $self->render_string($code->(), $vars); + }; +} + 1; diff --git a/lib/Text/Xslate/Syntax/Handlebars.pm b/lib/Text/Xslate/Syntax/Handlebars.pm index d8f2f9a..70e6506 100644 --- a/lib/Text/Xslate/Syntax/Handlebars.pm +++ b/lib/Text/Xslate/Syntax/Handlebars.pm @@ -181,6 +181,23 @@ sub nud_name { } } +sub nud_variable { + my $self = shift; + my ($symbol) = @_; + + my $var = $self->SUPER::nud_variable(@_); + + return $self->make_ternary( + $self->call('(is_code)', $var->clone), + $self->call( + '(run_code)', + $var->clone, + $self->symbol('(vars)')->clone(arity => 'vars'), + ), + $var, + ); +} + sub led_dot { my $self = shift; my ($symbol, $left) = @_; @@ -206,7 +223,8 @@ sub std_block { my $inverted = $symbol->id eq '^'; my $name = $self->expression(0); - if ($name->arity ne 'variable' && $name->arity ne 'field') { + # variable lookups are parsed into a ternary expression, hence arity 'if' + if ($name->arity ne 'if' && $name->arity ne 'field') { $self->_unexpected("opening block name", $self->token); } $self->advance(';'); @@ -216,7 +234,7 @@ sub std_block { $self->advance('/'); my $closing_name = $self->expression(0); - if ($closing_name->arity ne 'variable' && $closing_name->arity ne 'field') { + if ($closing_name->arity ne 'if' && $closing_name->arity ne 'field') { $self->_unexpected("closing block name", $self->token); } if ($closing_name->id ne $name->id) { # XXX diff --git a/t/mustache-spec.t b/t/mustache-spec.t index 3713abc..8ee1c10 100644 --- a/t/mustache-spec.t +++ b/t/mustache-spec.t @@ -9,7 +9,6 @@ use Test::Requires 'JSON', 'Path::Class'; for my $file (dir('t', 'mustache-spec', 'specs')->children) { next unless $file =~ /\.json$/; - next if $file->basename =~ /^~/; # for now next if $file->basename =~ /partials/; my $tests = decode_json($file->slurp); note("running " . $file->basename . " tests"); @@ -17,14 +16,36 @@ for my $file (dir('t', 'mustache-spec', 'specs')->children) { local $TODO = "unimplemented" if $file->basename eq 'delimiters.json' && $test->{name} =~ /partial/i; + local ($TODO, $SIG{__WARN__}) = ("unimplemented", sub { }) + if $file->basename eq '~lambdas.json' + && $test->{name} =~ /section/i; render_ok( $test->{template}, - $test->{data}, + fix_data($test->{data}), $test->{expected}, "$test->{name}: $test->{desc}" ); } } +sub fix_data { + my ($data) = @_; + + if (ref($data) eq 'HASH') { + if ($data->{__tag__} && $data->{__tag__} eq 'code') { + return eval $data->{perl}; + } + else { + return { map { $_ => fix_data($data->{$_}) } keys %$data }; + } + } + elsif (ref($data) eq 'ARRAY') { + return [ map { fix_data($_) } @$data ]; + } + else { + return $data; + } +} + done_testing; -- cgit v1.2.3