diff --git a/js/src/x-dust.js b/js/src/x-dust.js index d5b1819..ec32ffc 100755 --- a/js/src/x-dust.js +++ b/js/src/x-dust.js @@ -33,7 +33,7 @@ THE SOFTWARE. var BREAK = false, UNDEFINED, OPERATORS = ['~', '#', '?', '@', ':', '<', '>', '+', '/', '^'], - OPERATORS_WITH_BODY = ['#', '?', '@', ':', '+', '<'], + OPERATORS_WITH_BODY = ['#', '?', '@', ':', '+', '<', '^'], dust; function _hasProp(obj, name) { @@ -482,8 +482,13 @@ var XDustContext = _extend(function(head, tail, params) { XDustNotExistsNode = _extend(XDustExistsNode, function() { XDustExistsNode.apply(this, arguments); }, { - prepareModel: function(chain, context, model) { - return this.context.resolve(context, model) ? 'else' : 'block'; + operator: '^', + chooseBodyName: function(context, model) { + var resolved = this.context.resolve(context, model); + if (_isInstance(resolved, Array) && resolved.length < 1) { + resolved = false; + } + return resolved ? 'else' : 'block'; } }), XDustHelperNode = _extend(XDustLogicNode, function(name, scope, params, blocks, bodies) { @@ -657,6 +662,8 @@ var XDustContext = _extend(function(head, tail, params) { } } else if (operator == '?') { node = new XDustExistsNode(tagName, scope, params); + } else if (operator == '^') { + node = new XDustNotExistsNode(tagName, scope, params); } else if (operator == '@') { name = tag[0].slice(1); if (name == 'idx') { diff --git a/js/test/unit/x-dust.js b/js/test/unit/x-dust.js index 07f9986..d3d9f8b 100644 --- a/js/test/unit/x-dust.js +++ b/js/test/unit/x-dust.js @@ -71,6 +71,13 @@ describe('x-dust', function() { it('can test logic without consuming scope', render('ex', '{?tags}{:else}No tags!{/tags}', {foo: 'bar', tags: ['a', 'b', 'c']}, '')); it('can support an else block', render('ex', '{?tags}{:else}No tags!{/tags}', {foo: 'bar', tags: []}, 'No tags!')); }); + describe('^ operator', function() { + it('can output inner content when tested against an undefined value', render('ex', '{^tags}No tags!{:else}Yes tags!{/tags}', {foo: 'bar'}, 'No tags!')); + it('can output inner content when tested against a defined but falsey value', render('ex', '{^tags}No tags!{/tags}', {foo: 'bar', tags: 0}, 'No tags!')); + it('can output inner content when tested against an empty array', render('ex', '{^tags}No tags!{/tags}', {foo: 'bar', tags: []}, 'No tags!')); + it('can ignore inner content when tested against a truthy value', render('ex', '{^tags}no {/tags}tags here', {foo: 'bar', tags: ['a', 'b', 'c']}, 'tags here')); + it('can support an else block', render('ex', '{^tags}No tags!{:else}{/tags}', {foo: 'bar', tags: ['a', 'b', 'c']}, '')); + }); describe('! operator', function() { it('can comment out multiple lines of text', render('ex', '{!\nMultiline {#foo}{bar}{/foo}!}{!before!}Hello{!after!}', {}, 'Hello')); });