ember-rails 0.5.0 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,5 @@
1
+ <%= application_name.camelize %>.Store = DS.Store.extend({
2
+ revision: 4,
3
+ adapter: DS.RESTAdapter.create()
4
+ });
5
+
@@ -1,3 +1,5 @@
1
1
  <h1><%= class_name %></h1>
2
2
 
3
- <p>Your content here.</p>
3
+ <p>Your content here.</p>
4
+
5
+ {{outlet}}
@@ -1,4 +1,3 @@
1
1
  <%= application_name.camelize %>.<%= class_name.camelize %>View = Ember.View.extend({
2
- templateName: '<%= controller_name.camelize(:lower) %>/<%= class_name.underscore %>',
3
- controller: <%= application_name.camelize %>.<%= controller_name.camelize(:lower) %>Controller
4
- });
2
+ templateName: '<%= class_name.underscore %>'
3
+ });
@@ -1073,7 +1073,7 @@ DS.Store = Ember.Object.extend({
1073
1073
 
1074
1074
  // create a new instance of the model type in the
1075
1075
  // 'isLoading' state
1076
- record = this.materializeRecord(type, clientId);
1076
+ record = this.materializeRecord(type, clientId, id);
1077
1077
 
1078
1078
  // let the adapter set the data, possibly async
1079
1079
  var adapter = get(this, '_adapter');
@@ -1578,12 +1578,13 @@ DS.Store = Ember.Object.extend({
1578
1578
  // . RECORD MATERIALIZATION .
1579
1579
  // ..........................
1580
1580
 
1581
- materializeRecord: function(type, clientId) {
1581
+ materializeRecord: function(type, clientId, id) {
1582
1582
  var record;
1583
1583
 
1584
1584
  get(this, 'recordCache')[clientId] = record = type._create({
1585
1585
  store: this,
1586
- clientId: clientId
1586
+ clientId: clientId,
1587
+ _id: id
1587
1588
  });
1588
1589
 
1589
1590
  get(this, 'defaultTransaction').adoptRecord(record);
@@ -2642,7 +2643,8 @@ DS.Model = Ember.Object.extend(Ember.Evented, {
2642
2643
  return value;
2643
2644
  }
2644
2645
 
2645
- return data && get(data, primaryKey);
2646
+ var id = get(data, primaryKey);
2647
+ return id ? id : this._id;
2646
2648
  }).property('primaryKey', 'data'),
2647
2649
 
2648
2650
  // The following methods are callbacks invoked by `toJSON`. You
@@ -0,0 +1,229 @@
1
+ // lib/handlebars/base.js
2
+
3
+ /*jshint eqnull:true*/
4
+ this.Handlebars = {};
5
+
6
+ (function() {
7
+
8
+ Handlebars.VERSION = "1.0.rc.1";
9
+
10
+ Handlebars.helpers = {};
11
+ Handlebars.partials = {};
12
+
13
+ Handlebars.registerHelper = function(name, fn, inverse) {
14
+ if(inverse) { fn.not = inverse; }
15
+ this.helpers[name] = fn;
16
+ };
17
+
18
+ Handlebars.registerPartial = function(name, str) {
19
+ this.partials[name] = str;
20
+ };
21
+
22
+ Handlebars.registerHelper('helperMissing', function(arg) {
23
+ if(arguments.length === 2) {
24
+ return undefined;
25
+ } else {
26
+ throw new Error("Could not find property '" + arg + "'");
27
+ }
28
+ });
29
+
30
+ var toString = Object.prototype.toString, functionType = "[object Function]";
31
+
32
+ Handlebars.registerHelper('blockHelperMissing', function(context, options) {
33
+ var inverse = options.inverse || function() {}, fn = options.fn;
34
+
35
+
36
+ var ret = "";
37
+ var type = toString.call(context);
38
+
39
+ if(type === functionType) { context = context.call(this); }
40
+
41
+ if(context === true) {
42
+ return fn(this);
43
+ } else if(context === false || context == null) {
44
+ return inverse(this);
45
+ } else if(type === "[object Array]") {
46
+ if(context.length > 0) {
47
+ for(var i=0, j=context.length; i<j; i++) {
48
+ ret = ret + fn(context[i]);
49
+ }
50
+ } else {
51
+ ret = inverse(this);
52
+ }
53
+ return ret;
54
+ } else {
55
+ return fn(context);
56
+ }
57
+ });
58
+
59
+ Handlebars.registerHelper('each', function(context, options) {
60
+ var fn = options.fn, inverse = options.inverse;
61
+ var ret = "";
62
+
63
+ if(context && context.length > 0) {
64
+ for(var i=0, j=context.length; i<j; i++) {
65
+ ret = ret + fn(context[i]);
66
+ }
67
+ } else {
68
+ ret = inverse(this);
69
+ }
70
+ return ret;
71
+ });
72
+
73
+ Handlebars.registerHelper('if', function(context, options) {
74
+ var type = toString.call(context);
75
+ if(type === functionType) { context = context.call(this); }
76
+
77
+ if(!context || Handlebars.Utils.isEmpty(context)) {
78
+ return options.inverse(this);
79
+ } else {
80
+ return options.fn(this);
81
+ }
82
+ });
83
+
84
+ Handlebars.registerHelper('unless', function(context, options) {
85
+ var fn = options.fn, inverse = options.inverse;
86
+ options.fn = inverse;
87
+ options.inverse = fn;
88
+
89
+ return Handlebars.helpers['if'].call(this, context, options);
90
+ });
91
+
92
+ Handlebars.registerHelper('with', function(context, options) {
93
+ return options.fn(context);
94
+ });
95
+
96
+ Handlebars.registerHelper('log', function(context) {
97
+ Handlebars.log(context);
98
+ });
99
+
100
+ }());
101
+ ;
102
+ // lib/handlebars/utils.js
103
+ Handlebars.Exception = function(message) {
104
+ var tmp = Error.prototype.constructor.apply(this, arguments);
105
+
106
+ for (var p in tmp) {
107
+ if (tmp.hasOwnProperty(p)) { this[p] = tmp[p]; }
108
+ }
109
+
110
+ this.message = tmp.message;
111
+ };
112
+ Handlebars.Exception.prototype = new Error();
113
+
114
+ // Build out our basic SafeString type
115
+ Handlebars.SafeString = function(string) {
116
+ this.string = string;
117
+ };
118
+ Handlebars.SafeString.prototype.toString = function() {
119
+ return this.string.toString();
120
+ };
121
+
122
+ (function() {
123
+ var escape = {
124
+ "<": "&lt;",
125
+ ">": "&gt;",
126
+ '"': "&quot;",
127
+ "'": "&#x27;",
128
+ "`": "&#x60;"
129
+ };
130
+
131
+ var badChars = /&(?!\w+;)|[<>"'`]/g;
132
+ var possible = /[&<>"'`]/;
133
+
134
+ var escapeChar = function(chr) {
135
+ return escape[chr] || "&amp;";
136
+ };
137
+
138
+ Handlebars.Utils = {
139
+ escapeExpression: function(string) {
140
+ // don't escape SafeStrings, since they're already safe
141
+ if (string instanceof Handlebars.SafeString) {
142
+ return string.toString();
143
+ } else if (string == null || string === false) {
144
+ return "";
145
+ }
146
+
147
+ if(!possible.test(string)) { return string; }
148
+ return string.replace(badChars, escapeChar);
149
+ },
150
+
151
+ isEmpty: function(value) {
152
+ if (typeof value === "undefined") {
153
+ return true;
154
+ } else if (value === null) {
155
+ return true;
156
+ } else if (value === false) {
157
+ return true;
158
+ } else if(Object.prototype.toString.call(value) === "[object Array]" && value.length === 0) {
159
+ return true;
160
+ } else {
161
+ return false;
162
+ }
163
+ }
164
+ };
165
+ })();;
166
+ // lib/handlebars/runtime.js
167
+ Handlebars.VM = {
168
+ template: function(templateSpec) {
169
+ // Just add water
170
+ var container = {
171
+ escapeExpression: Handlebars.Utils.escapeExpression,
172
+ invokePartial: Handlebars.VM.invokePartial,
173
+ programs: [],
174
+ program: function(i, fn, data) {
175
+ var programWrapper = this.programs[i];
176
+ if(data) {
177
+ return Handlebars.VM.program(fn, data);
178
+ } else if(programWrapper) {
179
+ return programWrapper;
180
+ } else {
181
+ programWrapper = this.programs[i] = Handlebars.VM.program(fn);
182
+ return programWrapper;
183
+ }
184
+ },
185
+ programWithDepth: Handlebars.VM.programWithDepth,
186
+ noop: Handlebars.VM.noop
187
+ };
188
+
189
+ return function(context, options) {
190
+ options = options || {};
191
+ return templateSpec.call(container, Handlebars, context, options.helpers, options.partials, options.data);
192
+ };
193
+ },
194
+
195
+ programWithDepth: function(fn, data, $depth) {
196
+ var args = Array.prototype.slice.call(arguments, 2);
197
+
198
+ return function(context, options) {
199
+ options = options || {};
200
+
201
+ return fn.apply(this, [context, options.data || data].concat(args));
202
+ };
203
+ },
204
+ program: function(fn, data) {
205
+ return function(context, options) {
206
+ options = options || {};
207
+
208
+ return fn(context, options.data || data);
209
+ };
210
+ },
211
+ noop: function() { return ""; },
212
+ invokePartial: function(partial, name, context, helpers, partials, data) {
213
+ var options = { helpers: helpers, partials: partials, data: data };
214
+
215
+ if(partial === undefined) {
216
+ throw new Handlebars.Exception("The partial " + name + " could not be found");
217
+ } else if(partial instanceof Function) {
218
+ return partial(context, options);
219
+ } else if (!Handlebars.compile) {
220
+ throw new Handlebars.Exception("The partial " + name + " could not be compiled when running in runtime-only mode");
221
+ } else {
222
+ partials[name] = Handlebars.compile(partial);
223
+ return partials[name](context, options);
224
+ }
225
+ }
226
+ };
227
+
228
+ Handlebars.template = Handlebars.VM.template;
229
+ ;
@@ -0,0 +1,1895 @@
1
+ // lib/handlebars/base.js
2
+
3
+ /*jshint eqnull:true*/
4
+ this.Handlebars = {};
5
+
6
+ (function() {
7
+
8
+ Handlebars.VERSION = "1.0.rc.1";
9
+
10
+ Handlebars.helpers = {};
11
+ Handlebars.partials = {};
12
+
13
+ Handlebars.registerHelper = function(name, fn, inverse) {
14
+ if(inverse) { fn.not = inverse; }
15
+ this.helpers[name] = fn;
16
+ };
17
+
18
+ Handlebars.registerPartial = function(name, str) {
19
+ this.partials[name] = str;
20
+ };
21
+
22
+ Handlebars.registerHelper('helperMissing', function(arg) {
23
+ if(arguments.length === 2) {
24
+ return undefined;
25
+ } else {
26
+ throw new Error("Could not find property '" + arg + "'");
27
+ }
28
+ });
29
+
30
+ var toString = Object.prototype.toString, functionType = "[object Function]";
31
+
32
+ Handlebars.registerHelper('blockHelperMissing', function(context, options) {
33
+ var inverse = options.inverse || function() {}, fn = options.fn;
34
+
35
+
36
+ var ret = "";
37
+ var type = toString.call(context);
38
+
39
+ if(type === functionType) { context = context.call(this); }
40
+
41
+ if(context === true) {
42
+ return fn(this);
43
+ } else if(context === false || context == null) {
44
+ return inverse(this);
45
+ } else if(type === "[object Array]") {
46
+ if(context.length > 0) {
47
+ for(var i=0, j=context.length; i<j; i++) {
48
+ ret = ret + fn(context[i]);
49
+ }
50
+ } else {
51
+ ret = inverse(this);
52
+ }
53
+ return ret;
54
+ } else {
55
+ return fn(context);
56
+ }
57
+ });
58
+
59
+ Handlebars.registerHelper('each', function(context, options) {
60
+ var fn = options.fn, inverse = options.inverse;
61
+ var ret = "";
62
+
63
+ if(context && context.length > 0) {
64
+ for(var i=0, j=context.length; i<j; i++) {
65
+ ret = ret + fn(context[i]);
66
+ }
67
+ } else {
68
+ ret = inverse(this);
69
+ }
70
+ return ret;
71
+ });
72
+
73
+ Handlebars.registerHelper('if', function(context, options) {
74
+ var type = toString.call(context);
75
+ if(type === functionType) { context = context.call(this); }
76
+
77
+ if(!context || Handlebars.Utils.isEmpty(context)) {
78
+ return options.inverse(this);
79
+ } else {
80
+ return options.fn(this);
81
+ }
82
+ });
83
+
84
+ Handlebars.registerHelper('unless', function(context, options) {
85
+ var fn = options.fn, inverse = options.inverse;
86
+ options.fn = inverse;
87
+ options.inverse = fn;
88
+
89
+ return Handlebars.helpers['if'].call(this, context, options);
90
+ });
91
+
92
+ Handlebars.registerHelper('with', function(context, options) {
93
+ return options.fn(context);
94
+ });
95
+
96
+ Handlebars.registerHelper('log', function(context) {
97
+ Handlebars.log(context);
98
+ });
99
+
100
+ }());
101
+ ;
102
+ // lib/handlebars/compiler/parser.js
103
+ /* Jison generated parser */
104
+ var handlebars = (function(){
105
+
106
+ var parser = {trace: function trace() { },
107
+ yy: {},
108
+ symbols_: {"error":2,"root":3,"program":4,"EOF":5,"statements":6,"simpleInverse":7,"statement":8,"openInverse":9,"closeBlock":10,"openBlock":11,"mustache":12,"partial":13,"CONTENT":14,"COMMENT":15,"OPEN_BLOCK":16,"inMustache":17,"CLOSE":18,"OPEN_INVERSE":19,"OPEN_ENDBLOCK":20,"path":21,"OPEN":22,"OPEN_UNESCAPED":23,"OPEN_PARTIAL":24,"params":25,"hash":26,"param":27,"STRING":28,"INTEGER":29,"BOOLEAN":30,"hashSegments":31,"hashSegment":32,"ID":33,"EQUALS":34,"pathSegments":35,"SEP":36,"$accept":0,"$end":1},
109
+ terminals_: {2:"error",5:"EOF",14:"CONTENT",15:"COMMENT",16:"OPEN_BLOCK",18:"CLOSE",19:"OPEN_INVERSE",20:"OPEN_ENDBLOCK",22:"OPEN",23:"OPEN_UNESCAPED",24:"OPEN_PARTIAL",28:"STRING",29:"INTEGER",30:"BOOLEAN",33:"ID",34:"EQUALS",36:"SEP"},
110
+ productions_: [0,[3,2],[4,3],[4,1],[4,0],[6,1],[6,2],[8,3],[8,3],[8,1],[8,1],[8,1],[8,1],[11,3],[9,3],[10,3],[12,3],[12,3],[13,3],[13,4],[7,2],[17,3],[17,2],[17,2],[17,1],[25,2],[25,1],[27,1],[27,1],[27,1],[27,1],[26,1],[31,2],[31,1],[32,3],[32,3],[32,3],[32,3],[21,1],[35,3],[35,1]],
111
+ performAction: function anonymous(yytext,yyleng,yylineno,yy,yystate,$$,_$) {
112
+
113
+ var $0 = $$.length - 1;
114
+ switch (yystate) {
115
+ case 1: return $$[$0-1];
116
+ break;
117
+ case 2: this.$ = new yy.ProgramNode($$[$0-2], $$[$0]);
118
+ break;
119
+ case 3: this.$ = new yy.ProgramNode($$[$0]);
120
+ break;
121
+ case 4: this.$ = new yy.ProgramNode([]);
122
+ break;
123
+ case 5: this.$ = [$$[$0]];
124
+ break;
125
+ case 6: $$[$0-1].push($$[$0]); this.$ = $$[$0-1];
126
+ break;
127
+ case 7: this.$ = new yy.BlockNode($$[$0-2], $$[$0-1].inverse, $$[$0-1], $$[$0]);
128
+ break;
129
+ case 8: this.$ = new yy.BlockNode($$[$0-2], $$[$0-1], $$[$0-1].inverse, $$[$0]);
130
+ break;
131
+ case 9: this.$ = $$[$0];
132
+ break;
133
+ case 10: this.$ = $$[$0];
134
+ break;
135
+ case 11: this.$ = new yy.ContentNode($$[$0]);
136
+ break;
137
+ case 12: this.$ = new yy.CommentNode($$[$0]);
138
+ break;
139
+ case 13: this.$ = new yy.MustacheNode($$[$0-1][0], $$[$0-1][1]);
140
+ break;
141
+ case 14: this.$ = new yy.MustacheNode($$[$0-1][0], $$[$0-1][1]);
142
+ break;
143
+ case 15: this.$ = $$[$0-1];
144
+ break;
145
+ case 16: this.$ = new yy.MustacheNode($$[$0-1][0], $$[$0-1][1]);
146
+ break;
147
+ case 17: this.$ = new yy.MustacheNode($$[$0-1][0], $$[$0-1][1], true);
148
+ break;
149
+ case 18: this.$ = new yy.PartialNode($$[$0-1]);
150
+ break;
151
+ case 19: this.$ = new yy.PartialNode($$[$0-2], $$[$0-1]);
152
+ break;
153
+ case 20:
154
+ break;
155
+ case 21: this.$ = [[$$[$0-2]].concat($$[$0-1]), $$[$0]];
156
+ break;
157
+ case 22: this.$ = [[$$[$0-1]].concat($$[$0]), null];
158
+ break;
159
+ case 23: this.$ = [[$$[$0-1]], $$[$0]];
160
+ break;
161
+ case 24: this.$ = [[$$[$0]], null];
162
+ break;
163
+ case 25: $$[$0-1].push($$[$0]); this.$ = $$[$0-1];
164
+ break;
165
+ case 26: this.$ = [$$[$0]];
166
+ break;
167
+ case 27: this.$ = $$[$0];
168
+ break;
169
+ case 28: this.$ = new yy.StringNode($$[$0]);
170
+ break;
171
+ case 29: this.$ = new yy.IntegerNode($$[$0]);
172
+ break;
173
+ case 30: this.$ = new yy.BooleanNode($$[$0]);
174
+ break;
175
+ case 31: this.$ = new yy.HashNode($$[$0]);
176
+ break;
177
+ case 32: $$[$0-1].push($$[$0]); this.$ = $$[$0-1];
178
+ break;
179
+ case 33: this.$ = [$$[$0]];
180
+ break;
181
+ case 34: this.$ = [$$[$0-2], $$[$0]];
182
+ break;
183
+ case 35: this.$ = [$$[$0-2], new yy.StringNode($$[$0])];
184
+ break;
185
+ case 36: this.$ = [$$[$0-2], new yy.IntegerNode($$[$0])];
186
+ break;
187
+ case 37: this.$ = [$$[$0-2], new yy.BooleanNode($$[$0])];
188
+ break;
189
+ case 38: this.$ = new yy.IdNode($$[$0]);
190
+ break;
191
+ case 39: $$[$0-2].push($$[$0]); this.$ = $$[$0-2];
192
+ break;
193
+ case 40: this.$ = [$$[$0]];
194
+ break;
195
+ }
196
+ },
197
+ table: [{3:1,4:2,5:[2,4],6:3,8:4,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,11],22:[1,13],23:[1,14],24:[1,15]},{1:[3]},{5:[1,16]},{5:[2,3],7:17,8:18,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,19],20:[2,3],22:[1,13],23:[1,14],24:[1,15]},{5:[2,5],14:[2,5],15:[2,5],16:[2,5],19:[2,5],20:[2,5],22:[2,5],23:[2,5],24:[2,5]},{4:20,6:3,8:4,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,11],20:[2,4],22:[1,13],23:[1,14],24:[1,15]},{4:21,6:3,8:4,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,11],20:[2,4],22:[1,13],23:[1,14],24:[1,15]},{5:[2,9],14:[2,9],15:[2,9],16:[2,9],19:[2,9],20:[2,9],22:[2,9],23:[2,9],24:[2,9]},{5:[2,10],14:[2,10],15:[2,10],16:[2,10],19:[2,10],20:[2,10],22:[2,10],23:[2,10],24:[2,10]},{5:[2,11],14:[2,11],15:[2,11],16:[2,11],19:[2,11],20:[2,11],22:[2,11],23:[2,11],24:[2,11]},{5:[2,12],14:[2,12],15:[2,12],16:[2,12],19:[2,12],20:[2,12],22:[2,12],23:[2,12],24:[2,12]},{17:22,21:23,33:[1,25],35:24},{17:26,21:23,33:[1,25],35:24},{17:27,21:23,33:[1,25],35:24},{17:28,21:23,33:[1,25],35:24},{21:29,33:[1,25],35:24},{1:[2,1]},{6:30,8:4,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,11],22:[1,13],23:[1,14],24:[1,15]},{5:[2,6],14:[2,6],15:[2,6],16:[2,6],19:[2,6],20:[2,6],22:[2,6],23:[2,6],24:[2,6]},{17:22,18:[1,31],21:23,33:[1,25],35:24},{10:32,20:[1,33]},{10:34,20:[1,33]},{18:[1,35]},{18:[2,24],21:40,25:36,26:37,27:38,28:[1,41],29:[1,42],30:[1,43],31:39,32:44,33:[1,45],35:24},{18:[2,38],28:[2,38],29:[2,38],30:[2,38],33:[2,38],36:[1,46]},{18:[2,40],28:[2,40],29:[2,40],30:[2,40],33:[2,40],36:[2,40]},{18:[1,47]},{18:[1,48]},{18:[1,49]},{18:[1,50],21:51,33:[1,25],35:24},{5:[2,2],8:18,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,11],20:[2,2],22:[1,13],23:[1,14],24:[1,15]},{14:[2,20],15:[2,20],16:[2,20],19:[2,20],22:[2,20],23:[2,20],24:[2,20]},{5:[2,7],14:[2,7],15:[2,7],16:[2,7],19:[2,7],20:[2,7],22:[2,7],23:[2,7],24:[2,7]},{21:52,33:[1,25],35:24},{5:[2,8],14:[2,8],15:[2,8],16:[2,8],19:[2,8],20:[2,8],22:[2,8],23:[2,8],24:[2,8]},{14:[2,14],15:[2,14],16:[2,14],19:[2,14],20:[2,14],22:[2,14],23:[2,14],24:[2,14]},{18:[2,22],21:40,26:53,27:54,28:[1,41],29:[1,42],30:[1,43],31:39,32:44,33:[1,45],35:24},{18:[2,23]},{18:[2,26],28:[2,26],29:[2,26],30:[2,26],33:[2,26]},{18:[2,31],32:55,33:[1,56]},{18:[2,27],28:[2,27],29:[2,27],30:[2,27],33:[2,27]},{18:[2,28],28:[2,28],29:[2,28],30:[2,28],33:[2,28]},{18:[2,29],28:[2,29],29:[2,29],30:[2,29],33:[2,29]},{18:[2,30],28:[2,30],29:[2,30],30:[2,30],33:[2,30]},{18:[2,33],33:[2,33]},{18:[2,40],28:[2,40],29:[2,40],30:[2,40],33:[2,40],34:[1,57],36:[2,40]},{33:[1,58]},{14:[2,13],15:[2,13],16:[2,13],19:[2,13],20:[2,13],22:[2,13],23:[2,13],24:[2,13]},{5:[2,16],14:[2,16],15:[2,16],16:[2,16],19:[2,16],20:[2,16],22:[2,16],23:[2,16],24:[2,16]},{5:[2,17],14:[2,17],15:[2,17],16:[2,17],19:[2,17],20:[2,17],22:[2,17],23:[2,17],24:[2,17]},{5:[2,18],14:[2,18],15:[2,18],16:[2,18],19:[2,18],20:[2,18],22:[2,18],23:[2,18],24:[2,18]},{18:[1,59]},{18:[1,60]},{18:[2,21]},{18:[2,25],28:[2,25],29:[2,25],30:[2,25],33:[2,25]},{18:[2,32],33:[2,32]},{34:[1,57]},{21:61,28:[1,62],29:[1,63],30:[1,64],33:[1,25],35:24},{18:[2,39],28:[2,39],29:[2,39],30:[2,39],33:[2,39],36:[2,39]},{5:[2,19],14:[2,19],15:[2,19],16:[2,19],19:[2,19],20:[2,19],22:[2,19],23:[2,19],24:[2,19]},{5:[2,15],14:[2,15],15:[2,15],16:[2,15],19:[2,15],20:[2,15],22:[2,15],23:[2,15],24:[2,15]},{18:[2,34],33:[2,34]},{18:[2,35],33:[2,35]},{18:[2,36],33:[2,36]},{18:[2,37],33:[2,37]}],
198
+ defaultActions: {16:[2,1],37:[2,23],53:[2,21]},
199
+ parseError: function parseError(str, hash) {
200
+ throw new Error(str);
201
+ },
202
+ parse: function parse(input) {
203
+ var self = this,
204
+ stack = [0],
205
+ vstack = [null], // semantic value stack
206
+ lstack = [], // location stack
207
+ table = this.table,
208
+ yytext = '',
209
+ yylineno = 0,
210
+ yyleng = 0,
211
+ recovering = 0,
212
+ TERROR = 2,
213
+ EOF = 1;
214
+
215
+ //this.reductionCount = this.shiftCount = 0;
216
+
217
+ this.lexer.setInput(input);
218
+ this.lexer.yy = this.yy;
219
+ this.yy.lexer = this.lexer;
220
+ if (typeof this.lexer.yylloc == 'undefined')
221
+ this.lexer.yylloc = {};
222
+ var yyloc = this.lexer.yylloc;
223
+ lstack.push(yyloc);
224
+
225
+ if (typeof this.yy.parseError === 'function')
226
+ this.parseError = this.yy.parseError;
227
+
228
+ function popStack (n) {
229
+ stack.length = stack.length - 2*n;
230
+ vstack.length = vstack.length - n;
231
+ lstack.length = lstack.length - n;
232
+ }
233
+
234
+ function lex() {
235
+ var token;
236
+ token = self.lexer.lex() || 1; // $end = 1
237
+ // if token isn't its numeric value, convert
238
+ if (typeof token !== 'number') {
239
+ token = self.symbols_[token] || token;
240
+ }
241
+ return token;
242
+ }
243
+
244
+ var symbol, preErrorSymbol, state, action, a, r, yyval={},p,len,newState, expected;
245
+ while (true) {
246
+ // retreive state number from top of stack
247
+ state = stack[stack.length-1];
248
+
249
+ // use default actions if available
250
+ if (this.defaultActions[state]) {
251
+ action = this.defaultActions[state];
252
+ } else {
253
+ if (symbol == null)
254
+ symbol = lex();
255
+ // read action for current state and first input
256
+ action = table[state] && table[state][symbol];
257
+ }
258
+
259
+ // handle parse error
260
+ _handle_error:
261
+ if (typeof action === 'undefined' || !action.length || !action[0]) {
262
+
263
+ if (!recovering) {
264
+ // Report error
265
+ expected = [];
266
+ for (p in table[state]) if (this.terminals_[p] && p > 2) {
267
+ expected.push("'"+this.terminals_[p]+"'");
268
+ }
269
+ var errStr = '';
270
+ if (this.lexer.showPosition) {
271
+ errStr = 'Parse error on line '+(yylineno+1)+":\n"+this.lexer.showPosition()+"\nExpecting "+expected.join(', ') + ", got '" + this.terminals_[symbol]+ "'";
272
+ } else {
273
+ errStr = 'Parse error on line '+(yylineno+1)+": Unexpected " +
274
+ (symbol == 1 /*EOF*/ ? "end of input" :
275
+ ("'"+(this.terminals_[symbol] || symbol)+"'"));
276
+ }
277
+ this.parseError(errStr,
278
+ {text: this.lexer.match, token: this.terminals_[symbol] || symbol, line: this.lexer.yylineno, loc: yyloc, expected: expected});
279
+ }
280
+
281
+ // just recovered from another error
282
+ if (recovering == 3) {
283
+ if (symbol == EOF) {
284
+ throw new Error(errStr || 'Parsing halted.');
285
+ }
286
+
287
+ // discard current lookahead and grab another
288
+ yyleng = this.lexer.yyleng;
289
+ yytext = this.lexer.yytext;
290
+ yylineno = this.lexer.yylineno;
291
+ yyloc = this.lexer.yylloc;
292
+ symbol = lex();
293
+ }
294
+
295
+ // try to recover from error
296
+ while (1) {
297
+ // check for error recovery rule in this state
298
+ if ((TERROR.toString()) in table[state]) {
299
+ break;
300
+ }
301
+ if (state == 0) {
302
+ throw new Error(errStr || 'Parsing halted.');
303
+ }
304
+ popStack(1);
305
+ state = stack[stack.length-1];
306
+ }
307
+
308
+ preErrorSymbol = symbol; // save the lookahead token
309
+ symbol = TERROR; // insert generic error symbol as new lookahead
310
+ state = stack[stack.length-1];
311
+ action = table[state] && table[state][TERROR];
312
+ recovering = 3; // allow 3 real symbols to be shifted before reporting a new error
313
+ }
314
+
315
+ // this shouldn't happen, unless resolve defaults are off
316
+ if (action[0] instanceof Array && action.length > 1) {
317
+ throw new Error('Parse Error: multiple actions possible at state: '+state+', token: '+symbol);
318
+ }
319
+
320
+ switch (action[0]) {
321
+
322
+ case 1: // shift
323
+ //this.shiftCount++;
324
+
325
+ stack.push(symbol);
326
+ vstack.push(this.lexer.yytext);
327
+ lstack.push(this.lexer.yylloc);
328
+ stack.push(action[1]); // push state
329
+ symbol = null;
330
+ if (!preErrorSymbol) { // normal execution/no error
331
+ yyleng = this.lexer.yyleng;
332
+ yytext = this.lexer.yytext;
333
+ yylineno = this.lexer.yylineno;
334
+ yyloc = this.lexer.yylloc;
335
+ if (recovering > 0)
336
+ recovering--;
337
+ } else { // error just occurred, resume old lookahead f/ before error
338
+ symbol = preErrorSymbol;
339
+ preErrorSymbol = null;
340
+ }
341
+ break;
342
+
343
+ case 2: // reduce
344
+ //this.reductionCount++;
345
+
346
+ len = this.productions_[action[1]][1];
347
+
348
+ // perform semantic action
349
+ yyval.$ = vstack[vstack.length-len]; // default to $$ = $1
350
+ // default location, uses first token for firsts, last for lasts
351
+ yyval._$ = {
352
+ first_line: lstack[lstack.length-(len||1)].first_line,
353
+ last_line: lstack[lstack.length-1].last_line,
354
+ first_column: lstack[lstack.length-(len||1)].first_column,
355
+ last_column: lstack[lstack.length-1].last_column
356
+ };
357
+ r = this.performAction.call(yyval, yytext, yyleng, yylineno, this.yy, action[1], vstack, lstack);
358
+
359
+ if (typeof r !== 'undefined') {
360
+ return r;
361
+ }
362
+
363
+ // pop off stack
364
+ if (len) {
365
+ stack = stack.slice(0,-1*len*2);
366
+ vstack = vstack.slice(0, -1*len);
367
+ lstack = lstack.slice(0, -1*len);
368
+ }
369
+
370
+ stack.push(this.productions_[action[1]][0]); // push nonterminal (reduce)
371
+ vstack.push(yyval.$);
372
+ lstack.push(yyval._$);
373
+ // goto new state = table[STATE][NONTERMINAL]
374
+ newState = table[stack[stack.length-2]][stack[stack.length-1]];
375
+ stack.push(newState);
376
+ break;
377
+
378
+ case 3: // accept
379
+ return true;
380
+ }
381
+
382
+ }
383
+
384
+ return true;
385
+ }};/* Jison generated lexer */
386
+ var lexer = (function(){
387
+
388
+ var lexer = ({EOF:1,
389
+ parseError:function parseError(str, hash) {
390
+ if (this.yy.parseError) {
391
+ this.yy.parseError(str, hash);
392
+ } else {
393
+ throw new Error(str);
394
+ }
395
+ },
396
+ setInput:function (input) {
397
+ this._input = input;
398
+ this._more = this._less = this.done = false;
399
+ this.yylineno = this.yyleng = 0;
400
+ this.yytext = this.matched = this.match = '';
401
+ this.conditionStack = ['INITIAL'];
402
+ this.yylloc = {first_line:1,first_column:0,last_line:1,last_column:0};
403
+ return this;
404
+ },
405
+ input:function () {
406
+ var ch = this._input[0];
407
+ this.yytext+=ch;
408
+ this.yyleng++;
409
+ this.match+=ch;
410
+ this.matched+=ch;
411
+ var lines = ch.match(/\n/);
412
+ if (lines) this.yylineno++;
413
+ this._input = this._input.slice(1);
414
+ return ch;
415
+ },
416
+ unput:function (ch) {
417
+ this._input = ch + this._input;
418
+ return this;
419
+ },
420
+ more:function () {
421
+ this._more = true;
422
+ return this;
423
+ },
424
+ pastInput:function () {
425
+ var past = this.matched.substr(0, this.matched.length - this.match.length);
426
+ return (past.length > 20 ? '...':'') + past.substr(-20).replace(/\n/g, "");
427
+ },
428
+ upcomingInput:function () {
429
+ var next = this.match;
430
+ if (next.length < 20) {
431
+ next += this._input.substr(0, 20-next.length);
432
+ }
433
+ return (next.substr(0,20)+(next.length > 20 ? '...':'')).replace(/\n/g, "");
434
+ },
435
+ showPosition:function () {
436
+ var pre = this.pastInput();
437
+ var c = new Array(pre.length + 1).join("-");
438
+ return pre + this.upcomingInput() + "\n" + c+"^";
439
+ },
440
+ next:function () {
441
+ if (this.done) {
442
+ return this.EOF;
443
+ }
444
+ if (!this._input) this.done = true;
445
+
446
+ var token,
447
+ match,
448
+ col,
449
+ lines;
450
+ if (!this._more) {
451
+ this.yytext = '';
452
+ this.match = '';
453
+ }
454
+ var rules = this._currentRules();
455
+ for (var i=0;i < rules.length; i++) {
456
+ match = this._input.match(this.rules[rules[i]]);
457
+ if (match) {
458
+ lines = match[0].match(/\n.*/g);
459
+ if (lines) this.yylineno += lines.length;
460
+ this.yylloc = {first_line: this.yylloc.last_line,
461
+ last_line: this.yylineno+1,
462
+ first_column: this.yylloc.last_column,
463
+ last_column: lines ? lines[lines.length-1].length-1 : this.yylloc.last_column + match[0].length}
464
+ this.yytext += match[0];
465
+ this.match += match[0];
466
+ this.matches = match;
467
+ this.yyleng = this.yytext.length;
468
+ this._more = false;
469
+ this._input = this._input.slice(match[0].length);
470
+ this.matched += match[0];
471
+ token = this.performAction.call(this, this.yy, this, rules[i],this.conditionStack[this.conditionStack.length-1]);
472
+ if (token) return token;
473
+ else return;
474
+ }
475
+ }
476
+ if (this._input === "") {
477
+ return this.EOF;
478
+ } else {
479
+ this.parseError('Lexical error on line '+(this.yylineno+1)+'. Unrecognized text.\n'+this.showPosition(),
480
+ {text: "", token: null, line: this.yylineno});
481
+ }
482
+ },
483
+ lex:function lex() {
484
+ var r = this.next();
485
+ if (typeof r !== 'undefined') {
486
+ return r;
487
+ } else {
488
+ return this.lex();
489
+ }
490
+ },
491
+ begin:function begin(condition) {
492
+ this.conditionStack.push(condition);
493
+ },
494
+ popState:function popState() {
495
+ return this.conditionStack.pop();
496
+ },
497
+ _currentRules:function _currentRules() {
498
+ return this.conditions[this.conditionStack[this.conditionStack.length-1]].rules;
499
+ },
500
+ topState:function () {
501
+ return this.conditionStack[this.conditionStack.length-2];
502
+ },
503
+ pushState:function begin(condition) {
504
+ this.begin(condition);
505
+ }});
506
+ lexer.performAction = function anonymous(yy,yy_,$avoiding_name_collisions,YY_START) {
507
+
508
+ var YYSTATE=YY_START
509
+ switch($avoiding_name_collisions) {
510
+ case 0:
511
+ if(yy_.yytext.slice(-1) !== "\\") this.begin("mu");
512
+ if(yy_.yytext.slice(-1) === "\\") yy_.yytext = yy_.yytext.substr(0,yy_.yyleng-1), this.begin("emu");
513
+ if(yy_.yytext) return 14;
514
+
515
+ break;
516
+ case 1: return 14;
517
+ break;
518
+ case 2: this.popState(); return 14;
519
+ break;
520
+ case 3: return 24;
521
+ break;
522
+ case 4: return 16;
523
+ break;
524
+ case 5: return 20;
525
+ break;
526
+ case 6: return 19;
527
+ break;
528
+ case 7: return 19;
529
+ break;
530
+ case 8: return 23;
531
+ break;
532
+ case 9: return 23;
533
+ break;
534
+ case 10: yy_.yytext = yy_.yytext.substr(3,yy_.yyleng-5); this.popState(); return 15;
535
+ break;
536
+ case 11: return 22;
537
+ break;
538
+ case 12: return 34;
539
+ break;
540
+ case 13: return 33;
541
+ break;
542
+ case 14: return 33;
543
+ break;
544
+ case 15: return 36;
545
+ break;
546
+ case 16: /*ignore whitespace*/
547
+ break;
548
+ case 17: this.popState(); return 18;
549
+ break;
550
+ case 18: this.popState(); return 18;
551
+ break;
552
+ case 19: yy_.yytext = yy_.yytext.substr(1,yy_.yyleng-2).replace(/\\"/g,'"'); return 28;
553
+ break;
554
+ case 20: return 30;
555
+ break;
556
+ case 21: return 30;
557
+ break;
558
+ case 22: return 29;
559
+ break;
560
+ case 23: return 33;
561
+ break;
562
+ case 24: yy_.yytext = yy_.yytext.substr(1, yy_.yyleng-2); return 33;
563
+ break;
564
+ case 25: return 'INVALID';
565
+ break;
566
+ case 26: return 5;
567
+ break;
568
+ }
569
+ };
570
+ lexer.rules = [/^[^\x00]*?(?=(\{\{))/,/^[^\x00]+/,/^[^\x00]{2,}?(?=(\{\{))/,/^\{\{>/,/^\{\{#/,/^\{\{\//,/^\{\{\^/,/^\{\{\s*else\b/,/^\{\{\{/,/^\{\{&/,/^\{\{![\s\S]*?\}\}/,/^\{\{/,/^=/,/^\.(?=[} ])/,/^\.\./,/^[\/.]/,/^\s+/,/^\}\}\}/,/^\}\}/,/^"(\\["]|[^"])*"/,/^true(?=[}\s])/,/^false(?=[}\s])/,/^[0-9]+(?=[}\s])/,/^[a-zA-Z0-9_$-]+(?=[=}\s\/.])/,/^\[[^\]]*\]/,/^./,/^$/];
571
+ lexer.conditions = {"mu":{"rules":[3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26],"inclusive":false},"emu":{"rules":[2],"inclusive":false},"INITIAL":{"rules":[0,1,26],"inclusive":true}};return lexer;})()
572
+ parser.lexer = lexer;
573
+ return parser;
574
+ })();
575
+ if (typeof require !== 'undefined' && typeof exports !== 'undefined') {
576
+ exports.parser = handlebars;
577
+ exports.parse = function () { return handlebars.parse.apply(handlebars, arguments); }
578
+ exports.main = function commonjsMain(args) {
579
+ if (!args[1])
580
+ throw new Error('Usage: '+args[0]+' FILE');
581
+ if (typeof process !== 'undefined') {
582
+ var source = require('fs').readFileSync(require('path').join(process.cwd(), args[1]), "utf8");
583
+ } else {
584
+ var cwd = require("file").path(require("file").cwd());
585
+ var source = cwd.join(args[1]).read({charset: "utf-8"});
586
+ }
587
+ return exports.parser.parse(source);
588
+ }
589
+ if (typeof module !== 'undefined' && require.main === module) {
590
+ exports.main(typeof process !== 'undefined' ? process.argv.slice(1) : require("system").args);
591
+ }
592
+ };
593
+ ;
594
+ // lib/handlebars/compiler/base.js
595
+ Handlebars.Parser = handlebars;
596
+
597
+ Handlebars.parse = function(string) {
598
+ Handlebars.Parser.yy = Handlebars.AST;
599
+ return Handlebars.Parser.parse(string);
600
+ };
601
+
602
+ Handlebars.print = function(ast) {
603
+ return new Handlebars.PrintVisitor().accept(ast);
604
+ };
605
+
606
+ Handlebars.logger = {
607
+ DEBUG: 0, INFO: 1, WARN: 2, ERROR: 3, level: 3,
608
+
609
+ // override in the host environment
610
+ log: function(level, str) {}
611
+ };
612
+
613
+ Handlebars.log = function(level, str) { Handlebars.logger.log(level, str); };
614
+ ;
615
+ // lib/handlebars/compiler/ast.js
616
+ (function() {
617
+
618
+ Handlebars.AST = {};
619
+
620
+ Handlebars.AST.ProgramNode = function(statements, inverse) {
621
+ this.type = "program";
622
+ this.statements = statements;
623
+ if(inverse) { this.inverse = new Handlebars.AST.ProgramNode(inverse); }
624
+ };
625
+
626
+ Handlebars.AST.MustacheNode = function(rawParams, hash, unescaped) {
627
+ this.type = "mustache";
628
+ this.escaped = !unescaped;
629
+ this.hash = hash;
630
+
631
+ var id = this.id = rawParams[0];
632
+ var params = this.params = rawParams.slice(1);
633
+
634
+ // a mustache is an eligible helper if:
635
+ // * its id is simple (a single part, not `this` or `..`)
636
+ var eligibleHelper = this.eligibleHelper = id.isSimple;
637
+
638
+ // a mustache is definitely a helper if:
639
+ // * it is an eligible helper, and
640
+ // * it has at least one parameter or hash segment
641
+ this.isHelper = eligibleHelper && (params.length || hash);
642
+
643
+ // if a mustache is an eligible helper but not a definite
644
+ // helper, it is ambiguous, and will be resolved in a later
645
+ // pass or at runtime.
646
+ };
647
+
648
+ Handlebars.AST.PartialNode = function(id, context) {
649
+ this.type = "partial";
650
+
651
+ // TODO: disallow complex IDs
652
+
653
+ this.id = id;
654
+ this.context = context;
655
+ };
656
+
657
+ var verifyMatch = function(open, close) {
658
+ if(open.original !== close.original) {
659
+ throw new Handlebars.Exception(open.original + " doesn't match " + close.original);
660
+ }
661
+ };
662
+
663
+ Handlebars.AST.BlockNode = function(mustache, program, inverse, close) {
664
+ verifyMatch(mustache.id, close);
665
+ this.type = "block";
666
+ this.mustache = mustache;
667
+ this.program = program;
668
+ this.inverse = inverse;
669
+
670
+ if (this.inverse && !this.program) {
671
+ this.isInverse = true;
672
+ }
673
+ };
674
+
675
+ Handlebars.AST.ContentNode = function(string) {
676
+ this.type = "content";
677
+ this.string = string;
678
+ };
679
+
680
+ Handlebars.AST.HashNode = function(pairs) {
681
+ this.type = "hash";
682
+ this.pairs = pairs;
683
+ };
684
+
685
+ Handlebars.AST.IdNode = function(parts) {
686
+ this.type = "ID";
687
+ this.original = parts.join(".");
688
+
689
+ var dig = [], depth = 0;
690
+
691
+ for(var i=0,l=parts.length; i<l; i++) {
692
+ var part = parts[i];
693
+
694
+ if(part === "..") { depth++; }
695
+ else if(part === "." || part === "this") { this.isScoped = true; }
696
+ else { dig.push(part); }
697
+ }
698
+
699
+ this.parts = dig;
700
+ this.string = dig.join('.');
701
+ this.depth = depth;
702
+
703
+ // an ID is simple if it only has one part, and that part is not
704
+ // `..` or `this`.
705
+ this.isSimple = parts.length === 1 && !this.isScoped && depth === 0;
706
+ };
707
+
708
+ Handlebars.AST.StringNode = function(string) {
709
+ this.type = "STRING";
710
+ this.string = string;
711
+ };
712
+
713
+ Handlebars.AST.IntegerNode = function(integer) {
714
+ this.type = "INTEGER";
715
+ this.integer = integer;
716
+ };
717
+
718
+ Handlebars.AST.BooleanNode = function(bool) {
719
+ this.type = "BOOLEAN";
720
+ this.bool = bool;
721
+ };
722
+
723
+ Handlebars.AST.CommentNode = function(comment) {
724
+ this.type = "comment";
725
+ this.comment = comment;
726
+ };
727
+
728
+ })();;
729
+ // lib/handlebars/utils.js
730
+ Handlebars.Exception = function(message) {
731
+ var tmp = Error.prototype.constructor.apply(this, arguments);
732
+
733
+ for (var p in tmp) {
734
+ if (tmp.hasOwnProperty(p)) { this[p] = tmp[p]; }
735
+ }
736
+
737
+ this.message = tmp.message;
738
+ };
739
+ Handlebars.Exception.prototype = new Error();
740
+
741
+ // Build out our basic SafeString type
742
+ Handlebars.SafeString = function(string) {
743
+ this.string = string;
744
+ };
745
+ Handlebars.SafeString.prototype.toString = function() {
746
+ return this.string.toString();
747
+ };
748
+
749
+ (function() {
750
+ var escape = {
751
+ "<": "&lt;",
752
+ ">": "&gt;",
753
+ '"': "&quot;",
754
+ "'": "&#x27;",
755
+ "`": "&#x60;"
756
+ };
757
+
758
+ var badChars = /&(?!\w+;)|[<>"'`]/g;
759
+ var possible = /[&<>"'`]/;
760
+
761
+ var escapeChar = function(chr) {
762
+ return escape[chr] || "&amp;";
763
+ };
764
+
765
+ Handlebars.Utils = {
766
+ escapeExpression: function(string) {
767
+ // don't escape SafeStrings, since they're already safe
768
+ if (string instanceof Handlebars.SafeString) {
769
+ return string.toString();
770
+ } else if (string == null || string === false) {
771
+ return "";
772
+ }
773
+
774
+ if(!possible.test(string)) { return string; }
775
+ return string.replace(badChars, escapeChar);
776
+ },
777
+
778
+ isEmpty: function(value) {
779
+ if (typeof value === "undefined") {
780
+ return true;
781
+ } else if (value === null) {
782
+ return true;
783
+ } else if (value === false) {
784
+ return true;
785
+ } else if(Object.prototype.toString.call(value) === "[object Array]" && value.length === 0) {
786
+ return true;
787
+ } else {
788
+ return false;
789
+ }
790
+ }
791
+ };
792
+ })();;
793
+ // lib/handlebars/compiler/compiler.js
794
+
795
+ /*jshint eqnull:true*/
796
+ Handlebars.Compiler = function() {};
797
+ Handlebars.JavaScriptCompiler = function() {};
798
+
799
+ (function(Compiler, JavaScriptCompiler) {
800
+ // the foundHelper register will disambiguate helper lookup from finding a
801
+ // function in a context. This is necessary for mustache compatibility, which
802
+ // requires that context functions in blocks are evaluated by blockHelperMissing,
803
+ // and then proceed as if the resulting value was provided to blockHelperMissing.
804
+
805
+ Compiler.prototype = {
806
+ compiler: Compiler,
807
+
808
+ disassemble: function() {
809
+ var opcodes = this.opcodes, opcode, out = [], params, param;
810
+
811
+ for (var i=0, l=opcodes.length; i<l; i++) {
812
+ opcode = opcodes[i];
813
+
814
+ if (opcode.opcode === 'DECLARE') {
815
+ out.push("DECLARE " + opcode.name + "=" + opcode.value);
816
+ } else {
817
+ params = [];
818
+ for (var j=0; j<opcode.args.length; j++) {
819
+ param = opcode.args[j];
820
+ if (typeof param === "string") {
821
+ param = "\"" + param.replace("\n", "\\n") + "\"";
822
+ }
823
+ params.push(param);
824
+ }
825
+ out.push(opcode.opcode + " " + params.join(" "));
826
+ }
827
+ }
828
+
829
+ return out.join("\n");
830
+ },
831
+
832
+ guid: 0,
833
+
834
+ compile: function(program, options) {
835
+ this.children = [];
836
+ this.depths = {list: []};
837
+ this.options = options;
838
+
839
+ // These changes will propagate to the other compiler components
840
+ var knownHelpers = this.options.knownHelpers;
841
+ this.options.knownHelpers = {
842
+ 'helperMissing': true,
843
+ 'blockHelperMissing': true,
844
+ 'each': true,
845
+ 'if': true,
846
+ 'unless': true,
847
+ 'with': true,
848
+ 'log': true
849
+ };
850
+ if (knownHelpers) {
851
+ for (var name in knownHelpers) {
852
+ this.options.knownHelpers[name] = knownHelpers[name];
853
+ }
854
+ }
855
+
856
+ return this.program(program);
857
+ },
858
+
859
+ accept: function(node) {
860
+ return this[node.type](node);
861
+ },
862
+
863
+ program: function(program) {
864
+ var statements = program.statements, statement;
865
+ this.opcodes = [];
866
+
867
+ for(var i=0, l=statements.length; i<l; i++) {
868
+ statement = statements[i];
869
+ this[statement.type](statement);
870
+ }
871
+ this.isSimple = l === 1;
872
+
873
+ this.depths.list = this.depths.list.sort(function(a, b) {
874
+ return a - b;
875
+ });
876
+
877
+ return this;
878
+ },
879
+
880
+ compileProgram: function(program) {
881
+ var result = new this.compiler().compile(program, this.options);
882
+ var guid = this.guid++, depth;
883
+
884
+ this.usePartial = this.usePartial || result.usePartial;
885
+
886
+ this.children[guid] = result;
887
+
888
+ for(var i=0, l=result.depths.list.length; i<l; i++) {
889
+ depth = result.depths.list[i];
890
+
891
+ if(depth < 2) { continue; }
892
+ else { this.addDepth(depth - 1); }
893
+ }
894
+
895
+ return guid;
896
+ },
897
+
898
+ block: function(block) {
899
+ var mustache = block.mustache,
900
+ program = block.program,
901
+ inverse = block.inverse;
902
+
903
+ if (program) {
904
+ program = this.compileProgram(program);
905
+ }
906
+
907
+ if (inverse) {
908
+ inverse = this.compileProgram(inverse);
909
+ }
910
+
911
+ var type = this.classifyMustache(mustache);
912
+
913
+ if (type === "helper") {
914
+ this.helperMustache(mustache, program, inverse);
915
+ } else if (type === "simple") {
916
+ this.simpleMustache(mustache);
917
+
918
+ // now that the simple mustache is resolved, we need to
919
+ // evaluate it by executing `blockHelperMissing`
920
+ this.opcode('pushProgram', program);
921
+ this.opcode('pushProgram', inverse);
922
+ this.opcode('pushLiteral', '{}');
923
+ this.opcode('blockValue');
924
+ } else {
925
+ this.ambiguousMustache(mustache, program, inverse);
926
+
927
+ // now that the simple mustache is resolved, we need to
928
+ // evaluate it by executing `blockHelperMissing`
929
+ this.opcode('pushProgram', program);
930
+ this.opcode('pushProgram', inverse);
931
+ this.opcode('pushLiteral', '{}');
932
+ this.opcode('ambiguousBlockValue');
933
+ }
934
+
935
+ this.opcode('append');
936
+ },
937
+
938
+ hash: function(hash) {
939
+ var pairs = hash.pairs, pair, val;
940
+
941
+ this.opcode('push', '{}');
942
+
943
+ for(var i=0, l=pairs.length; i<l; i++) {
944
+ pair = pairs[i];
945
+ val = pair[1];
946
+
947
+ this.accept(val);
948
+ this.opcode('assignToHash', pair[0]);
949
+ }
950
+ },
951
+
952
+ partial: function(partial) {
953
+ var id = partial.id;
954
+ this.usePartial = true;
955
+
956
+ if(partial.context) {
957
+ this.ID(partial.context);
958
+ } else {
959
+ this.opcode('push', 'depth0');
960
+ }
961
+
962
+ this.opcode('invokePartial', id.original);
963
+ this.opcode('append');
964
+ },
965
+
966
+ content: function(content) {
967
+ this.opcode('appendContent', content.string);
968
+ },
969
+
970
+ mustache: function(mustache) {
971
+ var options = this.options;
972
+ var type = this.classifyMustache(mustache);
973
+
974
+ if (type === "simple") {
975
+ this.simpleMustache(mustache);
976
+ } else if (type === "helper") {
977
+ this.helperMustache(mustache);
978
+ } else {
979
+ this.ambiguousMustache(mustache);
980
+ }
981
+
982
+ if(mustache.escaped && !options.noEscape) {
983
+ this.opcode('appendEscaped');
984
+ } else {
985
+ this.opcode('append');
986
+ }
987
+ },
988
+
989
+ ambiguousMustache: function(mustache, program, inverse) {
990
+ var id = mustache.id, name = id.parts[0];
991
+
992
+ this.opcode('getContext', id.depth);
993
+
994
+ this.opcode('pushProgram', program);
995
+ this.opcode('pushProgram', inverse);
996
+
997
+ this.opcode('invokeAmbiguous', name);
998
+ },
999
+
1000
+ simpleMustache: function(mustache, program, inverse) {
1001
+ var id = mustache.id;
1002
+
1003
+ this.addDepth(id.depth);
1004
+ this.opcode('getContext', id.depth);
1005
+
1006
+ if (id.parts.length) {
1007
+ this.opcode('lookupOnContext', id.parts[0]);
1008
+ for(var i=1, l=id.parts.length; i<l; i++) {
1009
+ this.opcode('lookup', id.parts[i]);
1010
+ }
1011
+ } else {
1012
+ this.opcode('pushContext');
1013
+ }
1014
+ this.opcode('resolvePossibleLambda');
1015
+ },
1016
+
1017
+ helperMustache: function(mustache, program, inverse) {
1018
+ var params = this.setupFullMustacheParams(mustache, program, inverse),
1019
+ name = mustache.id.parts[0];
1020
+
1021
+ if (this.options.knownHelpers[name]) {
1022
+ this.opcode('invokeKnownHelper', params.length, name);
1023
+ } else if (this.knownHelpersOnly) {
1024
+ throw new Error("You specified knownHelpersOnly, but used the unknown helper " + name);
1025
+ } else {
1026
+ this.opcode('invokeHelper', params.length, name);
1027
+ }
1028
+ },
1029
+
1030
+ ID: function(id) {
1031
+ this.addDepth(id.depth);
1032
+ this.opcode('getContext', id.depth);
1033
+ this.opcode('lookupOnContext', id.parts[0]);
1034
+
1035
+ for(var i=1, l=id.parts.length; i<l; i++) {
1036
+ this.opcode('lookup', id.parts[i]);
1037
+ }
1038
+ },
1039
+
1040
+ STRING: function(string) {
1041
+ this.opcode('pushString', string.string);
1042
+ },
1043
+
1044
+ INTEGER: function(integer) {
1045
+ this.opcode('pushLiteral', integer.integer);
1046
+ },
1047
+
1048
+ BOOLEAN: function(bool) {
1049
+ this.opcode('pushLiteral', bool.bool);
1050
+ },
1051
+
1052
+ comment: function() {},
1053
+
1054
+ // HELPERS
1055
+ opcode: function(name) {
1056
+ this.opcodes.push({ opcode: name, args: [].slice.call(arguments, 1) });
1057
+ },
1058
+
1059
+ declare: function(name, value) {
1060
+ this.opcodes.push({ opcode: 'DECLARE', name: name, value: value });
1061
+ },
1062
+
1063
+ addDepth: function(depth) {
1064
+ if(depth === 0) { return; }
1065
+
1066
+ if(!this.depths[depth]) {
1067
+ this.depths[depth] = true;
1068
+ this.depths.list.push(depth);
1069
+ }
1070
+ },
1071
+
1072
+ classifyMustache: function(mustache) {
1073
+ var isHelper = mustache.isHelper;
1074
+ var isEligible = mustache.eligibleHelper;
1075
+ var options = this.options;
1076
+
1077
+ // if ambiguous, we can possibly resolve the ambiguity now
1078
+ if (isEligible && !isHelper) {
1079
+ var name = mustache.id.parts[0];
1080
+
1081
+ if (options.knownHelpers[name]) {
1082
+ isHelper = true;
1083
+ } else if (options.knownHelpersOnly) {
1084
+ isEligible = false;
1085
+ }
1086
+ }
1087
+
1088
+ if (isHelper) { return "helper"; }
1089
+ else if (isEligible) { return "ambiguous"; }
1090
+ else { return "simple"; }
1091
+ },
1092
+
1093
+ pushParams: function(params) {
1094
+ var i = params.length, param;
1095
+
1096
+ while(i--) {
1097
+ param = params[i];
1098
+
1099
+ if(this.options.stringParams) {
1100
+ if(param.depth) {
1101
+ this.addDepth(param.depth);
1102
+ }
1103
+
1104
+ this.opcode('getContext', param.depth || 0);
1105
+ this.opcode('pushStringParam', param.string);
1106
+ } else {
1107
+ this[param.type](param);
1108
+ }
1109
+ }
1110
+ },
1111
+
1112
+ setupMustacheParams: function(mustache) {
1113
+ var params = mustache.params;
1114
+ this.pushParams(params);
1115
+
1116
+ if(mustache.hash) {
1117
+ this.hash(mustache.hash);
1118
+ } else {
1119
+ this.opcode('pushLiteral', '{}');
1120
+ }
1121
+
1122
+ return params;
1123
+ },
1124
+
1125
+ // this will replace setupMustacheParams when we're done
1126
+ setupFullMustacheParams: function(mustache, program, inverse) {
1127
+ var params = mustache.params;
1128
+ this.pushParams(params);
1129
+
1130
+ this.opcode('pushProgram', program);
1131
+ this.opcode('pushProgram', inverse);
1132
+
1133
+ if(mustache.hash) {
1134
+ this.hash(mustache.hash);
1135
+ } else {
1136
+ this.opcode('pushLiteral', '{}');
1137
+ }
1138
+
1139
+ return params;
1140
+ }
1141
+ };
1142
+
1143
+ var Literal = function(value) {
1144
+ this.value = value;
1145
+ };
1146
+
1147
+ JavaScriptCompiler.prototype = {
1148
+ // PUBLIC API: You can override these methods in a subclass to provide
1149
+ // alternative compiled forms for name lookup and buffering semantics
1150
+ nameLookup: function(parent, name, type) {
1151
+ if (/^[0-9]+$/.test(name)) {
1152
+ return parent + "[" + name + "]";
1153
+ } else if (JavaScriptCompiler.isValidJavaScriptVariableName(name)) {
1154
+ return parent + "." + name;
1155
+ }
1156
+ else {
1157
+ return parent + "['" + name + "']";
1158
+ }
1159
+ },
1160
+
1161
+ appendToBuffer: function(string) {
1162
+ if (this.environment.isSimple) {
1163
+ return "return " + string + ";";
1164
+ } else {
1165
+ return "buffer += " + string + ";";
1166
+ }
1167
+ },
1168
+
1169
+ initializeBuffer: function() {
1170
+ return this.quotedString("");
1171
+ },
1172
+
1173
+ namespace: "Handlebars",
1174
+ // END PUBLIC API
1175
+
1176
+ compile: function(environment, options, context, asObject) {
1177
+ this.environment = environment;
1178
+ this.options = options || {};
1179
+
1180
+ Handlebars.log(Handlebars.logger.DEBUG, this.environment.disassemble() + "\n\n");
1181
+
1182
+ this.name = this.environment.name;
1183
+ this.isChild = !!context;
1184
+ this.context = context || {
1185
+ programs: [],
1186
+ aliases: { }
1187
+ };
1188
+
1189
+ this.preamble();
1190
+
1191
+ this.stackSlot = 0;
1192
+ this.stackVars = [];
1193
+ this.registers = { list: [] };
1194
+ this.compileStack = [];
1195
+
1196
+ this.compileChildren(environment, options);
1197
+
1198
+ var opcodes = environment.opcodes, opcode;
1199
+
1200
+ this.i = 0;
1201
+
1202
+ for(l=opcodes.length; this.i<l; this.i++) {
1203
+ opcode = opcodes[this.i];
1204
+
1205
+ if(opcode.opcode === 'DECLARE') {
1206
+ this[opcode.name] = opcode.value;
1207
+ } else {
1208
+ this[opcode.opcode].apply(this, opcode.args);
1209
+ }
1210
+ }
1211
+
1212
+ return this.createFunctionContext(asObject);
1213
+ },
1214
+
1215
+ nextOpcode: function() {
1216
+ var opcodes = this.environment.opcodes, opcode = opcodes[this.i + 1];
1217
+ return opcodes[this.i + 1];
1218
+ },
1219
+
1220
+ eat: function(opcode) {
1221
+ this.i = this.i + 1;
1222
+ },
1223
+
1224
+ preamble: function() {
1225
+ var out = [];
1226
+
1227
+ if (!this.isChild) {
1228
+ var namespace = this.namespace;
1229
+ var copies = "helpers = helpers || " + namespace + ".helpers;";
1230
+ if(this.environment.usePartial) { copies = copies + " partials = partials || " + namespace + ".partials;"; }
1231
+ out.push(copies);
1232
+ } else {
1233
+ out.push('');
1234
+ }
1235
+
1236
+ if (!this.environment.isSimple) {
1237
+ out.push(", buffer = " + this.initializeBuffer());
1238
+ } else {
1239
+ out.push("");
1240
+ }
1241
+
1242
+ // track the last context pushed into place to allow skipping the
1243
+ // getContext opcode when it would be a noop
1244
+ this.lastContext = 0;
1245
+ this.source = out;
1246
+ },
1247
+
1248
+ createFunctionContext: function(asObject) {
1249
+ var locals = this.stackVars.concat(this.registers.list);
1250
+
1251
+ if(locals.length > 0) {
1252
+ this.source[1] = this.source[1] + ", " + locals.join(", ");
1253
+ }
1254
+
1255
+ // Generate minimizer alias mappings
1256
+ if (!this.isChild) {
1257
+ var aliases = [];
1258
+ for (var alias in this.context.aliases) {
1259
+ this.source[1] = this.source[1] + ', ' + alias + '=' + this.context.aliases[alias];
1260
+ }
1261
+ }
1262
+
1263
+ if (this.source[1]) {
1264
+ this.source[1] = "var " + this.source[1].substring(2) + ";";
1265
+ }
1266
+
1267
+ // Merge children
1268
+ if (!this.isChild) {
1269
+ this.source[1] += '\n' + this.context.programs.join('\n') + '\n';
1270
+ }
1271
+
1272
+ if (!this.environment.isSimple) {
1273
+ this.source.push("return buffer;");
1274
+ }
1275
+
1276
+ var params = this.isChild ? ["depth0", "data"] : ["Handlebars", "depth0", "helpers", "partials", "data"];
1277
+
1278
+ for(var i=0, l=this.environment.depths.list.length; i<l; i++) {
1279
+ params.push("depth" + this.environment.depths.list[i]);
1280
+ }
1281
+
1282
+ if (asObject) {
1283
+ params.push(this.source.join("\n "));
1284
+
1285
+ return Function.apply(this, params);
1286
+ } else {
1287
+ var functionSource = 'function ' + (this.name || '') + '(' + params.join(',') + ') {\n ' + this.source.join("\n ") + '}';
1288
+ Handlebars.log(Handlebars.logger.DEBUG, functionSource + "\n\n");
1289
+ return functionSource;
1290
+ }
1291
+ },
1292
+
1293
+ // [blockValue]
1294
+ //
1295
+ // On stack, before: hash, inverse, program, value
1296
+ // On stack, after: return value of blockHelperMissing
1297
+ //
1298
+ // The purpose of this opcode is to take a block of the form
1299
+ // `{{#foo}}...{{/foo}}`, resolve the value of `foo`, and
1300
+ // replace it on the stack with the result of properly
1301
+ // invoking blockHelperMissing.
1302
+ blockValue: function() {
1303
+ this.context.aliases.blockHelperMissing = 'helpers.blockHelperMissing';
1304
+
1305
+ var params = ["depth0"];
1306
+ this.setupParams(0, params);
1307
+
1308
+ this.replaceStack(function(current) {
1309
+ params.splice(1, 0, current);
1310
+ return current + " = blockHelperMissing.call(" + params.join(", ") + ")";
1311
+ });
1312
+ },
1313
+
1314
+ // [ambiguousBlockValue]
1315
+ //
1316
+ // On stack, before: hash, inverse, program, value
1317
+ // Compiler value, before: lastHelper=value of last found helper, if any
1318
+ // On stack, after, if no lastHelper: same as [blockValue]
1319
+ // On stack, after, if lastHelper: value
1320
+ ambiguousBlockValue: function() {
1321
+ this.context.aliases.blockHelperMissing = 'helpers.blockHelperMissing';
1322
+
1323
+ var params = ["depth0"];
1324
+ this.setupParams(0, params);
1325
+
1326
+ var current = this.topStack();
1327
+ params.splice(1, 0, current);
1328
+
1329
+ this.source.push("if (!" + this.lastHelper + ") { " + current + " = blockHelperMissing.call(" + params.join(", ") + "); }");
1330
+ },
1331
+
1332
+ // [appendContent]
1333
+ //
1334
+ // On stack, before: ...
1335
+ // On stack, after: ...
1336
+ //
1337
+ // Appends the string value of `content` to the current buffer
1338
+ appendContent: function(content) {
1339
+ this.source.push(this.appendToBuffer(this.quotedString(content)));
1340
+ },
1341
+
1342
+ // [append]
1343
+ //
1344
+ // On stack, before: value, ...
1345
+ // On stack, after: ...
1346
+ //
1347
+ // Coerces `value` to a String and appends it to the current buffer.
1348
+ //
1349
+ // If `value` is truthy, or 0, it is coerced into a string and appended
1350
+ // Otherwise, the empty string is appended
1351
+ append: function() {
1352
+ var local = this.popStack();
1353
+ this.source.push("if(" + local + " || " + local + " === 0) { " + this.appendToBuffer(local) + " }");
1354
+ if (this.environment.isSimple) {
1355
+ this.source.push("else { " + this.appendToBuffer("''") + " }");
1356
+ }
1357
+ },
1358
+
1359
+ // [appendEscaped]
1360
+ //
1361
+ // On stack, before: value, ...
1362
+ // On stack, after: ...
1363
+ //
1364
+ // Escape `value` and append it to the buffer
1365
+ appendEscaped: function() {
1366
+ var opcode = this.nextOpcode(), extra = "";
1367
+ this.context.aliases.escapeExpression = 'this.escapeExpression';
1368
+
1369
+ if(opcode && opcode.opcode === 'appendContent') {
1370
+ extra = " + " + this.quotedString(opcode.args[0]);
1371
+ this.eat(opcode);
1372
+ }
1373
+
1374
+ this.source.push(this.appendToBuffer("escapeExpression(" + this.popStack() + ")" + extra));
1375
+ },
1376
+
1377
+ // [getContext]
1378
+ //
1379
+ // On stack, before: ...
1380
+ // On stack, after: ...
1381
+ // Compiler value, after: lastContext=depth
1382
+ //
1383
+ // Set the value of the `lastContext` compiler value to the depth
1384
+ getContext: function(depth) {
1385
+ if(this.lastContext !== depth) {
1386
+ this.lastContext = depth;
1387
+ }
1388
+ },
1389
+
1390
+ // [lookupOnContext]
1391
+ //
1392
+ // On stack, before: ...
1393
+ // On stack, after: currentContext[name], ...
1394
+ //
1395
+ // Looks up the value of `name` on the current context and pushes
1396
+ // it onto the stack.
1397
+ lookupOnContext: function(name) {
1398
+ this.pushStack(this.nameLookup('depth' + this.lastContext, name, 'context'));
1399
+ },
1400
+
1401
+ // [pushContext]
1402
+ //
1403
+ // On stack, before: ...
1404
+ // On stack, after: currentContext, ...
1405
+ //
1406
+ // Pushes the value of the current context onto the stack.
1407
+ pushContext: function() {
1408
+ this.pushStackLiteral('depth' + this.lastContext);
1409
+ },
1410
+
1411
+ // [resolvePossibleLambda]
1412
+ //
1413
+ // On stack, before: value, ...
1414
+ // On stack, after: resolved value, ...
1415
+ //
1416
+ // If the `value` is a lambda, replace it on the stack by
1417
+ // the return value of the lambda
1418
+ resolvePossibleLambda: function() {
1419
+ this.context.aliases.functionType = '"function"';
1420
+
1421
+ this.replaceStack(function(current) {
1422
+ return "typeof " + current + " === functionType ? " + current + "() : " + current;
1423
+ });
1424
+ },
1425
+
1426
+ // [lookup]
1427
+ //
1428
+ // On stack, before: value, ...
1429
+ // On stack, after: value[name], ...
1430
+ //
1431
+ // Replace the value on the stack with the result of looking
1432
+ // up `name` on `value`
1433
+ lookup: function(name) {
1434
+ this.replaceStack(function(current) {
1435
+ return current + " == null || " + current + " === false ? " + current + " : " + this.nameLookup(current, name, 'context');
1436
+ });
1437
+ },
1438
+
1439
+ // [pushStringParam]
1440
+ //
1441
+ // On stack, before: ...
1442
+ // On stack, after: string, currentContext, ...
1443
+ //
1444
+ // This opcode is designed for use in string mode, which
1445
+ // provides the string value of a parameter along with its
1446
+ // depth rather than resolving it immediately.
1447
+ pushStringParam: function(string) {
1448
+ this.pushStackLiteral('depth' + this.lastContext);
1449
+ this.pushString(string);
1450
+ },
1451
+
1452
+ // [pushString]
1453
+ //
1454
+ // On stack, before: ...
1455
+ // On stack, after: quotedString(string), ...
1456
+ //
1457
+ // Push a quoted version of `string` onto the stack
1458
+ pushString: function(string) {
1459
+ this.pushStackLiteral(this.quotedString(string));
1460
+ },
1461
+
1462
+ // [push]
1463
+ //
1464
+ // On stack, before: ...
1465
+ // On stack, after: expr, ...
1466
+ //
1467
+ // Push an expression onto the stack
1468
+ push: function(expr) {
1469
+ this.pushStack(expr);
1470
+ },
1471
+
1472
+ // [pushLiteral]
1473
+ //
1474
+ // On stack, before: ...
1475
+ // On stack, after: value, ...
1476
+ //
1477
+ // Pushes a value onto the stack. This operation prevents
1478
+ // the compiler from creating a temporary variable to hold
1479
+ // it.
1480
+ pushLiteral: function(value) {
1481
+ this.pushStackLiteral(value);
1482
+ },
1483
+
1484
+ // [pushProgram]
1485
+ //
1486
+ // On stack, before: ...
1487
+ // On stack, after: program(guid), ...
1488
+ //
1489
+ // Push a program expression onto the stack. This takes
1490
+ // a compile-time guid and converts it into a runtime-accessible
1491
+ // expression.
1492
+ pushProgram: function(guid) {
1493
+ if (guid != null) {
1494
+ this.pushStackLiteral(this.programExpression(guid));
1495
+ } else {
1496
+ this.pushStackLiteral(null);
1497
+ }
1498
+ },
1499
+
1500
+ // [invokeHelper]
1501
+ //
1502
+ // On stack, before: hash, inverse, program, params..., ...
1503
+ // On stack, after: result of helper invocation
1504
+ //
1505
+ // Pops off the helper's parameters, invokes the helper,
1506
+ // and pushes the helper's return value onto the stack.
1507
+ //
1508
+ // If the helper is not found, `helperMissing` is called.
1509
+ invokeHelper: function(paramSize, name) {
1510
+ this.context.aliases.helperMissing = 'helpers.helperMissing';
1511
+
1512
+ var helper = this.lastHelper = this.setupHelper(paramSize, name);
1513
+ this.register('foundHelper', helper.name);
1514
+
1515
+ this.pushStack("foundHelper ? foundHelper.call(" +
1516
+ helper.callParams + ") " + ": helperMissing.call(" +
1517
+ helper.helperMissingParams + ")");
1518
+ },
1519
+
1520
+ // [invokeKnownHelper]
1521
+ //
1522
+ // On stack, before: hash, inverse, program, params..., ...
1523
+ // On stack, after: result of helper invocation
1524
+ //
1525
+ // This operation is used when the helper is known to exist,
1526
+ // so a `helperMissing` fallback is not required.
1527
+ invokeKnownHelper: function(paramSize, name) {
1528
+ var helper = this.setupHelper(paramSize, name);
1529
+ this.pushStack(helper.name + ".call(" + helper.callParams + ")");
1530
+ },
1531
+
1532
+ // [invokeAmbiguous]
1533
+ //
1534
+ // On stack, before: hash, inverse, program, params..., ...
1535
+ // On stack, after: result of disambiguation
1536
+ //
1537
+ // This operation is used when an expression like `{{foo}}`
1538
+ // is provided, but we don't know at compile-time whether it
1539
+ // is a helper or a path.
1540
+ //
1541
+ // This operation emits more code than the other options,
1542
+ // and can be avoided by passing the `knownHelpers` and
1543
+ // `knownHelpersOnly` flags at compile-time.
1544
+ invokeAmbiguous: function(name) {
1545
+ this.context.aliases.functionType = '"function"';
1546
+
1547
+ this.pushStackLiteral('{}');
1548
+ var helper = this.setupHelper(0, name);
1549
+
1550
+ var helperName = this.lastHelper = this.nameLookup('helpers', name, 'helper');
1551
+ this.register('foundHelper', helperName);
1552
+
1553
+ var nonHelper = this.nameLookup('depth' + this.lastContext, name, 'context');
1554
+ var nextStack = this.nextStack();
1555
+
1556
+ this.source.push('if (foundHelper) { ' + nextStack + ' = foundHelper.call(' + helper.callParams + '); }');
1557
+ this.source.push('else { ' + nextStack + ' = ' + nonHelper + '; ' + nextStack + ' = typeof ' + nextStack + ' === functionType ? ' + nextStack + '() : ' + nextStack + '; }');
1558
+ },
1559
+
1560
+ // [invokePartial]
1561
+ //
1562
+ // On stack, before: context, ...
1563
+ // On stack after: result of partial invocation
1564
+ //
1565
+ // This operation pops off a context, invokes a partial with that context,
1566
+ // and pushes the result of the invocation back.
1567
+ invokePartial: function(name) {
1568
+ var params = [this.nameLookup('partials', name, 'partial'), "'" + name + "'", this.popStack(), "helpers", "partials"];
1569
+
1570
+ if (this.options.data) {
1571
+ params.push("data");
1572
+ }
1573
+
1574
+ this.context.aliases.self = "this";
1575
+ this.pushStack("self.invokePartial(" + params.join(", ") + ");");
1576
+ },
1577
+
1578
+ // [assignToHash]
1579
+ //
1580
+ // On stack, before: value, hash, ...
1581
+ // On stack, after: hash, ...
1582
+ //
1583
+ // Pops a value and hash off the stack, assigns `hash[key] = value`
1584
+ // and pushes the hash back onto the stack.
1585
+ assignToHash: function(key) {
1586
+ var value = this.popStack();
1587
+ var hash = this.topStack();
1588
+
1589
+ this.source.push(hash + "['" + key + "'] = " + value + ";");
1590
+ },
1591
+
1592
+ // HELPERS
1593
+
1594
+ compiler: JavaScriptCompiler,
1595
+
1596
+ compileChildren: function(environment, options) {
1597
+ var children = environment.children, child, compiler;
1598
+
1599
+ for(var i=0, l=children.length; i<l; i++) {
1600
+ child = children[i];
1601
+ compiler = new this.compiler();
1602
+
1603
+ this.context.programs.push(''); // Placeholder to prevent name conflicts for nested children
1604
+ var index = this.context.programs.length;
1605
+ child.index = index;
1606
+ child.name = 'program' + index;
1607
+ this.context.programs[index] = compiler.compile(child, options, this.context);
1608
+ }
1609
+ },
1610
+
1611
+ programExpression: function(guid) {
1612
+ this.context.aliases.self = "this";
1613
+
1614
+ if(guid == null) {
1615
+ return "self.noop";
1616
+ }
1617
+
1618
+ var child = this.environment.children[guid],
1619
+ depths = child.depths.list, depth;
1620
+
1621
+ var programParams = [child.index, child.name, "data"];
1622
+
1623
+ for(var i=0, l = depths.length; i<l; i++) {
1624
+ depth = depths[i];
1625
+
1626
+ if(depth === 1) { programParams.push("depth0"); }
1627
+ else { programParams.push("depth" + (depth - 1)); }
1628
+ }
1629
+
1630
+ if(depths.length === 0) {
1631
+ return "self.program(" + programParams.join(", ") + ")";
1632
+ } else {
1633
+ programParams.shift();
1634
+ return "self.programWithDepth(" + programParams.join(", ") + ")";
1635
+ }
1636
+ },
1637
+
1638
+ register: function(name, val) {
1639
+ this.useRegister(name);
1640
+ this.source.push(name + " = " + val + ";");
1641
+ },
1642
+
1643
+ useRegister: function(name) {
1644
+ if(!this.registers[name]) {
1645
+ this.registers[name] = true;
1646
+ this.registers.list.push(name);
1647
+ }
1648
+ },
1649
+
1650
+ pushStackLiteral: function(item) {
1651
+ this.compileStack.push(new Literal(item));
1652
+ return item;
1653
+ },
1654
+
1655
+ pushStack: function(item) {
1656
+ this.source.push(this.incrStack() + " = " + item + ";");
1657
+ this.compileStack.push("stack" + this.stackSlot);
1658
+ return "stack" + this.stackSlot;
1659
+ },
1660
+
1661
+ replaceStack: function(callback) {
1662
+ var item = callback.call(this, this.topStack());
1663
+
1664
+ this.source.push(this.topStack() + " = " + item + ";");
1665
+ return "stack" + this.stackSlot;
1666
+ },
1667
+
1668
+ nextStack: function(skipCompileStack) {
1669
+ var name = this.incrStack();
1670
+ this.compileStack.push("stack" + this.stackSlot);
1671
+ return name;
1672
+ },
1673
+
1674
+ incrStack: function() {
1675
+ this.stackSlot++;
1676
+ if(this.stackSlot > this.stackVars.length) { this.stackVars.push("stack" + this.stackSlot); }
1677
+ return "stack" + this.stackSlot;
1678
+ },
1679
+
1680
+ popStack: function() {
1681
+ var item = this.compileStack.pop();
1682
+
1683
+ if (item instanceof Literal) {
1684
+ return item.value;
1685
+ } else {
1686
+ this.stackSlot--;
1687
+ return item;
1688
+ }
1689
+ },
1690
+
1691
+ topStack: function() {
1692
+ var item = this.compileStack[this.compileStack.length - 1];
1693
+
1694
+ if (item instanceof Literal) {
1695
+ return item.value;
1696
+ } else {
1697
+ return item;
1698
+ }
1699
+ },
1700
+
1701
+ quotedString: function(str) {
1702
+ return '"' + str
1703
+ .replace(/\\/g, '\\\\')
1704
+ .replace(/"/g, '\\"')
1705
+ .replace(/\n/g, '\\n')
1706
+ .replace(/\r/g, '\\r') + '"';
1707
+ },
1708
+
1709
+ setupHelper: function(paramSize, name) {
1710
+ var params = [];
1711
+ this.setupParams(paramSize, params);
1712
+ var foundHelper = this.nameLookup('helpers', name, 'helper');
1713
+
1714
+ return {
1715
+ params: params,
1716
+ name: foundHelper,
1717
+ callParams: ["depth0"].concat(params).join(", "),
1718
+ helperMissingParams: ["depth0", this.quotedString(name)].concat(params).join(", ")
1719
+ };
1720
+ },
1721
+
1722
+ // the params and contexts arguments are passed in arrays
1723
+ // to fill in
1724
+ setupParams: function(paramSize, params) {
1725
+ var options = [], contexts = [], param, inverse, program;
1726
+
1727
+ options.push("hash:" + this.popStack());
1728
+
1729
+ inverse = this.popStack();
1730
+ program = this.popStack();
1731
+
1732
+ // Avoid setting fn and inverse if neither are set. This allows
1733
+ // helpers to do a check for `if (options.fn)`
1734
+ if (program || inverse) {
1735
+ if (!program) {
1736
+ this.context.aliases.self = "this";
1737
+ program = "self.noop";
1738
+ }
1739
+
1740
+ if (!inverse) {
1741
+ this.context.aliases.self = "this";
1742
+ inverse = "self.noop";
1743
+ }
1744
+
1745
+ options.push("inverse:" + inverse);
1746
+ options.push("fn:" + program);
1747
+ }
1748
+
1749
+ for(var i=0; i<paramSize; i++) {
1750
+ param = this.popStack();
1751
+ params.push(param);
1752
+
1753
+ if(this.options.stringParams) {
1754
+ contexts.push(this.popStack());
1755
+ }
1756
+ }
1757
+
1758
+ if (this.options.stringParams) {
1759
+ options.push("contexts:[" + contexts.join(",") + "]");
1760
+ }
1761
+
1762
+ if(this.options.data) {
1763
+ options.push("data:data");
1764
+ }
1765
+
1766
+ params.push("{" + options.join(",") + "}");
1767
+ return params.join(", ");
1768
+ }
1769
+ };
1770
+
1771
+ var reservedWords = (
1772
+ "break else new var" +
1773
+ " case finally return void" +
1774
+ " catch for switch while" +
1775
+ " continue function this with" +
1776
+ " default if throw" +
1777
+ " delete in try" +
1778
+ " do instanceof typeof" +
1779
+ " abstract enum int short" +
1780
+ " boolean export interface static" +
1781
+ " byte extends long super" +
1782
+ " char final native synchronized" +
1783
+ " class float package throws" +
1784
+ " const goto private transient" +
1785
+ " debugger implements protected volatile" +
1786
+ " double import public let yield"
1787
+ ).split(" ");
1788
+
1789
+ var compilerWords = JavaScriptCompiler.RESERVED_WORDS = {};
1790
+
1791
+ for(var i=0, l=reservedWords.length; i<l; i++) {
1792
+ compilerWords[reservedWords[i]] = true;
1793
+ }
1794
+
1795
+ JavaScriptCompiler.isValidJavaScriptVariableName = function(name) {
1796
+ if(!JavaScriptCompiler.RESERVED_WORDS[name] && /^[a-zA-Z_$][0-9a-zA-Z_$]+$/.test(name)) {
1797
+ return true;
1798
+ }
1799
+ return false;
1800
+ };
1801
+
1802
+ })(Handlebars.Compiler, Handlebars.JavaScriptCompiler);
1803
+
1804
+ Handlebars.precompile = function(string, options) {
1805
+ options = options || {};
1806
+
1807
+ var ast = Handlebars.parse(string);
1808
+ var environment = new Handlebars.Compiler().compile(ast, options);
1809
+ return new Handlebars.JavaScriptCompiler().compile(environment, options);
1810
+ };
1811
+
1812
+ Handlebars.compile = function(string, options) {
1813
+ options = options || {};
1814
+
1815
+ var compiled;
1816
+ function compile() {
1817
+ var ast = Handlebars.parse(string);
1818
+ var environment = new Handlebars.Compiler().compile(ast, options);
1819
+ var templateSpec = new Handlebars.JavaScriptCompiler().compile(environment, options, undefined, true);
1820
+ return Handlebars.template(templateSpec);
1821
+ }
1822
+
1823
+ // Template is only compiled on first use and cached after that point.
1824
+ return function(context, options) {
1825
+ if (!compiled) {
1826
+ compiled = compile();
1827
+ }
1828
+ return compiled.call(this, context, options);
1829
+ };
1830
+ };
1831
+ ;
1832
+ // lib/handlebars/runtime.js
1833
+ Handlebars.VM = {
1834
+ template: function(templateSpec) {
1835
+ // Just add water
1836
+ var container = {
1837
+ escapeExpression: Handlebars.Utils.escapeExpression,
1838
+ invokePartial: Handlebars.VM.invokePartial,
1839
+ programs: [],
1840
+ program: function(i, fn, data) {
1841
+ var programWrapper = this.programs[i];
1842
+ if(data) {
1843
+ return Handlebars.VM.program(fn, data);
1844
+ } else if(programWrapper) {
1845
+ return programWrapper;
1846
+ } else {
1847
+ programWrapper = this.programs[i] = Handlebars.VM.program(fn);
1848
+ return programWrapper;
1849
+ }
1850
+ },
1851
+ programWithDepth: Handlebars.VM.programWithDepth,
1852
+ noop: Handlebars.VM.noop
1853
+ };
1854
+
1855
+ return function(context, options) {
1856
+ options = options || {};
1857
+ return templateSpec.call(container, Handlebars, context, options.helpers, options.partials, options.data);
1858
+ };
1859
+ },
1860
+
1861
+ programWithDepth: function(fn, data, $depth) {
1862
+ var args = Array.prototype.slice.call(arguments, 2);
1863
+
1864
+ return function(context, options) {
1865
+ options = options || {};
1866
+
1867
+ return fn.apply(this, [context, options.data || data].concat(args));
1868
+ };
1869
+ },
1870
+ program: function(fn, data) {
1871
+ return function(context, options) {
1872
+ options = options || {};
1873
+
1874
+ return fn(context, options.data || data);
1875
+ };
1876
+ },
1877
+ noop: function() { return ""; },
1878
+ invokePartial: function(partial, name, context, helpers, partials, data) {
1879
+ var options = { helpers: helpers, partials: partials, data: data };
1880
+
1881
+ if(partial === undefined) {
1882
+ throw new Handlebars.Exception("The partial " + name + " could not be found");
1883
+ } else if(partial instanceof Function) {
1884
+ return partial(context, options);
1885
+ } else if (!Handlebars.compile) {
1886
+ throw new Handlebars.Exception("The partial " + name + " could not be compiled when running in runtime-only mode");
1887
+ } else {
1888
+ partials[name] = Handlebars.compile(partial);
1889
+ return partials[name](context, options);
1890
+ }
1891
+ }
1892
+ };
1893
+
1894
+ Handlebars.template = Handlebars.VM.template;
1895
+ ;