From 0da733acb424e9e0357dbf0822ed25f526b016af Mon Sep 17 00:00:00 2001 From: Seth Kinast Date: Wed, 12 Nov 2014 13:47:09 -0800 Subject: [PATCH 1/4] Add {@first} and {@last} helpers --- lib/dust-helpers.js | 14 ++++++++++++++ test/jasmine-test/spec/helpersTests.js | 23 ++++++++++++++++++++++- 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/lib/dust-helpers.js b/lib/dust-helpers.js index ccc105a..8b71830 100644 --- a/lib/dust-helpers.js +++ b/lib/dust-helpers.js @@ -154,6 +154,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; + }, + "idx": function(chunk, context, bodies) { var body = bodies.block; // Will be removed in 1.6 diff --git a/test/jasmine-test/spec/helpersTests.js b/test/jasmine-test/spec/helpersTests.js index 89e75d9..959754d 100644 --- a/test/jasmine-test/spec/helpersTests.js +++ b/test/jasmine-test/spec/helpersTests.js @@ -1346,7 +1346,7 @@ ] }, { - name: "sep", + name: "sep / first / last", tests: [ { name: "sep helper with no body", @@ -1377,6 +1377,27 @@ }, expected: "3, 2, 1", message: "should sep helper in a async_iterator" + }, + { + name: "first helper", + source: "{#guests}{@first}Hello {/first}{.} {/guests}", + context: { guests: function() { return ["Alice", "Bob", "Charlie"]; } }, + expected: "Hello Alice Bob Charlie ", + message: "first helper should output on the first iteration only" + }, + { + name: "last helper", + source: "Hello {#guests}{@last}and {/last}{.} {/guests}", + context: { guests: function() { return ["Alice", "Bob", "Charlie"]; } }, + expected: "Hello Alice Bob and Charlie ", + message: "last helper should output on the last iteration only" + }, + { + name: "first / last / sep combo", + source: "{#guests}{@first}Hello {/first}{@last}and {/last}{.}{@last}!{/last}{@sep}, {/sep}{/guests}", + context: { guests: function() { return ["Alice", "Bob", "Charlie"]; } }, + expected: "Hello Alice, Bob, and Charlie!", + message: "first, last, and sep helpers should operate together" } ] } From b872ed51362b127140b73d3fb7db3482ed741e17 Mon Sep 17 00:00:00 2001 From: Seth Kinast Date: Mon, 22 Dec 2014 13:41:40 -0800 Subject: [PATCH 2/4] Add {@none} helper as the converse to {@any} --- lib/dust-helpers.js | 33 +++++++++++++++++- test/jasmine-test/spec/helpersTests.js | 48 ++++++++++++++++++++++++++ 2 files changed, 80 insertions(+), 1 deletion(-) diff --git a/lib/dust-helpers.js b/lib/dust-helpers.js index c2d52c8..0f3d8d5 100644 --- a/lib/dust-helpers.js +++ b/lib/dust-helpers.js @@ -500,7 +500,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() { @@ -515,6 +515,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. @@ -522,6 +551,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; diff --git a/test/jasmine-test/spec/helpersTests.js b/test/jasmine-test/spec/helpersTests.js index 877d2a6..95067e7 100644 --- a/test/jasmine-test/spec/helpersTests.js +++ b/test/jasmine-test/spec/helpersTests.js @@ -1123,6 +1123,54 @@ } ] }, + { + name: "none", + tests: [ + { + name: "none without select", + source: '{@none}Hello{/none}', + context: { none: 'abc'}, + expected: "", + message: "none helper outside of select does not render" + }, + { + name: "none in select with no cases", + source: '{@select key=foo}{@none}Hello{/none}{/select}', + context: { foo: "bar"}, + expected: "Hello", + message: "none helper with no cases in the select renders" + }, + { + name: "none in select with no true cases", + source: '{@select key=foo}{@eq value=1/}{@none}Hello{/none}{/select}', + context: { foo: "bar"}, + expected: "Hello", + message: "none helper with no true cases in the select renders" + }, + { + name: "none in select with one true case", + source: '{@select key=foo}{@eq value="bar"/}{@none}Hello{/none}{/select}', + context: { foo: "bar"}, + expected: "", + message: "none helper with a true case in the select does not render" + }, + { + name: "multiple none helpers", + source: '{@select key=foo}{@none}Hello{/none}{@eq value="cow"/}{@none} World{/none}{/select}', + context: { foo: "bar"}, + expected: "Hello World", + message: "multiple none helpers in the same select all render" + }, + { + name: "none nested in an none properly with its own select", + source: '{@select key=foo}{@eq value="bar"/}{@none}Hello{@select key=moo}{@eq value="cow"/}{@none} World{/none}{/select}{/none}{/select}', + context: { foo: true, moo: true}, + expected: "Hello World", + message: "a none helper must have its own select to render" + } + + ] + }, { name: "size", tests: [ From 0a90948d936820a96b7ac33239a8e13e8a82d3de Mon Sep 17 00:00:00 2001 From: Seth Kinast Date: Mon, 22 Dec 2014 14:27:57 -0800 Subject: [PATCH 3/4] Select helper should still operate if its key parameter is set but resolves to undefined. --- lib/dust-helpers.js | 2 +- test/jasmine-test/spec/helpersTests.js | 16 +++++++++++++--- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/lib/dust-helpers.js b/lib/dust-helpers.js index c2d52c8..eafd7c4 100644 --- a/lib/dust-helpers.js +++ b/lib/dust-helpers.js @@ -367,7 +367,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) { diff --git a/test/jasmine-test/spec/helpersTests.js b/test/jasmine-test/spec/helpersTests.js index 877d2a6..d1de576 100644 --- a/test/jasmine-test/spec/helpersTests.js +++ b/test/jasmine-test/spec/helpersTests.js @@ -972,10 +972,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}\"}
FOO
{/eq}", " {@eq value=\"{x}\"}
BAR
{/eq}", " {@default}foofoo{/default}", @@ -984,6 +983,17 @@ expected: "", message: "should test select helper with missing key in the context and hence no output" }, + { + name: "select helper with key not defined in the context", + source: ["{#b}{@select key=y}", + " {@eq value=\"{z}\"}
FOO
{/eq}", + " {@eq value=\"{x}\"}
BAR
{/eq}", + " {@default}foofoo{/default}", + "{/select}{/b}"].join("\n"), + context: { b : { z: "foo", x: "bar" } }, + expected: "foofoo", + message: "should test select helper with undefined key in the context" + }, { name: "select helper wih key matching the default condition", source: ["{#b}{@select key=\"{x}\"}", From 77ccacda93aadf283279dcf46787abe3f6faafca Mon Sep 17 00:00:00 2001 From: Seth Kinast Date: Mon, 26 Jan 2015 16:34:15 -0800 Subject: [PATCH 4/4] Add AMD support --- .jshintrc | 3 ++- lib/dust-helpers.js | 18 ++++++++++++------ 2 files changed, 14 insertions(+), 7 deletions(-) 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 c2d52c8..d87e097 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) { @@ -566,12 +574,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); +}));