Merge branch 'decorators'
This commit is contained in:
+178
@@ -166,4 +166,182 @@ describe('blocks', function() {
|
||||
shouldCompileTo(string, [hash, undefined, undefined, true], 'Goodbye cruel ');
|
||||
});
|
||||
});
|
||||
|
||||
describe('decorators', function() {
|
||||
it('should apply mustache decorators', function() {
|
||||
var helpers = {
|
||||
helper: function(options) {
|
||||
return options.fn.run;
|
||||
}
|
||||
};
|
||||
var decorators = {
|
||||
decorator: function(fn) {
|
||||
fn.run = 'success';
|
||||
return fn;
|
||||
}
|
||||
};
|
||||
shouldCompileTo(
|
||||
'{{#helper}}{{*decorator}}{{/helper}}',
|
||||
{hash: {}, helpers: helpers, decorators: decorators},
|
||||
'success');
|
||||
});
|
||||
it('should apply allow undefined return', function() {
|
||||
var helpers = {
|
||||
helper: function(options) {
|
||||
return options.fn() + options.fn.run;
|
||||
}
|
||||
};
|
||||
var decorators = {
|
||||
decorator: function(fn) {
|
||||
fn.run = 'cess';
|
||||
}
|
||||
};
|
||||
shouldCompileTo(
|
||||
'{{#helper}}{{*decorator}}suc{{/helper}}',
|
||||
{hash: {}, helpers: helpers, decorators: decorators},
|
||||
'success');
|
||||
});
|
||||
|
||||
it('should apply block decorators', function() {
|
||||
var helpers = {
|
||||
helper: function(options) {
|
||||
return options.fn.run;
|
||||
}
|
||||
};
|
||||
var decorators = {
|
||||
decorator: function(fn, props, container, options) {
|
||||
fn.run = options.fn();
|
||||
return fn;
|
||||
}
|
||||
};
|
||||
shouldCompileTo(
|
||||
'{{#helper}}{{#*decorator}}success{{/decorator}}{{/helper}}',
|
||||
{hash: {}, helpers: helpers, decorators: decorators},
|
||||
'success');
|
||||
});
|
||||
it('should support nested decorators', function() {
|
||||
var helpers = {
|
||||
helper: function(options) {
|
||||
return options.fn.run;
|
||||
}
|
||||
};
|
||||
var decorators = {
|
||||
decorator: function(fn, props, container, options) {
|
||||
fn.run = options.fn.nested + options.fn();
|
||||
return fn;
|
||||
},
|
||||
nested: function(fn, props, container, options) {
|
||||
props.nested = options.fn();
|
||||
}
|
||||
};
|
||||
shouldCompileTo(
|
||||
'{{#helper}}{{#*decorator}}{{#*nested}}suc{{/nested}}cess{{/decorator}}{{/helper}}',
|
||||
{hash: {}, helpers: helpers, decorators: decorators},
|
||||
'success');
|
||||
});
|
||||
|
||||
it('should apply multiple decorators', function() {
|
||||
var helpers = {
|
||||
helper: function(options) {
|
||||
return options.fn.run;
|
||||
}
|
||||
};
|
||||
var decorators = {
|
||||
decorator: function(fn, props, container, options) {
|
||||
fn.run = (fn.run || '') + options.fn();
|
||||
return fn;
|
||||
}
|
||||
};
|
||||
shouldCompileTo(
|
||||
'{{#helper}}{{#*decorator}}suc{{/decorator}}{{#*decorator}}cess{{/decorator}}{{/helper}}',
|
||||
{hash: {}, helpers: helpers, decorators: decorators},
|
||||
'success');
|
||||
});
|
||||
|
||||
it('should access parent variables', function() {
|
||||
var helpers = {
|
||||
helper: function(options) {
|
||||
return options.fn.run;
|
||||
}
|
||||
};
|
||||
var decorators = {
|
||||
decorator: function(fn, props, container, options) {
|
||||
fn.run = options.args;
|
||||
return fn;
|
||||
}
|
||||
};
|
||||
shouldCompileTo(
|
||||
'{{#helper}}{{*decorator foo}}{{/helper}}',
|
||||
{hash: {'foo': 'success'}, helpers: helpers, decorators: decorators},
|
||||
'success');
|
||||
});
|
||||
it('should work with root program', function() {
|
||||
var run;
|
||||
var decorators = {
|
||||
decorator: function(fn, props, container, options) {
|
||||
equals(options.args[0], 'success');
|
||||
run = true;
|
||||
return fn;
|
||||
}
|
||||
};
|
||||
shouldCompileTo(
|
||||
'{{*decorator "success"}}',
|
||||
{hash: {'foo': 'success'}, decorators: decorators},
|
||||
'');
|
||||
equals(run, true);
|
||||
});
|
||||
it('should fail when accessing variables from root', function() {
|
||||
var run;
|
||||
var decorators = {
|
||||
decorator: function(fn, props, container, options) {
|
||||
equals(options.args[0], undefined);
|
||||
run = true;
|
||||
return fn;
|
||||
}
|
||||
};
|
||||
shouldCompileTo(
|
||||
'{{*decorator foo}}',
|
||||
{hash: {'foo': 'fail'}, decorators: decorators},
|
||||
'');
|
||||
equals(run, true);
|
||||
});
|
||||
|
||||
describe('registration', function() {
|
||||
it('unregisters', function() {
|
||||
handlebarsEnv.decorators = {};
|
||||
|
||||
handlebarsEnv.registerDecorator('foo', function() {
|
||||
return 'fail';
|
||||
});
|
||||
|
||||
equals(!!handlebarsEnv.decorators.foo, true);
|
||||
handlebarsEnv.unregisterDecorator('foo');
|
||||
equals(handlebarsEnv.decorators.foo, undefined);
|
||||
});
|
||||
|
||||
it('allows multiple globals', function() {
|
||||
handlebarsEnv.decorators = {};
|
||||
|
||||
handlebarsEnv.registerDecorator({
|
||||
foo: function() {},
|
||||
bar: function() {}
|
||||
});
|
||||
|
||||
equals(!!handlebarsEnv.decorators.foo, true);
|
||||
equals(!!handlebarsEnv.decorators.bar, true);
|
||||
handlebarsEnv.unregisterDecorator('foo');
|
||||
handlebarsEnv.unregisterDecorator('bar');
|
||||
equals(handlebarsEnv.decorators.foo, undefined);
|
||||
equals(handlebarsEnv.decorators.bar, undefined);
|
||||
});
|
||||
it('fails with multiple and args', function() {
|
||||
shouldThrow(function() {
|
||||
handlebarsEnv.registerDecorator({
|
||||
world: function() { return 'world!'; },
|
||||
testHelper: function() { return 'found it!'; }
|
||||
}, {});
|
||||
}, Error, 'Arg not supported with multiple decorators');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -247,6 +247,20 @@ describe('parser', function() {
|
||||
});
|
||||
});
|
||||
|
||||
describe('directives', function() {
|
||||
it('should parse block directives', function() {
|
||||
equals(astFor('{{#* foo}}{{/foo}}'), 'DIRECTIVE BLOCK:\n PATH:foo []\n PROGRAM:\n');
|
||||
});
|
||||
it('should parse directives', function() {
|
||||
equals(astFor('{{* foo}}'), '{{ DIRECTIVE PATH:foo [] }}\n');
|
||||
});
|
||||
it('should fail if directives have inverse', function() {
|
||||
shouldThrow(function() {
|
||||
astFor('{{#* foo}}{{^}}{{/foo}}');
|
||||
}, Error, /Unexpected inverse/);
|
||||
});
|
||||
});
|
||||
|
||||
it('GH1024 - should track program location properly', function() {
|
||||
var p = Handlebars.parse('\n'
|
||||
+ ' {{#if foo}}\n'
|
||||
|
||||
@@ -257,6 +257,45 @@ describe('partials', function() {
|
||||
});
|
||||
});
|
||||
|
||||
describe('inline partials', function() {
|
||||
it('should define inline partials for template', function() {
|
||||
shouldCompileTo('{{#*inline "myPartial"}}success{{/inline}}{{> myPartial}}', {}, 'success');
|
||||
});
|
||||
it('should overwrite multiple partials in the same template', function() {
|
||||
shouldCompileTo('{{#*inline "myPartial"}}fail{{/inline}}{{#*inline "myPartial"}}success{{/inline}}{{> myPartial}}', {}, 'success');
|
||||
});
|
||||
it('should define inline partials for block', function() {
|
||||
shouldCompileTo('{{#with .}}{{#*inline "myPartial"}}success{{/inline}}{{> myPartial}}{{/with}}', {}, 'success');
|
||||
shouldThrow(function() {
|
||||
shouldCompileTo('{{#with .}}{{#*inline "myPartial"}}success{{/inline}}{{/with}}{{> myPartial}}', {}, 'success');
|
||||
}, Error, /myPartial could not/);
|
||||
});
|
||||
it('should override global partials', function() {
|
||||
shouldCompileTo('{{#*inline "myPartial"}}success{{/inline}}{{> myPartial}}', {hash: {}, partials: {myPartial: function() { return 'fail'; }}}, 'success');
|
||||
});
|
||||
it('should override template partials', function() {
|
||||
shouldCompileTo('{{#*inline "myPartial"}}fail{{/inline}}{{#with .}}{{#*inline "myPartial"}}success{{/inline}}{{> myPartial}}{{/with}}', {}, 'success');
|
||||
});
|
||||
it('should override partials down the entire stack', function() {
|
||||
shouldCompileTo('{{#with .}}{{#*inline "myPartial"}}success{{/inline}}{{#with .}}{{#with .}}{{> myPartial}}{{/with}}{{/with}}{{/with}}', {}, 'success');
|
||||
});
|
||||
|
||||
it('should define inline partials for partial call', function() {
|
||||
shouldCompileToWithPartials(
|
||||
'{{#*inline "myPartial"}}success{{/inline}}{{> dude}}',
|
||||
[{}, {}, {dude: '{{> myPartial }}'}],
|
||||
true,
|
||||
'success');
|
||||
});
|
||||
it('should define inline partials in partial block call', function() {
|
||||
shouldCompileToWithPartials(
|
||||
'{{#> dude}}{{#*inline "myPartial"}}success{{/inline}}{{/dude}}',
|
||||
[{}, {}, {dude: '{{> myPartial }}'}],
|
||||
true,
|
||||
'success');
|
||||
});
|
||||
});
|
||||
|
||||
it('should pass compiler flags', function() {
|
||||
if (Handlebars.compile) {
|
||||
var env = Handlebars.create();
|
||||
|
||||
+3
-3
@@ -14,19 +14,19 @@ describe('runtime', function() {
|
||||
it('should throw on version mismatch', function() {
|
||||
shouldThrow(function() {
|
||||
Handlebars.template({
|
||||
main: true,
|
||||
main: {},
|
||||
compiler: [Handlebars.COMPILER_REVISION + 1]
|
||||
});
|
||||
}, Error, /Template was precompiled with a newer version of Handlebars than the current runtime/);
|
||||
shouldThrow(function() {
|
||||
Handlebars.template({
|
||||
main: true,
|
||||
main: {},
|
||||
compiler: [Handlebars.COMPILER_REVISION - 1]
|
||||
});
|
||||
}, Error, /Template was precompiled with an older version of Handlebars than the current runtime/);
|
||||
shouldThrow(function() {
|
||||
Handlebars.template({
|
||||
main: true
|
||||
main: {}
|
||||
});
|
||||
}, Error, /Template was precompiled with an older version of Handlebars than the current runtime/);
|
||||
});
|
||||
|
||||
@@ -241,6 +241,15 @@ describe('Tokenizer', function() {
|
||||
shouldMatchTokens(result, ['OPEN_BLOCK', 'ID', 'CLOSE', 'CONTENT', 'OPEN_ENDBLOCK', 'ID', 'CLOSE']);
|
||||
});
|
||||
|
||||
it('tokenizes directives', function() {
|
||||
shouldMatchTokens(
|
||||
tokenize('{{#*foo}}content{{/foo}}'),
|
||||
['OPEN_BLOCK', 'ID', 'CLOSE', 'CONTENT', 'OPEN_ENDBLOCK', 'ID', 'CLOSE']);
|
||||
shouldMatchTokens(
|
||||
tokenize('{{*foo}}'),
|
||||
['OPEN', 'ID', 'CLOSE']);
|
||||
});
|
||||
|
||||
it('tokenizes inverse sections as "INVERSE"', function() {
|
||||
shouldMatchTokens(tokenize('{{^}}'), ['INVERSE']);
|
||||
shouldMatchTokens(tokenize('{{else}}'), ['INVERSE']);
|
||||
|
||||
@@ -9,6 +9,8 @@ describe('Visitor', function() {
|
||||
var visitor = new Handlebars.Visitor();
|
||||
visitor.accept(Handlebars.parse('{{foo}}{{#foo (bar 1 "1" true undefined null) foo=@data}}{{!comment}}{{> bar }} {{/foo}}'));
|
||||
visitor.accept(Handlebars.parse('{{#> bar }} {{/bar}}'));
|
||||
visitor.accept(Handlebars.parse('{{#* bar }} {{/bar}}'));
|
||||
visitor.accept(Handlebars.parse('{{* bar }}'));
|
||||
});
|
||||
|
||||
it('should traverse to stubs', function() {
|
||||
|
||||
Reference in New Issue
Block a user