diff --git a/.jshintrc b/.jshintrc index c862aec..e66f0ed 100644 --- a/.jshintrc +++ b/.jshintrc @@ -16,7 +16,8 @@ "dust": true, "require": true, "module": true, + "define": true, "console": true, "__dirname": true } -} \ No newline at end of file +} diff --git a/lib/dust-helpers.js b/lib/dust-helpers.js index e7ecdc3..d8b033a 100644 --- a/lib/dust-helpers.js +++ b/lib/dust-helpers.js @@ -1,4 +1,12 @@ -(function(dust){ +(function(root, factory) { + if (typeof define === 'function' && define.amd && define.amd.dust === true) { + define(['dust.core'], factory); + } else if (typeof exports === 'object') { + module.exports = factory(require('dustjs-linkedin')); + } else { + factory(root.dust); + } +}(this, function(dust) { // Use dust's built-in logging when available var _log = dust.log ? function(msg, level) { @@ -180,6 +188,20 @@ var helpers = { } }, + "first": function(chunk, context, bodies) { + if (context.stack.index === 0) { + return bodies.block(chunk, context); + } + return chunk; + }, + + "last": function(chunk, context, bodies) { + if (context.stack.index === context.stack.of - 1) { + return bodies.block(chunk, context); + } + return chunk; + }, + /** * contextDump helper * @param key specifies how much to dump. @@ -324,7 +346,7 @@ var helpers = { var body = bodies.block, state, key, len, x; - if (params && typeof params.key !== "undefined") { + if (params.hasOwnProperty("key")) { key = dust.helpers.tap(params.key, chunk, context); // bodies['else'] is meaningless and is ignored if (body) { @@ -457,7 +479,7 @@ var helpers = { } else { selectState = getSelectState(context); if(selectState.isDeferredComplete) { - _log("{@any} nested inside {@any} block. It needs its own {@select} block", "WARN"); + _log("{@any} nested inside {@any} or {@none} block. It needs its own {@select} block", "WARN"); } else { chunk = chunk.map(function(chunk) { selectState.deferreds.push(function() { @@ -472,6 +494,35 @@ var helpers = { return chunk; }, + /** + * {@none} + * Outputs if no truth tests inside a {@select} pass. + * Must be contained inside a {@select} block. + * The position of the helper does not matter. + */ + "none": function(chunk, context, bodies, params) { + var selectState; + + if(!isSelect(context)) { + _log("{@none} used outside of a {@select} block", "WARN"); + } else { + selectState = getSelectState(context); + if(selectState.isDeferredComplete) { + _log("{@none} nested inside {@any} or {@none} block. It needs its own {@select} block", "WARN"); + } else { + chunk = chunk.map(function(chunk) { + selectState.deferreds.push(function() { + if(!selectState.isResolved) { + chunk = chunk.render(bodies.block, context); + } + chunk.end(); + }); + }); + } + } + return chunk; + }, + /** * {@default} * Outputs if no truth test inside a {@select} has passed. @@ -479,6 +530,8 @@ var helpers = { */ "default": function(chunk, context, bodies, params) { params.filterOpType = "default"; + // Deprecated for removal in 1.7 + _deprecated("{@default}"); if(!isSelect(context)) { _log("{@default} used outside of a {@select} block", "WARN"); return chunk; @@ -523,12 +576,10 @@ var helpers = { }; - for (var key in helpers) { + for(var key in helpers) { dust.helpers[key] = helpers[key]; } - if(typeof exports !== 'undefined') { - module.exports = dust; - } + return dust; -})(typeof exports !== 'undefined' ? require('dustjs-linkedin') : dust); +})); diff --git a/test/jasmine-test/spec/helpersTests.js b/test/jasmine-test/spec/helpersTests.js index 3ef94f7..a307cdc 100644 --- a/test/jasmine-test/spec/helpersTests.js +++ b/test/jasmine-test/spec/helpersTests.js @@ -918,10 +918,9 @@ expected: "foobar", message: "should test select helper with variable and type string in a nested objects" }, - { - name: "select helper with missing key in the context and hence no output", - source: ["{#b}{@select key=y}", + name: "select helper with missing key parameter and hence no output", + source: ["{#b}{@select}", " {@eq value=\"{z}\"}