summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJesse Luehrs <doy@tozt.net>2012-10-08 13:33:45 -0500
committerJesse Luehrs <doy@tozt.net>2012-10-08 13:33:45 -0500
commit6d3b76546c92f15aadc2a9c4b7568411e49ccfbe (patch)
tree99d12c1e4c9d73765fa9bc09320f896cdae50ca4
parent7f47485c049416b1c4386d21531f1e50ae3acd79 (diff)
downloadtext-handlebars-6d3b76546c92f15aadc2a9c4b7568411e49ccfbe.tar.gz
text-handlebars-6d3b76546c92f15aadc2a9c4b7568411e49ccfbe.zip
implement hash parameters for block helpers
-rw-r--r--lib/Text/Handlebars.pm7
-rw-r--r--lib/Text/Handlebars/Compiler.pm31
-rw-r--r--lib/Text/Xslate/Syntax/Handlebars.pm18
-rw-r--r--t/block-helpers.t10
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 "<ul $attrs>"
. join("\n", map {
"<li>" . $options->{fn}->($_) . "</li>"
} @$items)
- . "</ul>";
+ . "</ul>\n";
},
},
},
<<'TEMPLATE',
-{{list nav id="nav-bar" class="top"}}
+{{#list nav id="nav-bar" class="top"}}
<a href="{{url}}">{{title}}</a>
{{/list}}
TEMPLATE
@@ -325,12 +324,13 @@ TEMPLATE
<<'RENDERED',
<ul class="top" id="nav-bar"><li> <a href="http://www.yehudakatz.com">Katz Got Your Tongue</a>
</li>
- <a href="http://www.sproutcore.com/block">SproutCore Blog</a>
+<li> <a href="http://www.sproutcore.com/block">SproutCore Blog</a>
</li></ul>
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!