walrus-rb 0.10.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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);