Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

moved dustjs helpers from the original repo. Math helper and idx chan…

…ge added.
  • Loading branch information...
commit 71a4fc989004e3f7d2377bc5edd787eccac22b44 1 parent 5f59b59
Jairo de Morais authored August 22, 2012
130  dist/dust-helpers-1.0.0.js
@@ -14,7 +14,7 @@ if (typeof exports !== "undefined")
14 14
 
15 15
 /* make a safe version of console if it is not available
16 16
  * currently supporting:
17  
- *   _console.log 
  17
+ *   _console.log
18 18
  * */
19 19
 var _console = (typeof console !== 'undefined')? console: {
20 20
   log: function(){
@@ -24,12 +24,12 @@ var _console = (typeof console !== 'undefined')? console: {
24 24
 
25 25
 function isSelect(context) {
26 26
   var value = context.current();
27  
-  return typeof value === "object" && value.isSelect === true;    
  27
+  return typeof value === "object" && value.isSelect === true;
28 28
 }
29 29
 
30 30
 function filter(chunk, context, bodies, params, filter) {
31 31
   var params = params || {},
32  
-      actual, 
  32
+      actual,
33 33
       expected;
34 34
   if (params.key) {
35 35
     actual = helpers.tap(params.key, chunk, context);
@@ -82,7 +82,7 @@ var helpers = {
82 82
   },
83 83
   
84 84
   contextDump: function(chunk, context, bodies) {
85  
-    _console.log(JSON.stringify(context.stack));
  85
+    _console.log(JSON.stringify(context.stack.head));
86 86
     return chunk;
87 87
   },
88 88
   
@@ -92,20 +92,24 @@ var helpers = {
92 92
     var output = input;
93 93
     // dust compiles a string to function, if there are references
94 94
     if( typeof input === "function"){
95  
-      output = '';
96  
-      chunk.tap(function(data){
97  
-        output += data;
98  
-        return '';
99  
-      }).render(input, context).untap();
100  
-      if( output === '' ){
101  
-        output = false;
  95
+      if( ( typeof input.isReference !== "undefined" ) && ( input.isReference === true ) ){ // just a plain function, not a dust `body` function
  96
+        output = input();
  97
+      } else {
  98
+        output = '';
  99
+        chunk.tap(function(data){
  100
+          output += data;
  101
+          return '';
  102
+        }).render(input, context).untap();
  103
+        if( output === '' ){
  104
+          output = false;
  105
+        }
102 106
       }
103  
-    } 
  107
+    }
104 108
     return output;
105 109
   },
106 110
 
107 111
   /**
108  
-  if helper 
  112
+  if helper
109 113
    @param cond, either a string literal value or a dust reference
110 114
                 a string literal value, is enclosed in double quotes, e.g. cond="2>3"
111 115
                 a dust reference is also enclosed in double quotes, e.g. cond="'{val}'' > 3"
@@ -131,8 +135,72 @@ var helpers = {
131 135
     return chunk;
132 136
   },
133 137
   
  138
+  /**
  139
+   * math helper
  140
+   * @param key is the value to perform math against
  141
+   * @param eq is the value to test for equality with key
  142
+   * @param method is the math method we will employ
  143
+   * in the absence of an equality test
  144
+   * @param operand is the second value needed for
  145
+   * operations like mod, add, subtract, etc.
  146
+   */
  147
+  "math": function ( chunk, context, bodies, params ) {
  148
+    //make sure we have key and eq or method params before continuing
  149
+    if( params && params.key && (params.eq ||  params.method) ){
  150
+      var key  = params.key;
  151
+      key  = this.tap(key, chunk, context);
  152
+      if (params.eq) {
  153
+        var eq = params.eq;
  154
+        eq = this.tap(eq, chunk, context);
  155
+        return chunk.write(key === eq);
  156
+      }
  157
+      //we are going to operate with math methods if not equals
  158
+      else {
  159
+        var method = params.method;
  160
+        var operand = params.operand || null;
  161
+        var operError = function(){_console.log("operand is required for this math method")};
  162
+        var returnExpression = function(exp){chunk.write( exp )};
  163
+        if (operand) {
  164
+          operand = this.tap(operand, chunk, context);
  165
+        }
  166
+        switch(method) {
  167
+            case "mod":
  168
+              (operand) ? returnExpression( parseFloat(key) % parseFloat(operand) ) : operError();
  169
+              break;
  170
+            case "add":
  171
+              (operand) ? returnExpression( parseFloat(key) + parseFloat(operand) ) : operError();
  172
+              break;
  173
+            case "subtract":
  174
+              (operand) ? returnExpression( parseFloat(key) - parseFloat(operand) ) : operError();
  175
+              break;
  176
+            case "multiply":
  177
+              (operand) ? returnExpression( parseFloat(key) * parseFloat(operand) ) : operError();
  178
+              break;
  179
+            case "divide":
  180
+              (operand) ? returnExpression( parseFloat(key) / parseFloat(operand) ) : operError();
  181
+              break;
  182
+            case "ceil":
  183
+              returnExpression( Math.ceil(parseFloat(key)) );
  184
+              break;
  185
+            case "floor":
  186
+              returnExpression( Math.floor(parseFloat(key)) );
  187
+              break;
  188
+            case "abs":
  189
+              returnExpression( Math.abs(parseFloat(key)) );
  190
+              break;
  191
+            default:
  192
+              _console.log( "method passed is not supported" );
  193
+        }
  194
+      }
  195
+    }
  196
+    // no key parameter and no method or eq passed
  197
+    else {
  198
+      _console.log( "Key is a required parameter along with eq or method/operand!" );
  199
+    }
  200
+    return chunk;
  201
+  },
134 202
    /**
135  
-   select/eq/lt/lte/gt/gte/default helper 
  203
+   select/eq/lt/lte/gt/gte/default helper
136 204
    @param key, either a string literal value or a dust reference
137 205
                 a string literal value, is enclosed in double quotes, e.g. key="foo"
138 206
                 a dust reference may or may not be enclosed in double quotes, e.g. key="{val}" and key=val are both valid
@@ -174,28 +242,32 @@ var helpers = {
174 242
   "default": function(chunk, context, bodies, params) {
175 243
     return filter(chunk, context, bodies, params, function(expected, actual) { return true; });
176 244
   },
177  
-
178 245
   "size": function( chunk, context, bodies, params ) {
179  
-    var subject = params.subject; 
  246
+    var subject = params.subject;
180 247
     var value   = 0;
181 248
     if (!subject) { //undefined, "", 0
182  
-      value = 0;  
183  
-    } else if(dust.isArray(subject)) { //array 
184  
-      value = subject.length;  
185  
-    } else if (!isNaN(subject)) { //numeric values  
186  
-      value = subject;  
187  
-    } else if (Object(subject) === subject) { //object test
188  
-      var nr = 0;  
189  
-      for(var k in subject) if(Object.hasOwnProperty.call(subject,k)) nr++;  
190  
-        value = nr;
191  
-    } else { 
192  
-      value = (subject + '').length; //any other value (strings etc.)  
193  
-    } 
194  
-    return chunk.write(value); 
  249
+      value = 0;
  250
+    }
  251
+    else if(dust.isArray(subject)) { //array
  252
+      value = subject.length;
  253
+    }
  254
+    else if (!isNaN(subject)) { //numeric values
  255
+      value = subject;
  256
+    }
  257
+    else if (Object(subject) === subject) { //object test
  258
+      var nr = 0;
  259
+      for(var k in subject)
  260
+        if(Object.hasOwnProperty.call(subject,k)) nr++;
  261
+          value = nr;
  262
+    } else {
  263
+      value = (subject + '').length; //any other value (strings etc.)
  264
+    }
  265
+    return chunk.write(value);
195 266
   }
196 267
 };
197 268
 
198 269
 dust.helpers = helpers;
  270
+
199 271
 if (typeof exports !== "undefined")
200 272
 {
201 273
   module.exports = dust;
102  lib/dust-helpers.js
@@ -75,7 +75,7 @@ var helpers = {
75 75
   },
76 76
   
77 77
   contextDump: function(chunk, context, bodies) {
78  
-    _console.log(JSON.stringify(context.stack));
  78
+    _console.log(JSON.stringify(context.stack.head));
79 79
     return chunk;
80 80
   },
81 81
   
@@ -85,7 +85,7 @@ var helpers = {
85 85
     var output = input;
86 86
     // dust compiles a string to function, if there are references
87 87
     if( typeof input === "function"){
88  
-      if( input.length == 0 ) { // just a plain function, not a dust `body` function
  88
+      if( ( typeof input.isReference !== "undefined" ) && ( input.isReference === true ) ){ // just a plain function, not a dust `body` function
89 89
         output = input();
90 90
       } else {
91 91
         output = '';
@@ -128,6 +128,70 @@ var helpers = {
128 128
     return chunk;
129 129
   },
130 130
   
  131
+  /**
  132
+   * math helper
  133
+   * @param key is the value to perform math against
  134
+   * @param eq is the value to test for equality with key
  135
+   * @param method is the math method we will employ
  136
+   * in the absence of an equality test
  137
+   * @param operand is the second value needed for
  138
+   * operations like mod, add, subtract, etc.
  139
+   */
  140
+  "math": function ( chunk, context, bodies, params ) {
  141
+    //make sure we have key and eq or method params before continuing
  142
+    if( params && params.key && (params.eq ||  params.method) ){
  143
+      var key  = params.key;
  144
+      key  = this.tap(key, chunk, context);
  145
+      if (params.eq) {
  146
+        var eq = params.eq;
  147
+        eq = this.tap(eq, chunk, context);
  148
+        return chunk.write(key === eq);
  149
+      }
  150
+      //we are going to operate with math methods if not equals
  151
+      else {
  152
+        var method = params.method;
  153
+        var operand = params.operand || null;
  154
+        var operError = function(){_console.log("operand is required for this math method")};
  155
+        var returnExpression = function(exp){chunk.write( exp )};
  156
+        if (operand) {
  157
+          operand = this.tap(operand, chunk, context);
  158
+        }
  159
+        switch(method) {
  160
+            case "mod":
  161
+              (operand) ? returnExpression( parseFloat(key) % parseFloat(operand) ) : operError();
  162
+              break;
  163
+            case "add":
  164
+              (operand) ? returnExpression( parseFloat(key) + parseFloat(operand) ) : operError();
  165
+              break;
  166
+            case "subtract":
  167
+              (operand) ? returnExpression( parseFloat(key) - parseFloat(operand) ) : operError();
  168
+              break;
  169
+            case "multiply":
  170
+              (operand) ? returnExpression( parseFloat(key) * parseFloat(operand) ) : operError();
  171
+              break;
  172
+            case "divide":
  173
+              (operand) ? returnExpression( parseFloat(key) / parseFloat(operand) ) : operError();
  174
+              break;
  175
+            case "ceil":
  176
+              returnExpression( Math.ceil(parseFloat(key)) );
  177
+              break;
  178
+            case "floor":
  179
+              returnExpression( Math.floor(parseFloat(key)) );
  180
+              break;
  181
+            case "abs":
  182
+              returnExpression( Math.abs(parseFloat(key)) );
  183
+              break;
  184
+            default:
  185
+              _console.log( "method passed is not supported" );
  186
+        }
  187
+      }
  188
+    }
  189
+    // no key parameter and no method or eq passed
  190
+    else {
  191
+      _console.log( "Key is a required parameter along with eq or method/operand!" );
  192
+    }
  193
+    return chunk;
  194
+  },
131 195
    /**
132 196
    select/eq/lt/lte/gt/gte/default helper
133 197
    @param key, either a string literal value or a dust reference
@@ -171,28 +235,32 @@ var helpers = {
171 235
   "default": function(chunk, context, bodies, params) {
172 236
     return filter(chunk, context, bodies, params, function(expected, actual) { return true; });
173 237
   },
174  
-
175 238
   "size": function( chunk, context, bodies, params ) {
176  
-    var subject = params.subject; 
  239
+    var subject = params.subject;
177 240
     var value   = 0;
178 241
     if (!subject) { //undefined, "", 0
179  
-      value = 0;  
180  
-    } else if(dust.isArray(subject)) { //array 
181  
-      value = subject.length;  
182  
-    } else if (!isNaN(subject)) { //numeric values  
183  
-      value = subject;  
184  
-    } else if (Object(subject) === subject) { //object test
185  
-      var nr = 0;  
186  
-      for(var k in subject) if(Object.hasOwnProperty.call(subject,k)) nr++;  
187  
-        value = nr;
188  
-    } else { 
189  
-      value = (subject + '').length; //any other value (strings etc.)  
190  
-    } 
191  
-    return chunk.write(value); 
  242
+      value = 0;
  243
+    }
  244
+    else if(dust.isArray(subject)) { //array
  245
+      value = subject.length;
  246
+    }
  247
+    else if (!isNaN(subject)) { //numeric values
  248
+      value = subject;
  249
+    }
  250
+    else if (Object(subject) === subject) { //object test
  251
+      var nr = 0;
  252
+      for(var k in subject)
  253
+        if(Object.hasOwnProperty.call(subject,k)) nr++;
  254
+          value = nr;
  255
+    } else {
  256
+      value = (subject + '').length; //any other value (strings etc.)
  257
+    }
  258
+    return chunk.write(value);
192 259
   }
193 260
 };
194 261
 
195 262
 dust.helpers = helpers;
  263
+
196 264
 if (typeof exports !== "undefined")
197 265
 {
198 266
   module.exports = dust;
BIN  test/jasmine-test/client/lib/.DS_Store
Binary file not shown
6  test/jasmine-test/client/specRunner.html
@@ -20,6 +20,12 @@
20 20
 
21 21
   <script type="text/javascript">
22 22
     (function() {
  23
+      //Add the tapper helper to test the Tap helper.
  24
+      dust.helpers.tapper = function(chunk, context, bodies, params) {
  25
+        var result = dust.helpers.tap(params.value,chunk,context);
  26
+        chunk.write(result);
  27
+        return chunk;
  28
+      };
23 29
       var jasmineEnv = jasmine.getEnv();
24 30
       jasmineEnv.updateInterval = 1000;
25 31
 
7  test/jasmine-test/server/specRunner.js
@@ -9,6 +9,13 @@ helpersTests = require('../spec/helpersTests');
9 9
 
10 10
 //Add the tapper helper to test the Tap helper.
11 11
 dust.helpers.tapper = function(chunk, context, bodies, params) {
  12
+  var result = dust.helpers.tap(params.value,chunk,context);
  13
+  chunk.write(result);
  14
+  return chunk;
  15
+};
  16
+
  17
+//Add the tapper helper to test the Tap helper.
  18
+dust.helpers.tapper = function(chunk, context, bodies, params) {
12 19
   var result = dust.helpers.tap(params.value,chunk,context); 
13 20
   chunk.write(result); 
14 21
   return chunk;
133  test/jasmine-test/spec/helpersTests.js
@@ -42,6 +42,83 @@ var helpersTests = [
42 42
     message: "should test the if helper using $idx"
43 43
   },
44 44
   {
  45
+    name:     "math helper mod numbers",
  46
+    source:   '<div>{@math key="16" method="mod" operand="4"/}</div>',  
  47
+    context:  {},
  48
+    expected: "<div>0</div>",
  49
+    message: "testing math/mod helper with two numbers"
  50
+  },
  51
+  {
  52
+    name:     "math helper mod using $idx",
  53
+    source:   '{#list}<div>{@math key="{$idx}" method="mod" operand="5"/}</div>{/list}',
  54
+    context:  { list: [ { y: 'foo' } ]},
  55
+    expected: "<div>0</div>",
  56
+    message: "should test the math/mod helper using $idx"
  57
+  },
  58
+  {
  59
+    name:     "math helper subtract numbers",
  60
+    source:   '<div>{@math key="16" method="subtract" operand="4"/}</div>',
  61
+    context:  {},
  62
+    expected: "<div>12</div>",
  63
+    message: "testing math/subtract helper with two numbers"
  64
+  },
  65
+  {
  66
+    name:     "math helper subtract number and string",
  67
+    source:   '<div>{@math key="16" method="subtract" operand="doh"/}</div>',
  68
+    context:  {},
  69
+    expected: "<div>NaN</div>",
  70
+    message: "testing math/subtract helper with a number and a string"
  71
+  },
  72
+  {
  73
+    name:     "math helper add numbers",
  74
+    source:   '<div>{@math key="5" method="add" operand="4"/}</div>',
  75
+    context:  {},
  76
+    expected: "<div>9</div>",
  77
+    message: "testing math/add helper with two numbers"
  78
+  },
  79
+  {
  80
+    name:     "math helper multiply numbers",
  81
+    source:   '<div>{@math key="5" method="multiply" operand="4"/}</div>',
  82
+    context:  {},
  83
+    expected: "<div>20</div>",
  84
+    message: "testing math/multiply helper with two numbers"
  85
+  },
  86
+  {
  87
+    name:     "math helper divide using variable",
  88
+    source:   '<div>{@math key="16" method="divide" operand="{y}"/}</div>',
  89
+    context:  { y : 4 },
  90
+    expected: "<div>4</div>",
  91
+    message: "testing math/divide helper with variable as operand"
  92
+  },
  93
+  {
  94
+    name:     "math helper floor numbers",
  95
+    source:   '<div>{@math key="16.5" method="floor"/}</div>',
  96
+    context:  {},
  97
+    expected: "<div>16</div>",
  98
+    message: "testing math/floor helper with two numbers"
  99
+  },
  100
+  {
  101
+    name:     "math helper ceil numbers",
  102
+    source:   '<div>{@math key="16.5" method="ceil"/}</div>',
  103
+    context:  {},
  104
+    expected: "<div>17</div>",
  105
+    message: "testing math/ceil helper with two numbers"
  106
+  },
  107
+  {
  108
+    name:     "math helper abs numbers",
  109
+    source:   '<div>{@math key="-16" method="abs"/}</div>',
  110
+    context:  {},
  111
+    expected: "<div>16</div>",
  112
+    message: "testing math/abs helper with two numbers"
  113
+  },
  114
+  { 
  115
+    name:     "math helper eq  numbers",
  116
+    source:   '<div>{@math key="15" eq="16"/}</div>',
  117
+    context:  {},
  118
+    expected: "<div>false</div>",
  119
+    message: "testing math/eq helper with two numbers"
  120
+  },
  121
+  {
45 122
     name:     "select helper with a constant string and condition eq",
46 123
     source:   ["{@select key=\"foo\"}",
47 124
                  "{@eq value=\"foo\"}foo{/eq}",
@@ -398,6 +475,62 @@ var helpersTests = [
398 475
     context:  { "a" : {"foo" : function() { return "bar"; } } },
399 476
     expected: "bar bar",
400 477
     message: "should test if tap Helper is working properly when it makes reference to a function within an object-valued {context variable}"
  478
+  },
  479
+  {
  480
+     name:     "array: reference $idx in iteration on objects",
  481
+     source:   "{#names}({$idx}).{title} {name}{~n}{/names}",
  482
+     context:  { title: "Sir", names: [ { name: "Moe" }, { name: "Larry" }, { name: "Curly" } ] },
  483
+     expected: "(0).Sir Moe\n(1).Sir Larry\n(2).Sir Curly\n",
  484
+     message: "array: reference $idx in iteration on objects"
  485
+  },
  486
+  {
  487
+      name:     "array: reference $len in iteration on objects",
  488
+      source:   "{#names}Size=({$len}).{title} {name}{~n}{/names}",
  489
+      context:  { title: "Sir", names: [ { name: "Moe" }, { name: "Larry" }, { name: "Curly" } ] },
  490
+      expected: "Size=(3).Sir Moe\nSize=(3).Sir Larry\nSize=(3).Sir Curly\n",
  491
+      message: "test array: reference $len in iteration on objects"
  492
+  },
  493
+  {
  494
+     name:     "array reference $idx in iteration on simple type",
  495
+     source:   "{#names}({$idx}).{title} {.}{~n}{/names}",
  496
+     context:  { title: "Sir", names: [ "Moe", "Larry", "Curly" ] },
  497
+     expected: "(0).Sir Moe\n(1).Sir Larry\n(2).Sir Curly\n",
  498
+     message: "test array reference $idx in iteration on simple types"
  499
+  },
  500
+  {
  501
+      name:     "array reference $len in iteration on simple type",
  502
+      source:   "{#names}Size=({$len}).{title} {.}{~n}{/names}",
  503
+      context:  { title: "Sir", names: [ "Moe", "Larry", "Curly" ] },
  504
+      expected: "Size=(3).Sir Moe\nSize=(3).Sir Larry\nSize=(3).Sir Curly\n",
  505
+      message: "test array reference $len in iteration on simple types"
  506
+  },
  507
+  {
  508
+      name:     "array reference $idx/$len on empty array case",
  509
+      source:   "{#names}Idx={$idx} Size=({$len}).{title} {.}{~n}{/names}",
  510
+      context:  { title: "Sir", names: [ ] },
  511
+      expected: "",
  512
+      message: "test array reference $idx/$len on empty array case"
  513
+  },
  514
+  {
  515
+      name:     "array reference $idx/$len on single element case",
  516
+      source:   "{#names}Idx={$idx} Size={$len} {.}{/names}",
  517
+      context:  { names: "Just one name" },
  518
+      expected: "Idx=0 Size=1 Just one name",
  519
+      message: "test array reference $idx/$len on single element case"
  520
+  },
  521
+  {
  522
+      name:     "array reference $idx/$len {#.} section case",
  523
+      source:   "{#names}{#.}{$idx}{.} {/.}{/names}",
  524
+      context:  { names:  ["Moe", "Larry", "Curly"] },
  525
+      expected: "0Moe 1Larry 2Curly ",
  526
+      message: "test array reference $idx/$len {#.} section case"
  527
+  },
  528
+  {
  529
+      name:     "array reference $idx/$len nested loops",
  530
+      source:   "{#A}A loop:{$idx}-{$len},{#B}B loop:{$idx}-{$len}C[0]={.C[0]} {/B}A loop trailing: {$idx}-{$len}{/A}",
  531
+      context:  {"A": [ {"B": [ {"C": ["Ca1", "C2"]}, {"C": ["Ca2", "Ca22"]} ] }, {"B": [ {"C": ["Cb1", "C2"]}, {"C": ["Cb2", "Ca2"]} ] } ] },
  532
+      expected: "A loop:0-2,B loop:0-2C[0]=Ca1 B loop:1-2C[0]=Ca2 A loop trailing: 0-2A loop:1-2,B loop:0-2C[0]=Cb1 B loop:1-2C[0]=Cb2 A loop trailing: 1-2",
  533
+      message: "test array reference $idx/$len nested loops"
401 534
   }
402 535
 ];
403 536
 
7  test/server.js
@@ -3,6 +3,13 @@ var uutest    = require('./uutest'),
3 3
     tests     = require('./jasmine-test/spec/helpersTests'),
4 4
     coreSetup = require('./core').coreSetup;
5 5
 
  6
+//Add the tapper helper to test the Tap helper.
  7
+dust.helpers.tapper = function(chunk, context, bodies, params) {
  8
+  var result = dust.helpers.tap(params.value,chunk,context);
  9
+  chunk.write(result);
  10
+  return chunk;
  11
+};
  12
+
6 13
 function dumpError(err) {
7 14
   var out = err.testName + " -> ";
8 15
   if (!err.message) {

0 notes on commit 71a4fc9

Please sign in to comment.
Something went wrong with that request. Please try again.