walrus-rb 0.10.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,1304 @@
1
+
2
+ /**
3
+ * walrus 0.10.1
4
+ * A bolder kind of mustache.
5
+ * (c) 2012 Jeremy Ruppel
6
+ * Released under the MIT license.
7
+ * For all details and documentation:
8
+ * https://github.com/jeremyruppel/walrus
9
+ */
10
+
11
+ (function() {
12
+ var AST, Utils, Walrus,
13
+ __hasProp = Object.prototype.hasOwnProperty,
14
+ __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor; child.__super__ = parent.prototype; return child; },
15
+ __slice = Array.prototype.slice;
16
+
17
+ Walrus = {
18
+ VERSION: '0.10.1'
19
+ /**
20
+ * This object will get mixed in to every object
21
+ * passed to a compiled template. This is a good
22
+ * place to put any methods you need to access
23
+ * in all of your templates.
24
+ */
25
+ };
26
+
27
+ Walrus.Context = {};
28
+
29
+
30
+ /* Jison generated parser */
31
+ var walrus = (function(){
32
+ var parser = {trace: function trace() { },
33
+ yy: {},
34
+ symbols_: {"error":2,"document":3,"text":4,"EOF":5,"statements":6,"statement":7,"OPEN":8,"helper":9,"mustache":10,"block":11,"SAFE":12,"CLOSE":13,"CONTENT":14,"expression":15,"PIPE":16,"filters":17,"ATTR":18,"paths":19,"DOT":20,"primitive":21,"OPEN_BLOCK":22,"CLOSE_BLOCK":23,"HELP":24,"MEMBER":25,"filter":26,"OPEN_PAREN":27,"arguments":28,"CLOSE_PAREN":29,"path":30,"method":31,"member":32,"COMMA":33,"argument":34,"SINGLE_QUOTE_STRING_LITERAL":35,"DOUBLE_QUOTE_STRING_LITERAL":36,"BOOLEAN_FALSE":37,"BOOLEAN_TRUE":38,"NUMBER":39,"$accept":0,"$end":1},
35
+ terminals_: {2:"error",5:"EOF",8:"OPEN",12:"SAFE",13:"CLOSE",14:"CONTENT",16:"PIPE",18:"ATTR",20:"DOT",22:"OPEN_BLOCK",23:"CLOSE_BLOCK",24:"HELP",25:"MEMBER",27:"OPEN_PAREN",29:"CLOSE_PAREN",33:"COMMA",35:"SINGLE_QUOTE_STRING_LITERAL",36:"DOUBLE_QUOTE_STRING_LITERAL",37:"BOOLEAN_FALSE",38:"BOOLEAN_TRUE",39:"NUMBER"},
36
+ productions_: [0,[3,2],[3,1],[4,1],[6,2],[6,1],[7,4],[7,3],[7,3],[7,1],[10,3],[10,1],[15,2],[15,1],[15,1],[15,1],[11,4],[9,2],[17,2],[17,1],[26,5],[26,2],[19,3],[19,1],[30,1],[30,1],[31,4],[31,3],[28,3],[28,1],[34,1],[21,1],[21,1],[21,1],[21,1],[21,1],[32,1]],
37
+ performAction: function anonymous(yytext,yyleng,yylineno,yy,yystate,$$,_$) {
38
+
39
+ var $0 = $$.length - 1;
40
+ switch (yystate) {
41
+ case 1: return new yy.DocumentNode( $$[$0-1] )
42
+ break;
43
+ case 2: return new yy.DocumentNode( [ ] )
44
+ break;
45
+ case 3: this.$ = $$[$0]
46
+ break;
47
+ case 4: $$[$0-1].push( $$[$0] ); this.$ = $$[$0-1]
48
+ break;
49
+ case 5: this.$ = [ $$[$0] ]
50
+ break;
51
+ case 6: this.$ = new yy.BlockNode( $$[$0-2], $$[$0-1], $$[$0] )
52
+ break;
53
+ case 7: this.$ = new yy.SafeNode( $$[$0-1] )
54
+ break;
55
+ case 8: this.$ = $$[$0-1]
56
+ break;
57
+ case 9: this.$ = new yy.ContentNode( $$[$0] )
58
+ break;
59
+ case 10: this.$ = new yy.ExpressionNode( $$[$0-2], new yy.FilterCollection( $$[$0] ) )
60
+ break;
61
+ case 11: this.$ = new yy.ExpressionNode( $$[$0], new yy.FilterCollection( [ ] ) )
62
+ break;
63
+ case 12: this.$ = new yy.PathNode( $$[$0], false )
64
+ break;
65
+ case 13: this.$ = new yy.PathNode( $$[$0], true )
66
+ break;
67
+ case 14: this.$ = new yy.ThisNode( )
68
+ break;
69
+ case 15: this.$ = $$[$0]
70
+ break;
71
+ case 16: this.$ = new yy.JoinedNodeCollection( $$[$0-2] )
72
+ break;
73
+ case 17: this.$ = $$[$0]
74
+ break;
75
+ case 18: $$[$0-1].push( $$[$0] ); this.$ = $$[$0-1]
76
+ break;
77
+ case 19: this.$ = [ $$[$0] ]
78
+ break;
79
+ case 20: this.$ = new yy.FilterNode( $$[$0-3], new yy.NodeCollection( $$[$0-1] ) )
80
+ break;
81
+ case 21: this.$ = new yy.FilterNode( $$[$0], new yy.NodeCollection( [ ] ) )
82
+ break;
83
+ case 22: $$[$0-2].push( $$[$0] ); this.$ = $$[$0-2]
84
+ break;
85
+ case 23: this.$ = [ $$[$0] ]
86
+ break;
87
+ case 24: this.$ = $$[$0]
88
+ break;
89
+ case 25: this.$ = $$[$0]
90
+ break;
91
+ case 26: this.$ = new yy.MethodNode( $$[$0-3], new yy.NodeCollection( $$[$0-1] ) )
92
+ break;
93
+ case 27: this.$ = new yy.MethodNode( $$[$0-2], new yy.NodeCollection( [ ] ) )
94
+ break;
95
+ case 28: $$[$0-2].push( $$[$0] ); this.$ = $$[$0-2]
96
+ break;
97
+ case 29: this.$ = [ $$[$0] ]
98
+ break;
99
+ case 30: this.$ = $$[$0]
100
+ break;
101
+ case 31: this.$ = new yy.PrimitiveNode( $$[$0] )
102
+ break;
103
+ case 32: this.$ = new yy.PrimitiveNode( $$[$0] )
104
+ break;
105
+ case 33: this.$ = new yy.PrimitiveNode( false )
106
+ break;
107
+ case 34: this.$ = new yy.PrimitiveNode( true )
108
+ break;
109
+ case 35: this.$ = new yy.PrimitiveNode( parseFloat( $$[$0] ) )
110
+ break;
111
+ case 36: this.$ = new yy.MemberNode( $$[$0], false )
112
+ break;
113
+ }
114
+ },
115
+ table: [{3:1,4:2,5:[1,3],6:4,7:5,8:[1,6],12:[1,7],14:[1,8]},{1:[3]},{5:[1,9]},{1:[2,2]},{5:[2,3],7:10,8:[1,6],12:[1,7],14:[1,8],23:[2,3]},{5:[2,5],8:[2,5],12:[2,5],14:[2,5],23:[2,5]},{9:11,10:12,15:14,18:[1,15],19:16,20:[1,17],21:18,24:[1,13],25:[1,27],30:19,31:25,32:26,35:[1,20],36:[1,21],37:[1,22],38:[1,23],39:[1,24]},{10:28,15:14,18:[1,15],19:16,20:[1,17],21:18,25:[1,27],30:19,31:25,32:26,35:[1,20],36:[1,21],37:[1,22],38:[1,23],39:[1,24]},{5:[2,9],8:[2,9],12:[2,9],14:[2,9],23:[2,9]},{1:[2,1]},{5:[2,4],8:[2,4],12:[2,4],14:[2,4],23:[2,4]},{10:29,15:14,18:[1,15],19:16,20:[1,17],21:18,25:[1,27],30:19,31:25,32:26,35:[1,20],36:[1,21],37:[1,22],38:[1,23],39:[1,24]},{13:[1,30]},{25:[1,31]},{13:[2,11],16:[1,32],22:[2,11]},{19:33,25:[1,27],30:19,31:25,32:26},{13:[2,13],16:[2,13],20:[1,34],22:[2,13],29:[2,13],33:[2,13]},{13:[2,14],16:[2,14],22:[2,14],29:[2,14],33:[2,14]},{13:[2,15],16:[2,15],22:[2,15],29:[2,15],33:[2,15]},{13:[2,23],16:[2,23],20:[2,23],22:[2,23],29:[2,23],33:[2,23]},{13:[2,31],16:[2,31],22:[2,31],29:[2,31],33:[2,31]},{13:[2,32],16:[2,32],22:[2,32],29:[2,32],33:[2,32]},{13:[2,33],16:[2,33],22:[2,33],29:[2,33],33:[2,33]},{13:[2,34],16:[2,34],22:[2,34],29:[2,34],33:[2,34]},{13:[2,35],16:[2,35],22:[2,35],29:[2,35],33:[2,35]},{13:[2,24],16:[2,24],20:[2,24],22:[2,24],29:[2,24],33:[2,24]},{13:[2,25],16:[2,25],20:[2,25],22:[2,25],29:[2,25],33:[2,25]},{13:[2,36],16:[2,36],20:[2,36],22:[2,36],27:[1,35],29:[2,36],33:[2,36]},{13:[1,36]},{11:37,22:[1,38]},{5:[2,8],8:[2,8],12:[2,8],14:[2,8],23:[2,8]},{18:[2,17],20:[2,17],25:[2,17],35:[2,17],36:[2,17],37:[2,17],38:[2,17],39:[2,17]},{17:39,24:[1,41],26:40},{13:[2,12],16:[2,12],20:[1,34],22:[2,12],29:[2,12],33:[2,12]},{25:[1,27],30:42,31:25,32:26},{15:46,18:[1,15],19:16,20:[1,17],21:18,25:[1,27],28:43,29:[1,44],30:19,31:25,32:26,34:45,35:[1,20],36:[1,21],37:[1,22],38:[1,23],39:[1,24]},{5:[2,7],8:[2,7],12:[2,7],14:[2,7],23:[2,7]},{5:[2,6],8:[2,6],12:[2,6],14:[2,6],23:[2,6]},{4:47,6:4,7:5,8:[1,6],12:[1,7],14:[1,8]},{13:[2,10],22:[2,10],24:[1,41],26:48},{13:[2,19],22:[2,19],24:[2,19]},{25:[1,49]},{13:[2,22],16:[2,22],20:[2,22],22:[2,22],29:[2,22],33:[2,22]},{29:[1,50],33:[1,51]},{13:[2,27],16:[2,27],20:[2,27],22:[2,27],29:[2,27],33:[2,27]},{29:[2,29],33:[2,29]},{29:[2,30],33:[2,30]},{23:[1,52]},{13:[2,18],22:[2,18],24:[2,18]},{13:[2,21],22:[2,21],24:[2,21],27:[1,53]},{13:[2,26],16:[2,26],20:[2,26],22:[2,26],29:[2,26],33:[2,26]},{15:46,18:[1,15],19:16,20:[1,17],21:18,25:[1,27],30:19,31:25,32:26,34:54,35:[1,20],36:[1,21],37:[1,22],38:[1,23],39:[1,24]},{13:[1,55]},{15:46,18:[1,15],19:16,20:[1,17],21:18,25:[1,27],28:56,30:19,31:25,32:26,34:45,35:[1,20],36:[1,21],37:[1,22],38:[1,23],39:[1,24]},{29:[2,28],33:[2,28]},{5:[2,16],8:[2,16],12:[2,16],14:[2,16],23:[2,16]},{29:[1,57],33:[1,51]},{13:[2,20],22:[2,20],24:[2,20]}],
116
+ defaultActions: {3:[2,2],9:[2,1]},
117
+ parseError: function parseError(str, hash) {
118
+ throw new Error(str);
119
+ },
120
+ parse: function parse(input) {
121
+ var self = this,
122
+ stack = [0],
123
+ vstack = [null], // semantic value stack
124
+ lstack = [], // location stack
125
+ table = this.table,
126
+ yytext = '',
127
+ yylineno = 0,
128
+ yyleng = 0,
129
+ recovering = 0,
130
+ TERROR = 2,
131
+ EOF = 1;
132
+
133
+ //this.reductionCount = this.shiftCount = 0;
134
+
135
+ this.lexer.setInput(input);
136
+ this.lexer.yy = this.yy;
137
+ this.yy.lexer = this.lexer;
138
+ if (typeof this.lexer.yylloc == 'undefined')
139
+ this.lexer.yylloc = {};
140
+ var yyloc = this.lexer.yylloc;
141
+ lstack.push(yyloc);
142
+
143
+ if (typeof this.yy.parseError === 'function')
144
+ this.parseError = this.yy.parseError;
145
+
146
+ function popStack (n) {
147
+ stack.length = stack.length - 2*n;
148
+ vstack.length = vstack.length - n;
149
+ lstack.length = lstack.length - n;
150
+ }
151
+
152
+ function lex() {
153
+ var token;
154
+ token = self.lexer.lex() || 1; // $end = 1
155
+ // if token isn't its numeric value, convert
156
+ if (typeof token !== 'number') {
157
+ token = self.symbols_[token] || token;
158
+ }
159
+ return token;
160
+ }
161
+
162
+ var symbol, preErrorSymbol, state, action, a, r, yyval={},p,len,newState, expected;
163
+ while (true) {
164
+ // retreive state number from top of stack
165
+ state = stack[stack.length-1];
166
+
167
+ // use default actions if available
168
+ if (this.defaultActions[state]) {
169
+ action = this.defaultActions[state];
170
+ } else {
171
+ if (symbol == null)
172
+ symbol = lex();
173
+ // read action for current state and first input
174
+ action = table[state] && table[state][symbol];
175
+ }
176
+
177
+ // handle parse error
178
+ _handle_error:
179
+ if (typeof action === 'undefined' || !action.length || !action[0]) {
180
+
181
+ if (!recovering) {
182
+ // Report error
183
+ expected = [];
184
+ for (p in table[state]) if (this.terminals_[p] && p > 2) {
185
+ expected.push("'"+this.terminals_[p]+"'");
186
+ }
187
+ var errStr = '';
188
+ if (this.lexer.showPosition) {
189
+ errStr = 'Parse error on line '+(yylineno+1)+":\n"+this.lexer.showPosition()+"\nExpecting "+expected.join(', ') + ", got '" + this.terminals_[symbol]+ "'";
190
+ } else {
191
+ errStr = 'Parse error on line '+(yylineno+1)+": Unexpected " +
192
+ (symbol == 1 /*EOF*/ ? "end of input" :
193
+ ("'"+(this.terminals_[symbol] || symbol)+"'"));
194
+ }
195
+ this.parseError(errStr,
196
+ {text: this.lexer.match, token: this.terminals_[symbol] || symbol, line: this.lexer.yylineno, loc: yyloc, expected: expected});
197
+ }
198
+
199
+ // just recovered from another error
200
+ if (recovering == 3) {
201
+ if (symbol == EOF) {
202
+ throw new Error(errStr || 'Parsing halted.');
203
+ }
204
+
205
+ // discard current lookahead and grab another
206
+ yyleng = this.lexer.yyleng;
207
+ yytext = this.lexer.yytext;
208
+ yylineno = this.lexer.yylineno;
209
+ yyloc = this.lexer.yylloc;
210
+ symbol = lex();
211
+ }
212
+
213
+ // try to recover from error
214
+ while (1) {
215
+ // check for error recovery rule in this state
216
+ if ((TERROR.toString()) in table[state]) {
217
+ break;
218
+ }
219
+ if (state == 0) {
220
+ throw new Error(errStr || 'Parsing halted.');
221
+ }
222
+ popStack(1);
223
+ state = stack[stack.length-1];
224
+ }
225
+
226
+ preErrorSymbol = symbol; // save the lookahead token
227
+ symbol = TERROR; // insert generic error symbol as new lookahead
228
+ state = stack[stack.length-1];
229
+ action = table[state] && table[state][TERROR];
230
+ recovering = 3; // allow 3 real symbols to be shifted before reporting a new error
231
+ }
232
+
233
+ // this shouldn't happen, unless resolve defaults are off
234
+ if (action[0] instanceof Array && action.length > 1) {
235
+ throw new Error('Parse Error: multiple actions possible at state: '+state+', token: '+symbol);
236
+ }
237
+
238
+ switch (action[0]) {
239
+
240
+ case 1: // shift
241
+ //this.shiftCount++;
242
+
243
+ stack.push(symbol);
244
+ vstack.push(this.lexer.yytext);
245
+ lstack.push(this.lexer.yylloc);
246
+ stack.push(action[1]); // push state
247
+ symbol = null;
248
+ if (!preErrorSymbol) { // normal execution/no error
249
+ yyleng = this.lexer.yyleng;
250
+ yytext = this.lexer.yytext;
251
+ yylineno = this.lexer.yylineno;
252
+ yyloc = this.lexer.yylloc;
253
+ if (recovering > 0)
254
+ recovering--;
255
+ } else { // error just occurred, resume old lookahead f/ before error
256
+ symbol = preErrorSymbol;
257
+ preErrorSymbol = null;
258
+ }
259
+ break;
260
+
261
+ case 2: // reduce
262
+ //this.reductionCount++;
263
+
264
+ len = this.productions_[action[1]][1];
265
+
266
+ // perform semantic action
267
+ yyval.$ = vstack[vstack.length-len]; // default to $$ = $1
268
+ // default location, uses first token for firsts, last for lasts
269
+ yyval._$ = {
270
+ first_line: lstack[lstack.length-(len||1)].first_line,
271
+ last_line: lstack[lstack.length-1].last_line,
272
+ first_column: lstack[lstack.length-(len||1)].first_column,
273
+ last_column: lstack[lstack.length-1].last_column
274
+ };
275
+ r = this.performAction.call(yyval, yytext, yyleng, yylineno, this.yy, action[1], vstack, lstack);
276
+
277
+ if (typeof r !== 'undefined') {
278
+ return r;
279
+ }
280
+
281
+ // pop off stack
282
+ if (len) {
283
+ stack = stack.slice(0,-1*len*2);
284
+ vstack = vstack.slice(0, -1*len);
285
+ lstack = lstack.slice(0, -1*len);
286
+ }
287
+
288
+ stack.push(this.productions_[action[1]][0]); // push nonterminal (reduce)
289
+ vstack.push(yyval.$);
290
+ lstack.push(yyval._$);
291
+ // goto new state = table[STATE][NONTERMINAL]
292
+ newState = table[stack[stack.length-2]][stack[stack.length-1]];
293
+ stack.push(newState);
294
+ break;
295
+
296
+ case 3: // accept
297
+ return true;
298
+ }
299
+
300
+ }
301
+
302
+ return true;
303
+ }};
304
+ /* Jison generated lexer */
305
+ var lexer = (function(){
306
+ var lexer = ({EOF:1,
307
+ parseError:function parseError(str, hash) {
308
+ if (this.yy.parseError) {
309
+ this.yy.parseError(str, hash);
310
+ } else {
311
+ throw new Error(str);
312
+ }
313
+ },
314
+ setInput:function (input) {
315
+ this._input = input;
316
+ this._more = this._less = this.done = false;
317
+ this.yylineno = this.yyleng = 0;
318
+ this.yytext = this.matched = this.match = '';
319
+ this.conditionStack = ['INITIAL'];
320
+ this.yylloc = {first_line:1,first_column:0,last_line:1,last_column:0};
321
+ return this;
322
+ },
323
+ input:function () {
324
+ var ch = this._input[0];
325
+ this.yytext+=ch;
326
+ this.yyleng++;
327
+ this.match+=ch;
328
+ this.matched+=ch;
329
+ var lines = ch.match(/\n/);
330
+ if (lines) this.yylineno++;
331
+ this._input = this._input.slice(1);
332
+ return ch;
333
+ },
334
+ unput:function (ch) {
335
+ this._input = ch + this._input;
336
+ return this;
337
+ },
338
+ more:function () {
339
+ this._more = true;
340
+ return this;
341
+ },
342
+ pastInput:function () {
343
+ var past = this.matched.substr(0, this.matched.length - this.match.length);
344
+ return (past.length > 20 ? '...':'') + past.substr(-20).replace(/\n/g, "");
345
+ },
346
+ upcomingInput:function () {
347
+ var next = this.match;
348
+ if (next.length < 20) {
349
+ next += this._input.substr(0, 20-next.length);
350
+ }
351
+ return (next.substr(0,20)+(next.length > 20 ? '...':'')).replace(/\n/g, "");
352
+ },
353
+ showPosition:function () {
354
+ var pre = this.pastInput();
355
+ var c = new Array(pre.length + 1).join("-");
356
+ return pre + this.upcomingInput() + "\n" + c+"^";
357
+ },
358
+ next:function () {
359
+ if (this.done) {
360
+ return this.EOF;
361
+ }
362
+ if (!this._input) this.done = true;
363
+
364
+ var token,
365
+ match,
366
+ tempMatch,
367
+ index,
368
+ col,
369
+ lines;
370
+ if (!this._more) {
371
+ this.yytext = '';
372
+ this.match = '';
373
+ }
374
+ var rules = this._currentRules();
375
+ for (var i=0;i < rules.length; i++) {
376
+ tempMatch = this._input.match(this.rules[rules[i]]);
377
+ if (tempMatch && (!match || tempMatch[0].length > match[0].length)) {
378
+ match = tempMatch;
379
+ index = i;
380
+ if (!this.options.flex) break;
381
+ }
382
+ }
383
+ if (match) {
384
+ lines = match[0].match(/\n.*/g);
385
+ if (lines) this.yylineno += lines.length;
386
+ this.yylloc = {first_line: this.yylloc.last_line,
387
+ last_line: this.yylineno+1,
388
+ first_column: this.yylloc.last_column,
389
+ last_column: lines ? lines[lines.length-1].length-1 : this.yylloc.last_column + match[0].length}
390
+ this.yytext += match[0];
391
+ this.match += match[0];
392
+ this.yyleng = this.yytext.length;
393
+ this._more = false;
394
+ this._input = this._input.slice(match[0].length);
395
+ this.matched += match[0];
396
+ token = this.performAction.call(this, this.yy, this, rules[index],this.conditionStack[this.conditionStack.length-1]);
397
+ if (token) return token;
398
+ else return;
399
+ }
400
+ if (this._input === "") {
401
+ return this.EOF;
402
+ } else {
403
+ this.parseError('Lexical error on line '+(this.yylineno+1)+'. Unrecognized text.\n'+this.showPosition(),
404
+ {text: "", token: null, line: this.yylineno});
405
+ }
406
+ },
407
+ lex:function lex() {
408
+ var r = this.next();
409
+ if (typeof r !== 'undefined') {
410
+ return r;
411
+ } else {
412
+ return this.lex();
413
+ }
414
+ },
415
+ begin:function begin(condition) {
416
+ this.conditionStack.push(condition);
417
+ },
418
+ popState:function popState() {
419
+ return this.conditionStack.pop();
420
+ },
421
+ _currentRules:function _currentRules() {
422
+ return this.conditions[this.conditionStack[this.conditionStack.length-1]].rules;
423
+ },
424
+ topState:function () {
425
+ return this.conditionStack[this.conditionStack.length-2];
426
+ },
427
+ pushState:function begin(condition) {
428
+ this.begin(condition);
429
+ }});
430
+ lexer.options = {};
431
+ lexer.performAction = function anonymous(yy,yy_,$avoiding_name_collisions,YY_START) {
432
+
433
+ var YYSTATE=YY_START
434
+ switch($avoiding_name_collisions) {
435
+ case 0: this.begin( 'mu' ); if( yy_.yytext ) return 14;
436
+ break;
437
+ case 1: return 14;
438
+ break;
439
+ case 2: this.begin( 'INITIAL' ); return 22;
440
+ break;
441
+ case 3: return 23;
442
+ break;
443
+ case 4: return 12;
444
+ break;
445
+ case 5: return 8;
446
+ break;
447
+ case 6: this.begin( 'INITIAL' ); return 13;
448
+ break;
449
+ case 7: return 18;
450
+ break;
451
+ case 8: return 24;
452
+ break;
453
+ case 9: return 16;
454
+ break;
455
+ case 10: return 20;
456
+ break;
457
+ case 11: return 33;
458
+ break;
459
+ case 12: /* ignore whitespace */
460
+ break;
461
+ case 13: yy_.yytext = yy_.yytext.substr( 1, yy_.yyleng - 2 ); return 35;
462
+ break;
463
+ case 14: yy_.yytext = yy_.yytext.substr( 1, yy_.yyleng - 2 ); return 36;
464
+ break;
465
+ case 15: return 27;
466
+ break;
467
+ case 16: return 29;
468
+ break;
469
+ case 17: return 38;
470
+ break;
471
+ case 18: return 37;
472
+ break;
473
+ case 19: return 39;
474
+ break;
475
+ case 20: return 25;
476
+ break;
477
+ case 21: return 5;
478
+ break;
479
+ }
480
+ };
481
+ lexer.rules = [/^[^\x00]*?(?=(\{\{))/,/^[^\x00]+/,/^do\s*\}\}\n*/,/^\{\{\s*end\b/,/^\{\{=/,/^\{\{/,/^\}\}\n*/,/^@/,/^:/,/^\|/,/^\./,/^,/,/^\s+/,/^'[^\']*?'/,/^"[^\"]*?"/,/^\(/,/^\)/,/^true\b/,/^false\b/,/^-?\d+(\.\d+)?/,/^[a-zA-Z0-9\_\$]+/,/^$/];
482
+ lexer.conditions = {"mu":{"rules":[2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21],"inclusive":false},"INITIAL":{"rules":[0,1,21],"inclusive":true}};
483
+ return lexer;})()
484
+ parser.lexer = lexer;
485
+ return parser;
486
+ })();
487
+ if (typeof require !== 'undefined' && typeof exports !== 'undefined') {
488
+ exports.parser = walrus;
489
+ exports.parse = function () { return walrus.parse.apply(walrus, arguments); }
490
+ exports.main = function commonjsMain(args) {
491
+ if (!args[1])
492
+ throw new Error('Usage: '+args[0]+' FILE');
493
+ if (typeof process !== 'undefined') {
494
+ var source = require('fs').readFileSync(require('path').join(process.cwd(), args[1]), "utf8");
495
+ } else {
496
+ var cwd = require("file").path(require("file").cwd());
497
+ var source = cwd.join(args[1]).read({charset: "utf-8"});
498
+ }
499
+ return exports.parser.parse(source);
500
+ }
501
+ if (typeof module !== 'undefined' && require.main === module) {
502
+ exports.main(typeof process !== 'undefined' ? process.argv.slice(1) : require("system").args);
503
+ }
504
+ }
505
+ ;
506
+
507
+ Walrus.i18n = {
508
+ /**
509
+ * the current locale key
510
+ */
511
+ locale: 'en',
512
+ /**
513
+ * looks up the translation at `keypath` for the current locale,
514
+ * optionally interpolating values from `context`
515
+ */
516
+ t: function(keypath, context) {
517
+ var value;
518
+ if (context == null) context = {};
519
+ try {
520
+ value = Walrus.Utils.keypath(keypath, Walrus.i18n[Walrus.i18n.locale]);
521
+ if (typeof value === 'string') {
522
+ return Walrus.Utils.interpolate(value, context);
523
+ } else {
524
+ return value;
525
+ }
526
+ } catch (error) {
527
+ throw new Error("Missing translation: " + Walrus.i18n.locale + "." + keypath);
528
+ }
529
+ },
530
+ /**
531
+ * default en translations
532
+ * TODO this hash should probably be opt-in, either explicitly
533
+ * or by breaking it up and including each portion with its filter bundle
534
+ */
535
+ en: {
536
+ currencies: {
537
+ symbol: '$',
538
+ precision: 2,
539
+ decimal: '.',
540
+ thousand: ','
541
+ },
542
+ dates: {
543
+ full_daynames: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
544
+ abbr_daynames: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
545
+ full_monthnames: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
546
+ abbr_monthnames: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
547
+ am: 'AM',
548
+ pm: 'PM',
549
+ distance_in_words: {
550
+ half_a_minute: 'half a minute',
551
+ less_than_x_seconds: {
552
+ one: 'less than a second',
553
+ other: 'less than %{count} seconds'
554
+ },
555
+ less_than_x_minutes: {
556
+ one: 'less than a minute',
557
+ other: 'less than %{count} minutes'
558
+ },
559
+ x_minutes: {
560
+ one: '1 minute',
561
+ other: '%{count} minutes'
562
+ },
563
+ about_x_hours: {
564
+ one: 'about 1 hour',
565
+ other: 'about %{count} hours'
566
+ },
567
+ x_days: {
568
+ one: '1 day',
569
+ other: '%{count} days'
570
+ },
571
+ about_x_months: {
572
+ one: 'about 1 month',
573
+ other: 'about %{count} months'
574
+ },
575
+ x_months: {
576
+ one: '1 month',
577
+ other: '%{count} months'
578
+ },
579
+ about_x_years: {
580
+ one: 'about 1 year',
581
+ other: 'about %{count} years'
582
+ },
583
+ over_x_years: {
584
+ one: 'over 1 year',
585
+ other: 'over %{count} years'
586
+ },
587
+ almost_x_years: {
588
+ one: 'almost 1 year',
589
+ other: 'almost %{count} years'
590
+ }
591
+ }
592
+ }
593
+ }
594
+ };
595
+
596
+ /**
597
+ * Allow Walrus.Context to use the `t` method
598
+ */
599
+
600
+ Walrus.Context.t = Walrus.i18n.t;
601
+
602
+ Utils = {
603
+ /**
604
+ * trims leading and trailing whitespace
605
+ */
606
+ trim: function(str) {
607
+ return str.replace(/^\s+|\s+$/g, '');
608
+ },
609
+ /**
610
+ * reduces a list into a single result
611
+ */
612
+ reduce: function(array, initial, method) {
613
+ var item, memo, _i, _len;
614
+ memo = initial;
615
+ for (_i = 0, _len = array.length; _i < _len; _i++) {
616
+ item = array[_i];
617
+ memo = method(memo, item);
618
+ }
619
+ return memo;
620
+ },
621
+ /**
622
+ * returns the string representation of `foo`
623
+ */
624
+ toString: function(foo) {
625
+ return Object.prototype.toString.call(foo);
626
+ },
627
+ /**
628
+ * returns whether or not `foo` is an array
629
+ */
630
+ isArray: function(foo) {
631
+ return this.toString(foo) === '[object Array]';
632
+ },
633
+ /**
634
+ * applies all properties from `bar` onto `foo`
635
+ */
636
+ extend: function(foo, bar) {
637
+ var key, value, _results;
638
+ _results = [];
639
+ for (key in bar) {
640
+ value = bar[key];
641
+ _results.push(foo[key] = value);
642
+ }
643
+ return _results;
644
+ },
645
+ /**
646
+ * all of the nasty html characters to escape
647
+ */
648
+ escapees: /[&'"<>]/g,
649
+ escapes: {
650
+ '&': '&amp;',
651
+ "'": '&#x27;',
652
+ '"': '&quot;',
653
+ '<': '&lt;',
654
+ '>': '&gt;'
655
+ },
656
+ /**
657
+ * escapes nasty html characters
658
+ */
659
+ escape: function(value) {
660
+ var _this = this;
661
+ if ((value != null) && (value.replace != null)) {
662
+ return value.replace(this.escapees, function(c) {
663
+ return _this.escapes[c] || c;
664
+ });
665
+ } else {
666
+ return value;
667
+ }
668
+ },
669
+ /**
670
+ * looks up a nested property on an object
671
+ */
672
+ keypath: function(path, object) {
673
+ return this.reduce(path.split('.'), object, function(memo, key) {
674
+ return memo[key];
675
+ });
676
+ },
677
+ /**
678
+ * inserts values into a string
679
+ */
680
+ interpolate: function(string, context) {
681
+ if (context == null) context = {};
682
+ return string.replace(/%{(\w+)}/g, function(match, key) {
683
+ return context[key] || match;
684
+ });
685
+ }
686
+ };
687
+
688
+ Walrus.Utils = Utils;
689
+
690
+ AST = {};
691
+
692
+ /**
693
+ * AST.SafeNode
694
+ * A simple wrapper node to signify safe compilation for the rest of
695
+ * the nodes in the tree.
696
+ */
697
+
698
+ AST.SafeNode = (function() {
699
+
700
+ function SafeNode(node) {
701
+ this.node = node;
702
+ }
703
+
704
+ SafeNode.prototype.compile = function(context, root, safe) {
705
+ return this.node.compile(context, root, true);
706
+ };
707
+
708
+ return SafeNode;
709
+
710
+ })();
711
+
712
+ /**
713
+ * AST.NodeCollection
714
+ * A collection of nodes with the #compile interface, simply compiles
715
+ * each of its nodes and returns the resulting array.
716
+ */
717
+
718
+ AST.NodeCollection = (function() {
719
+
720
+ function NodeCollection(nodes) {
721
+ this.nodes = nodes;
722
+ }
723
+
724
+ NodeCollection.prototype.compile = function(context, root, safe) {
725
+ var node, _i, _len, _ref, _results;
726
+ _ref = this.nodes;
727
+ _results = [];
728
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
729
+ node = _ref[_i];
730
+ _results.push(node.compile(context, root, safe));
731
+ }
732
+ return _results;
733
+ };
734
+
735
+ return NodeCollection;
736
+
737
+ })();
738
+
739
+ /**
740
+ * AST.JoinedNodeCollection
741
+ * Compiles all of its nodes, then joins them.
742
+ */
743
+
744
+ AST.JoinedNodeCollection = (function(_super) {
745
+
746
+ __extends(JoinedNodeCollection, _super);
747
+
748
+ function JoinedNodeCollection(nodes) {
749
+ this.nodes = nodes;
750
+ }
751
+
752
+ JoinedNodeCollection.prototype.compile = function(context, root, safe) {
753
+ return JoinedNodeCollection.__super__.compile.call(this, context, root, safe).join('');
754
+ };
755
+
756
+ return JoinedNodeCollection;
757
+
758
+ })(AST.NodeCollection);
759
+
760
+ /**
761
+ * AST.DocumentNode
762
+ * The root node of the document. Defaults to escaping its content.
763
+ */
764
+
765
+ AST.DocumentNode = (function(_super) {
766
+
767
+ __extends(DocumentNode, _super);
768
+
769
+ function DocumentNode() {
770
+ DocumentNode.__super__.constructor.apply(this, arguments);
771
+ }
772
+
773
+ DocumentNode.prototype.compile = function(context) {
774
+ Walrus.Utils.extend(context, Walrus.Context);
775
+ return DocumentNode.__super__.compile.call(this, context, context, false);
776
+ };
777
+
778
+ return DocumentNode;
779
+
780
+ })(AST.JoinedNodeCollection);
781
+
782
+ /**
783
+ * AST.ContentNode
784
+ * A node with non-mustache content, probably HTML. We simply pass the content through.
785
+ */
786
+
787
+ AST.ContentNode = (function() {
788
+
789
+ function ContentNode(content) {
790
+ this.content = content;
791
+ }
792
+
793
+ ContentNode.prototype.compile = function(context, root, safe) {
794
+ return this.content;
795
+ };
796
+
797
+ return ContentNode;
798
+
799
+ })();
800
+
801
+ /**
802
+ * AST.MemberNode
803
+ * A node that refers to a member of the context. We don't explicitly check that this
804
+ * member exists in case the developer wants to check that in a conditional.
805
+ *
806
+ * `{{member}}`, for instance, will compile to `index[ 'member' ]`.
807
+ */
808
+
809
+ AST.MemberNode = (function() {
810
+
811
+ function MemberNode(path) {
812
+ this.path = path;
813
+ }
814
+
815
+ MemberNode.prototype.compile = function(index, context, root, safe) {
816
+ if (safe) {
817
+ return index[this.path];
818
+ } else {
819
+ return Walrus.Utils.escape(index[this.path]);
820
+ }
821
+ };
822
+
823
+ return MemberNode;
824
+
825
+ })();
826
+
827
+ /**
828
+ * AST.MethodNode
829
+ * A node that refers to a member of the context, specifically a method, and will
830
+ * call that method with any given arguments after they compile. We explicitly
831
+ * check that the method exists to avoid 'foo is not a function' or other cryptic
832
+ * errors.
833
+ *
834
+ * `{{member( )}}`, for instance, will compile to `index[ 'member' ]( )`.
835
+ */
836
+
837
+ AST.MethodNode = (function() {
838
+
839
+ function MethodNode(path, _arguments) {
840
+ this.path = path;
841
+ this.arguments = _arguments;
842
+ }
843
+
844
+ MethodNode.prototype.compile = function(index, context, root, safe) {
845
+ if (index[this.path] == null) {
846
+ throw new Error("Cannot find any method named '" + this.path + "' in " + index + ".");
847
+ }
848
+ return index[this.path].apply(index, this.arguments.compile(context, root, safe));
849
+ };
850
+
851
+ return MethodNode;
852
+
853
+ })();
854
+
855
+ /**
856
+ * AST.ThisNode
857
+ * A node that simply returns the current context to be evaluated. This is most useful
858
+ * during implicit iteration and is denoted with a dot, like `{{.}}`.
859
+ *
860
+ * One example is when you've got an array of primitive types, like strings:
861
+ *
862
+ * var names = [ 'Antonio', 'Ben', 'Curtis' ];
863
+ *
864
+ * {{:each names do}}
865
+ * <li>{{.}}</li>
866
+ * {{end}}
867
+ *
868
+ * A similar use case is when the root view object is an array:
869
+ *
870
+ * var view = [ { name : 'Antonio' }, { name : 'Ben' }, { name : 'Curtis' } ];
871
+ *
872
+ * {{:each . do}}
873
+ * <li>{{name}}</li>
874
+ * {{end}}
875
+ */
876
+
877
+ AST.ThisNode = (function() {
878
+
879
+ function ThisNode() {}
880
+
881
+ ThisNode.prototype.compile = function(context, root, safe) {
882
+ return context;
883
+ };
884
+
885
+ return ThisNode;
886
+
887
+ })();
888
+
889
+ /**
890
+ * AST.PathNode
891
+ * A node that represents an object path. The path segments are typically
892
+ * `AST.MemberNode`s and `AST.MethodNode`s.
893
+ *
894
+ * A `PathNode` may be evaluated in two contexts: the current "local" context
895
+ * and the "root" context. For example, `{{foo.bar.baz}}` will try to evaluate
896
+ * the object path from the current context, while `{{@foo.bar.baz}}` will
897
+ * start back up at the root view object.
898
+ */
899
+
900
+ AST.PathNode = (function() {
901
+
902
+ function PathNode(paths, local) {
903
+ this.paths = paths;
904
+ this.local = local;
905
+ }
906
+
907
+ PathNode.prototype.compile = function(context, root, safe) {
908
+ var scope;
909
+ scope = this.local ? context : root;
910
+ return Walrus.Utils.reduce(this.paths, scope, function(scope, path) {
911
+ return path.compile(scope, context, root, safe);
912
+ });
913
+ };
914
+
915
+ return PathNode;
916
+
917
+ })();
918
+
919
+ /**
920
+ * AST.PrimitiveNode
921
+ * A node whose value is a javascript primitive or literal. Supported
922
+ * primitives are:
923
+ *
924
+ * - Strings with "double quotes"
925
+ * - Strings with 'single quotes'
926
+ * - Numbers, like 45 or 987.654
927
+ * - Booleans, true or false
928
+ *
929
+ * TODO These primitives are currently parsed in the lexing phase. I'm
930
+ * kinda feeling like a bit of that logic should be moved to the AST instead.
931
+ * Perhaps declare the literal type in the lexer and determine the conversion
932
+ * here, or create distinct classes for each primitive type, like `BooleanNode`
933
+ * and `NumberNode`.
934
+ */
935
+
936
+ AST.PrimitiveNode = (function() {
937
+
938
+ function PrimitiveNode(value) {
939
+ this.value = value;
940
+ }
941
+
942
+ PrimitiveNode.prototype.compile = function(context, root, safe) {
943
+ return this.value;
944
+ };
945
+
946
+ return PrimitiveNode;
947
+
948
+ })();
949
+
950
+ /**
951
+ * AST.ExpressionNode
952
+ * An expression is the main part of a mustache. It typically consists of a path,
953
+ * which gets compiled, then passed to any filters to be manipulated further.
954
+ * The subject of an expression may also be a primitive.
955
+ *
956
+ * The breakdown of a single-line mustache is:
957
+ *
958
+ * {{ expression | :filter(s) }}
959
+ *
960
+ * And a block mustache with a helper, like:
961
+ *
962
+ * {{ :helper expression | :filters(s) do }}
963
+ * // block content
964
+ * {{ end }}
965
+ */
966
+
967
+ AST.ExpressionNode = (function() {
968
+
969
+ function ExpressionNode(paths, filters) {
970
+ this.paths = paths;
971
+ this.filters = filters;
972
+ }
973
+
974
+ ExpressionNode.prototype.compile = function(context, root, safe) {
975
+ return this.filters.apply(this.paths.compile(context, root, safe), context, root, safe);
976
+ };
977
+
978
+ return ExpressionNode;
979
+
980
+ })();
981
+
982
+ /**
983
+ * AST.BlockNode
984
+ * A node that contains other statements within a block. `BlockNode`s are denoted
985
+ * by the use of a _:helper_, and the presence of `do`/`end` to signify the start
986
+ * and end of the node's block. It is the helper's responsibility to determine
987
+ * how to compile the block.
988
+ *
989
+ * Will throw an error if the named helper is not defined in `Walrus.Helpers`.
990
+ */
991
+
992
+ AST.BlockNode = (function() {
993
+
994
+ function BlockNode(name, expression, block) {
995
+ this.name = name;
996
+ this.expression = expression;
997
+ this.block = block;
998
+ if (Walrus.Helpers[this.name] == null) {
999
+ throw new Error("Cannot find any helper named '" + this.name + "'.");
1000
+ }
1001
+ }
1002
+
1003
+ BlockNode.prototype.compile = function(context, root, safe) {
1004
+ return Walrus.Helpers[this.name](this.expression, context, root, safe, this.block);
1005
+ };
1006
+
1007
+ return BlockNode;
1008
+
1009
+ })();
1010
+
1011
+ /**
1012
+ * AST.FilterNode
1013
+ * A node that specifies a _filter_ used to post-process the result of the expression.
1014
+ * Filters may also accept arguments, just like methods. These arguments are determined
1015
+ * and handled by the filter itself.
1016
+ *
1017
+ * Will throw an error if the named filter is not defined in `Walrus.Filters`.
1018
+ */
1019
+
1020
+ AST.FilterNode = (function() {
1021
+
1022
+ function FilterNode(name, _arguments) {
1023
+ this.name = name;
1024
+ this.arguments = _arguments;
1025
+ if (Walrus.Filters[this.name] == null) {
1026
+ throw new Error("Cannot find any filter named '" + this.name + "'.");
1027
+ }
1028
+ }
1029
+
1030
+ FilterNode.prototype.apply = function(value, context, root, safe) {
1031
+ var _ref;
1032
+ return (_ref = Walrus.Filters)[this.name].apply(_ref, [value].concat(__slice.call(this.arguments.compile(context, root, safe))));
1033
+ };
1034
+
1035
+ return FilterNode;
1036
+
1037
+ })();
1038
+
1039
+ /**
1040
+ * AST.FilterCollection
1041
+ * A collection of filters. Filters are applied to the expression
1042
+ * in order from left to right.
1043
+ */
1044
+
1045
+ AST.FilterCollection = (function() {
1046
+
1047
+ function FilterCollection(filters) {
1048
+ this.filters = filters;
1049
+ }
1050
+
1051
+ FilterCollection.prototype.apply = function(expression, context, root, safe) {
1052
+ return Walrus.Utils.reduce(this.filters, expression, function(memo, filter) {
1053
+ return filter.apply(memo, context, root, safe);
1054
+ });
1055
+ };
1056
+
1057
+ return FilterCollection;
1058
+
1059
+ })();
1060
+
1061
+ Walrus.AST = AST;
1062
+
1063
+ Walrus.Helpers = {};
1064
+
1065
+ Walrus.addHelper = function(name, fn) {
1066
+ if (this.Helpers[name] != null) {
1067
+ throw "Cannot override existing helper named '" + name + "'.";
1068
+ }
1069
+ return this.Helpers[name] = fn;
1070
+ };
1071
+
1072
+ /**
1073
+ * *:if*
1074
+ * Evaluates a block only if the result of `expression` is truthy. Opposite of `:unless`.
1075
+ *
1076
+ * Usage:
1077
+ *
1078
+ * {{:if expression do}}
1079
+ * // block content
1080
+ * {{end}}
1081
+ */
1082
+
1083
+ Walrus.addHelper('if', function(expression, context, root, safe, block) {
1084
+ if (expression.compile(context, root, safe)) {
1085
+ return block.compile(context, root, safe);
1086
+ } else {
1087
+ return '';
1088
+ }
1089
+ });
1090
+
1091
+ /**
1092
+ * *:unless*
1093
+ * Evaluates a block only if the result of `expression` is falsy. Opposite of `:if`.
1094
+ *
1095
+ * Usage:
1096
+ *
1097
+ * {{:unless expression do}}
1098
+ * // block content
1099
+ * {{end}}
1100
+ */
1101
+
1102
+ Walrus.addHelper('unless', function(expression, context, root, safe, block) {
1103
+ if (!expression.compile(context, root, safe)) {
1104
+ return block.compile(context, root, safe);
1105
+ } else {
1106
+ return '';
1107
+ }
1108
+ });
1109
+
1110
+ /**
1111
+ * *:each*
1112
+ * Iterates over the array returned by `expression` and evaluates the block
1113
+ * for each member of the array. The compiled blocks are then joined.
1114
+ */
1115
+
1116
+ Walrus.addHelper('each', function(expression, context, root, safe, block) {
1117
+ var array, index, item, items;
1118
+ array = expression.compile(context, root, safe);
1119
+ if (!Walrus.Utils.isArray(array)) array = [array];
1120
+ items = (function() {
1121
+ var _len, _results;
1122
+ _results = [];
1123
+ for (index = 0, _len = array.length; index < _len; index++) {
1124
+ item = array[index];
1125
+ item['$index'] = index;
1126
+ item['$parent'] = context;
1127
+ item['$length'] = array.length;
1128
+ _results.push(block.compile(item, root, safe));
1129
+ }
1130
+ return _results;
1131
+ })();
1132
+ return items.join('');
1133
+ });
1134
+
1135
+ /**
1136
+ * *:with*
1137
+ * Changes the local context of the block to the result of `expression`.
1138
+ *
1139
+ * Usage:
1140
+ *
1141
+ * {{:with expression do}}
1142
+ * <p>{{name}}</p>
1143
+ * {{end}}
1144
+ */
1145
+
1146
+ Walrus.addHelper('with', function(expression, context, root, safe, block) {
1147
+ var subcontext;
1148
+ subcontext = expression.compile(context, root, safe);
1149
+ subcontext['$parent'] = context;
1150
+ return block.compile(subcontext, root, safe);
1151
+ });
1152
+
1153
+ Walrus.Filters = {};
1154
+
1155
+ Walrus.addFilter = function(name, fn) {
1156
+ if (this.Filters[name] != null) {
1157
+ throw "Cannot override existing filter named '" + name + "'.";
1158
+ }
1159
+ return this.Filters[name] = fn;
1160
+ };
1161
+
1162
+ /**
1163
+ * Create a namespace for all of our domain methods
1164
+ */
1165
+
1166
+ Walrus.Domain = {};
1167
+
1168
+ /**
1169
+ * *:as*
1170
+ * Decorates a view object or collection of view objects with
1171
+ * custom domain methods.
1172
+ *
1173
+ * Parameters:
1174
+ * name - The key for the object on `Walrus.Domain` to decorate with
1175
+ */
1176
+
1177
+ Walrus.addFilter('as', function(value, name) {
1178
+ var item, _i, _len;
1179
+ if (Walrus.Utils.isArray(value)) {
1180
+ for (_i = 0, _len = value.length; _i < _len; _i++) {
1181
+ item = value[_i];
1182
+ Walrus.Utils.extend(item, Walrus.Domain[name]);
1183
+ }
1184
+ } else {
1185
+ Walrus.Utils.extend(value, Walrus.Domain[name]);
1186
+ }
1187
+ return value;
1188
+ });
1189
+
1190
+ /**
1191
+ * *:equals*
1192
+ * Returns whether the expression is strictly equal to the given value.
1193
+ *
1194
+ * Parameters:
1195
+ * foo - the value to compare to the expression
1196
+ *
1197
+ * Usage:
1198
+ *
1199
+ * {{ :if "foo" | :equals( "bar" ) do }}
1200
+ * // block will not be evaluated
1201
+ * {{ end }}
1202
+ */
1203
+
1204
+ Walrus.addFilter('equals', function(value, foo) {
1205
+ return value === foo;
1206
+ });
1207
+
1208
+ /**
1209
+ * *:if*
1210
+ * Returns the expression if _condition_ is truthy, or nothing if _condition_ is falsy.
1211
+ *
1212
+ * Parameters:
1213
+ *
1214
+ * condition - the condition to test against
1215
+ *
1216
+ * Usage:
1217
+ *
1218
+ * {{ 'active' | :if( true ) }} // => "active"
1219
+ */
1220
+
1221
+ Walrus.addFilter('if', function(value, condition) {
1222
+ if (condition) {
1223
+ return value;
1224
+ } else {
1225
+ return '';
1226
+ }
1227
+ });
1228
+
1229
+ /**
1230
+ * *:unless*
1231
+ * Returns the expression if _condition_ is falsy, or nothing if _condition_ is truthy.
1232
+ *
1233
+ * Parameters:
1234
+ *
1235
+ * condition - the condition to test against
1236
+ *
1237
+ * Usage:
1238
+ *
1239
+ * {{ 'active' | :unless( true ) }} // => ""
1240
+ */
1241
+
1242
+ Walrus.addFilter('unless', function(value, condition) {
1243
+ if (!condition) {
1244
+ return value;
1245
+ } else {
1246
+ return '';
1247
+ }
1248
+ });
1249
+
1250
+ /**
1251
+ * *:or*
1252
+ * Returns the result of the expression if it is truthy, the given value if not.
1253
+ *
1254
+ * Parameters:
1255
+ * foo - the value to default to if the expression is falsy.
1256
+ *
1257
+ * Usage:
1258
+ *
1259
+ * {{ false | :or( "Not Specified" ) }} // => "Not Specified"
1260
+ */
1261
+
1262
+ Walrus.addFilter('or', function(value, foo) {
1263
+ return value || foo;
1264
+ });
1265
+
1266
+ /**
1267
+ * *:log*
1268
+ * Logs whatever you want to the console if `console.log` is available.
1269
+ * Helpful for debugging your view object especially if your console
1270
+ * supports object inspection.
1271
+ *
1272
+ * Parameters: any
1273
+ *
1274
+ * Usage:
1275
+ *
1276
+ * {{ @root | :log( 'wtf' ) }} // => Console logs: [object Object], 'wtf'
1277
+ */
1278
+
1279
+ Walrus.addFilter('log', function() {
1280
+ if ((typeof console !== "undefined" && console !== null) && (console.log != null)) {
1281
+ return console.log.apply(console, ['[Walrus]'].concat(__slice.call(arguments)));
1282
+ }
1283
+ });
1284
+
1285
+ /**
1286
+ * Setup
1287
+ */
1288
+
1289
+ Walrus.Parser = {
1290
+ parser: walrus,
1291
+ parse: function() {
1292
+ return walrus.parse.apply(walrus, arguments);
1293
+ }
1294
+ };
1295
+
1296
+ Walrus.Parser.parser.yy = Walrus.AST;
1297
+
1298
+ /**
1299
+ * Export
1300
+ */
1301
+
1302
+ (typeof exports !== "undefined" && exports !== null ? exports : this).Walrus = Walrus;
1303
+
1304
+ }).call(this);