steering-rails 1.0.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.md +34 -0
- data/lib/steering/rails/version.rb +1 -1
- data/steering-rails.gemspec +1 -1
- data/vendor/assets/javascripts/handlebars.js +798 -428
- data/vendor/assets/javascripts/handlebars.runtime.js +32 -14
- metadata +62 -72
data/README.md
CHANGED
@@ -20,4 +20,38 @@ Or install it yourself as:
|
|
20
20
|
|
21
21
|
TODO: write usage instructions
|
22
22
|
|
23
|
+
## Changelog
|
24
|
+
|
25
|
+
### 1.1.0
|
26
|
+
|
27
|
+
* Bumped steering version to 1.1.1
|
28
|
+
* Updated Handlbars assets to 1.0.rc.1
|
29
|
+
|
30
|
+
### 1.0.0
|
31
|
+
|
32
|
+
Initial version.
|
33
|
+
|
34
|
+
## License (MIT)
|
35
|
+
|
36
|
+
Copyright (c) 2012 Andrew White <andyw@pixeltrix.co.uk>
|
37
|
+
|
38
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
39
|
+
a copy of this software and associated documentation files (the
|
40
|
+
"Software"), to deal in the Software without restriction, including
|
41
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
42
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
43
|
+
permit persons to whom the Software is furnished to do so, subject to
|
44
|
+
the following conditions:
|
45
|
+
|
46
|
+
The above copyright notice and this permission notice shall be
|
47
|
+
included in all copies or substantial portions of the Software.
|
48
|
+
|
49
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
50
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
51
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
52
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
53
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
54
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
55
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
56
|
+
|
23
57
|
[1]: https://github.com/wycats/handlebars.js
|
data/steering-rails.gemspec
CHANGED
@@ -1,7 +1,11 @@
|
|
1
1
|
// lib/handlebars/base.js
|
2
|
-
var Handlebars = {};
|
3
2
|
|
4
|
-
|
3
|
+
/*jshint eqnull:true*/
|
4
|
+
this.Handlebars = {};
|
5
|
+
|
6
|
+
(function(Handlebars) {
|
7
|
+
|
8
|
+
Handlebars.VERSION = "1.0.rc.1";
|
5
9
|
|
6
10
|
Handlebars.helpers = {};
|
7
11
|
Handlebars.partials = {};
|
@@ -40,25 +44,36 @@ Handlebars.registerHelper('blockHelperMissing', function(context, options) {
|
|
40
44
|
return inverse(this);
|
41
45
|
} else if(type === "[object Array]") {
|
42
46
|
if(context.length > 0) {
|
43
|
-
|
44
|
-
ret = ret + fn(context[i]);
|
45
|
-
}
|
47
|
+
return Handlebars.helpers.each(context, options);
|
46
48
|
} else {
|
47
|
-
|
49
|
+
return inverse(this);
|
48
50
|
}
|
49
|
-
return ret;
|
50
51
|
} else {
|
51
52
|
return fn(context);
|
52
53
|
}
|
53
54
|
});
|
54
55
|
|
56
|
+
Handlebars.K = function() {};
|
57
|
+
|
58
|
+
Handlebars.createFrame = Object.create || function(object) {
|
59
|
+
Handlebars.K.prototype = object;
|
60
|
+
var obj = new Handlebars.K();
|
61
|
+
Handlebars.K.prototype = null;
|
62
|
+
return obj;
|
63
|
+
};
|
64
|
+
|
55
65
|
Handlebars.registerHelper('each', function(context, options) {
|
56
66
|
var fn = options.fn, inverse = options.inverse;
|
57
|
-
var ret = "";
|
67
|
+
var ret = "", data;
|
68
|
+
|
69
|
+
if (options.data) {
|
70
|
+
data = Handlebars.createFrame(options.data);
|
71
|
+
}
|
58
72
|
|
59
73
|
if(context && context.length > 0) {
|
60
74
|
for(var i=0, j=context.length; i<j; i++) {
|
61
|
-
|
75
|
+
if (data) { data.index = i; }
|
76
|
+
ret = ret + fn(context[i], { data: data });
|
62
77
|
}
|
63
78
|
} else {
|
64
79
|
ret = inverse(this);
|
@@ -92,104 +107,111 @@ Handlebars.registerHelper('with', function(context, options) {
|
|
92
107
|
Handlebars.registerHelper('log', function(context) {
|
93
108
|
Handlebars.log(context);
|
94
109
|
});
|
110
|
+
|
111
|
+
}(this.Handlebars));
|
95
112
|
;
|
96
113
|
// lib/handlebars/compiler/parser.js
|
97
114
|
/* Jison generated parser */
|
98
115
|
var handlebars = (function(){
|
99
|
-
|
100
116
|
var parser = {trace: function trace() { },
|
101
117
|
yy: {},
|
102
|
-
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,"
|
103
|
-
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",
|
104
|
-
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],[
|
118
|
+
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,"DATA":27,"param":28,"STRING":29,"INTEGER":30,"BOOLEAN":31,"hashSegments":32,"hashSegment":33,"ID":34,"EQUALS":35,"pathSegments":36,"SEP":37,"$accept":0,"$end":1},
|
119
|
+
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",27:"DATA",29:"STRING",30:"INTEGER",31:"BOOLEAN",34:"ID",35:"EQUALS",37:"SEP"},
|
120
|
+
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],[17,1],[25,2],[25,1],[28,1],[28,1],[28,1],[28,1],[28,1],[26,1],[32,2],[32,1],[33,3],[33,3],[33,3],[33,3],[33,3],[21,1],[36,3],[36,1]],
|
105
121
|
performAction: function anonymous(yytext,yyleng,yylineno,yy,yystate,$$,_$) {
|
106
122
|
|
107
123
|
var $0 = $$.length - 1;
|
108
124
|
switch (yystate) {
|
109
|
-
case 1: return $$[$0-1]
|
125
|
+
case 1: return $$[$0-1];
|
126
|
+
break;
|
127
|
+
case 2: this.$ = new yy.ProgramNode($$[$0-2], $$[$0]);
|
110
128
|
break;
|
111
|
-
case
|
129
|
+
case 3: this.$ = new yy.ProgramNode($$[$0]);
|
112
130
|
break;
|
113
|
-
case
|
131
|
+
case 4: this.$ = new yy.ProgramNode([]);
|
114
132
|
break;
|
115
|
-
case
|
133
|
+
case 5: this.$ = [$$[$0]];
|
116
134
|
break;
|
117
|
-
case
|
135
|
+
case 6: $$[$0-1].push($$[$0]); this.$ = $$[$0-1];
|
118
136
|
break;
|
119
|
-
case
|
137
|
+
case 7: this.$ = new yy.BlockNode($$[$0-2], $$[$0-1].inverse, $$[$0-1], $$[$0]);
|
120
138
|
break;
|
121
|
-
case
|
139
|
+
case 8: this.$ = new yy.BlockNode($$[$0-2], $$[$0-1], $$[$0-1].inverse, $$[$0]);
|
122
140
|
break;
|
123
|
-
case
|
141
|
+
case 9: this.$ = $$[$0];
|
124
142
|
break;
|
125
|
-
case
|
143
|
+
case 10: this.$ = $$[$0];
|
126
144
|
break;
|
127
|
-
case
|
145
|
+
case 11: this.$ = new yy.ContentNode($$[$0]);
|
128
146
|
break;
|
129
|
-
case
|
147
|
+
case 12: this.$ = new yy.CommentNode($$[$0]);
|
130
148
|
break;
|
131
|
-
case
|
149
|
+
case 13: this.$ = new yy.MustacheNode($$[$0-1][0], $$[$0-1][1]);
|
132
150
|
break;
|
133
|
-
case
|
151
|
+
case 14: this.$ = new yy.MustacheNode($$[$0-1][0], $$[$0-1][1]);
|
134
152
|
break;
|
135
|
-
case
|
153
|
+
case 15: this.$ = $$[$0-1];
|
136
154
|
break;
|
137
|
-
case
|
155
|
+
case 16: this.$ = new yy.MustacheNode($$[$0-1][0], $$[$0-1][1]);
|
138
156
|
break;
|
139
|
-
case
|
157
|
+
case 17: this.$ = new yy.MustacheNode($$[$0-1][0], $$[$0-1][1], true);
|
140
158
|
break;
|
141
|
-
case
|
159
|
+
case 18: this.$ = new yy.PartialNode($$[$0-1]);
|
142
160
|
break;
|
143
|
-
case
|
161
|
+
case 19: this.$ = new yy.PartialNode($$[$0-2], $$[$0-1]);
|
144
162
|
break;
|
145
|
-
case
|
163
|
+
case 20:
|
146
164
|
break;
|
147
|
-
case
|
165
|
+
case 21: this.$ = [[$$[$0-2]].concat($$[$0-1]), $$[$0]];
|
148
166
|
break;
|
149
|
-
case
|
167
|
+
case 22: this.$ = [[$$[$0-1]].concat($$[$0]), null];
|
150
168
|
break;
|
151
|
-
case
|
169
|
+
case 23: this.$ = [[$$[$0-1]], $$[$0]];
|
152
170
|
break;
|
153
|
-
case
|
171
|
+
case 24: this.$ = [[$$[$0]], null];
|
154
172
|
break;
|
155
|
-
case
|
173
|
+
case 25: this.$ = [[new yy.DataNode($$[$0])], null];
|
156
174
|
break;
|
157
|
-
case
|
175
|
+
case 26: $$[$0-1].push($$[$0]); this.$ = $$[$0-1];
|
158
176
|
break;
|
159
|
-
case
|
177
|
+
case 27: this.$ = [$$[$0]];
|
160
178
|
break;
|
161
|
-
case
|
179
|
+
case 28: this.$ = $$[$0];
|
162
180
|
break;
|
163
|
-
case
|
181
|
+
case 29: this.$ = new yy.StringNode($$[$0]);
|
164
182
|
break;
|
165
|
-
case
|
183
|
+
case 30: this.$ = new yy.IntegerNode($$[$0]);
|
166
184
|
break;
|
167
|
-
case
|
185
|
+
case 31: this.$ = new yy.BooleanNode($$[$0]);
|
168
186
|
break;
|
169
|
-
case
|
187
|
+
case 32: this.$ = new yy.DataNode($$[$0]);
|
170
188
|
break;
|
171
|
-
case
|
189
|
+
case 33: this.$ = new yy.HashNode($$[$0]);
|
172
190
|
break;
|
173
|
-
case
|
191
|
+
case 34: $$[$0-1].push($$[$0]); this.$ = $$[$0-1];
|
174
192
|
break;
|
175
|
-
case
|
193
|
+
case 35: this.$ = [$$[$0]];
|
176
194
|
break;
|
177
|
-
case
|
195
|
+
case 36: this.$ = [$$[$0-2], $$[$0]];
|
178
196
|
break;
|
179
|
-
case
|
197
|
+
case 37: this.$ = [$$[$0-2], new yy.StringNode($$[$0])];
|
180
198
|
break;
|
181
|
-
case
|
199
|
+
case 38: this.$ = [$$[$0-2], new yy.IntegerNode($$[$0])];
|
182
200
|
break;
|
183
|
-
case
|
201
|
+
case 39: this.$ = [$$[$0-2], new yy.BooleanNode($$[$0])];
|
184
202
|
break;
|
185
|
-
case
|
203
|
+
case 40: this.$ = [$$[$0-2], new yy.DataNode($$[$0])];
|
186
204
|
break;
|
187
|
-
case
|
205
|
+
case 41: this.$ = new yy.IdNode($$[$0]);
|
206
|
+
break;
|
207
|
+
case 42: $$[$0-2].push($$[$0]); this.$ = $$[$0-2];
|
208
|
+
break;
|
209
|
+
case 43: this.$ = [$$[$0]];
|
188
210
|
break;
|
189
211
|
}
|
190
212
|
},
|
191
|
-
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,
|
192
|
-
defaultActions: {16:[2,1],
|
213
|
+
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,27:[1,24],34:[1,26],36:25},{17:27,21:23,27:[1,24],34:[1,26],36:25},{17:28,21:23,27:[1,24],34:[1,26],36:25},{17:29,21:23,27:[1,24],34:[1,26],36:25},{21:30,34:[1,26],36:25},{1:[2,1]},{6:31,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,32],21:23,27:[1,24],34:[1,26],36:25},{10:33,20:[1,34]},{10:35,20:[1,34]},{18:[1,36]},{18:[2,24],21:41,25:37,26:38,27:[1,45],28:39,29:[1,42],30:[1,43],31:[1,44],32:40,33:46,34:[1,47],36:25},{18:[2,25]},{18:[2,41],27:[2,41],29:[2,41],30:[2,41],31:[2,41],34:[2,41],37:[1,48]},{18:[2,43],27:[2,43],29:[2,43],30:[2,43],31:[2,43],34:[2,43],37:[2,43]},{18:[1,49]},{18:[1,50]},{18:[1,51]},{18:[1,52],21:53,34:[1,26],36:25},{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:54,34:[1,26],36:25},{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:41,26:55,27:[1,45],28:56,29:[1,42],30:[1,43],31:[1,44],32:40,33:46,34:[1,47],36:25},{18:[2,23]},{18:[2,27],27:[2,27],29:[2,27],30:[2,27],31:[2,27],34:[2,27]},{18:[2,33],33:57,34:[1,58]},{18:[2,28],27:[2,28],29:[2,28],30:[2,28],31:[2,28],34:[2,28]},{18:[2,29],27:[2,29],29:[2,29],30:[2,29],31:[2,29],34:[2,29]},{18:[2,30],27:[2,30],29:[2,30],30:[2,30],31:[2,30],34:[2,30]},{18:[2,31],27:[2,31],29:[2,31],30:[2,31],31:[2,31],34:[2,31]},{18:[2,32],27:[2,32],29:[2,32],30:[2,32],31:[2,32],34:[2,32]},{18:[2,35],34:[2,35]},{18:[2,43],27:[2,43],29:[2,43],30:[2,43],31:[2,43],34:[2,43],35:[1,59],37:[2,43]},{34:[1,60]},{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,61]},{18:[1,62]},{18:[2,21]},{18:[2,26],27:[2,26],29:[2,26],30:[2,26],31:[2,26],34:[2,26]},{18:[2,34],34:[2,34]},{35:[1,59]},{21:63,27:[1,67],29:[1,64],30:[1,65],31:[1,66],34:[1,26],36:25},{18:[2,42],27:[2,42],29:[2,42],30:[2,42],31:[2,42],34:[2,42],37:[2,42]},{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,36],34:[2,36]},{18:[2,37],34:[2,37]},{18:[2,38],34:[2,38]},{18:[2,39],34:[2,39]},{18:[2,40],34:[2,40]}],
|
214
|
+
defaultActions: {16:[2,1],24:[2,25],38:[2,23],55:[2,21]},
|
193
215
|
parseError: function parseError(str, hash) {
|
194
216
|
throw new Error(str);
|
195
217
|
},
|
@@ -198,10 +220,12 @@ parse: function parse(input) {
|
|
198
220
|
this.lexer.setInput(input);
|
199
221
|
this.lexer.yy = this.yy;
|
200
222
|
this.yy.lexer = this.lexer;
|
223
|
+
this.yy.parser = this;
|
201
224
|
if (typeof this.lexer.yylloc == "undefined")
|
202
225
|
this.lexer.yylloc = {};
|
203
226
|
var yyloc = this.lexer.yylloc;
|
204
227
|
lstack.push(yyloc);
|
228
|
+
var ranges = this.lexer.options && this.lexer.options.ranges;
|
205
229
|
if (typeof this.yy.parseError === "function")
|
206
230
|
this.parseError = this.yy.parseError;
|
207
231
|
function popStack(n) {
|
@@ -223,20 +247,21 @@ parse: function parse(input) {
|
|
223
247
|
if (this.defaultActions[state]) {
|
224
248
|
action = this.defaultActions[state];
|
225
249
|
} else {
|
226
|
-
if (symbol ==
|
250
|
+
if (symbol === null || typeof symbol == "undefined") {
|
227
251
|
symbol = lex();
|
252
|
+
}
|
228
253
|
action = table[state] && table[state][symbol];
|
229
254
|
}
|
230
255
|
if (typeof action === "undefined" || !action.length || !action[0]) {
|
256
|
+
var errStr = "";
|
231
257
|
if (!recovering) {
|
232
258
|
expected = [];
|
233
259
|
for (p in table[state])
|
234
260
|
if (this.terminals_[p] && p > 2) {
|
235
261
|
expected.push("'" + this.terminals_[p] + "'");
|
236
262
|
}
|
237
|
-
var errStr = "";
|
238
263
|
if (this.lexer.showPosition) {
|
239
|
-
errStr = "Parse error on line " + (yylineno + 1) + ":\n" + this.lexer.showPosition() + "\nExpecting " + expected.join(", ") + ", got '" + this.terminals_[symbol] + "'";
|
264
|
+
errStr = "Parse error on line " + (yylineno + 1) + ":\n" + this.lexer.showPosition() + "\nExpecting " + expected.join(", ") + ", got '" + (this.terminals_[symbol] || symbol) + "'";
|
240
265
|
} else {
|
241
266
|
errStr = "Parse error on line " + (yylineno + 1) + ": Unexpected " + (symbol == 1?"end of input":"'" + (this.terminals_[symbol] || symbol) + "'");
|
242
267
|
}
|
@@ -269,6 +294,9 @@ parse: function parse(input) {
|
|
269
294
|
len = this.productions_[action[1]][1];
|
270
295
|
yyval.$ = vstack[vstack.length - len];
|
271
296
|
yyval._$ = {first_line: lstack[lstack.length - (len || 1)].first_line, last_line: lstack[lstack.length - 1].last_line, first_column: lstack[lstack.length - (len || 1)].first_column, last_column: lstack[lstack.length - 1].last_column};
|
297
|
+
if (ranges) {
|
298
|
+
yyval._$.range = [lstack[lstack.length - (len || 1)].range[0], lstack[lstack.length - 1].range[1]];
|
299
|
+
}
|
272
300
|
r = this.performAction.call(yyval, yytext, yyleng, yylineno, this.yy, action[1], vstack, lstack);
|
273
301
|
if (typeof r !== "undefined") {
|
274
302
|
return r;
|
@@ -290,13 +318,13 @@ parse: function parse(input) {
|
|
290
318
|
}
|
291
319
|
return true;
|
292
320
|
}
|
293
|
-
}
|
321
|
+
};
|
322
|
+
/* Jison generated lexer */
|
294
323
|
var lexer = (function(){
|
295
|
-
|
296
324
|
var lexer = ({EOF:1,
|
297
325
|
parseError:function parseError(str, hash) {
|
298
|
-
if (this.yy.
|
299
|
-
this.yy.parseError(str, hash);
|
326
|
+
if (this.yy.parser) {
|
327
|
+
this.yy.parser.parseError(str, hash);
|
300
328
|
} else {
|
301
329
|
throw new Error(str);
|
302
330
|
}
|
@@ -308,27 +336,64 @@ setInput:function (input) {
|
|
308
336
|
this.yytext = this.matched = this.match = '';
|
309
337
|
this.conditionStack = ['INITIAL'];
|
310
338
|
this.yylloc = {first_line:1,first_column:0,last_line:1,last_column:0};
|
339
|
+
if (this.options.ranges) this.yylloc.range = [0,0];
|
340
|
+
this.offset = 0;
|
311
341
|
return this;
|
312
342
|
},
|
313
343
|
input:function () {
|
314
344
|
var ch = this._input[0];
|
315
|
-
this.yytext+=ch;
|
345
|
+
this.yytext += ch;
|
316
346
|
this.yyleng++;
|
317
|
-
this.
|
318
|
-
this.
|
319
|
-
|
320
|
-
|
347
|
+
this.offset++;
|
348
|
+
this.match += ch;
|
349
|
+
this.matched += ch;
|
350
|
+
var lines = ch.match(/(?:\r\n?|\n).*/g);
|
351
|
+
if (lines) {
|
352
|
+
this.yylineno++;
|
353
|
+
this.yylloc.last_line++;
|
354
|
+
} else {
|
355
|
+
this.yylloc.last_column++;
|
356
|
+
}
|
357
|
+
if (this.options.ranges) this.yylloc.range[1]++;
|
358
|
+
|
321
359
|
this._input = this._input.slice(1);
|
322
360
|
return ch;
|
323
361
|
},
|
324
362
|
unput:function (ch) {
|
363
|
+
var len = ch.length;
|
364
|
+
var lines = ch.split(/(?:\r\n?|\n)/g);
|
365
|
+
|
325
366
|
this._input = ch + this._input;
|
367
|
+
this.yytext = this.yytext.substr(0, this.yytext.length-len-1);
|
368
|
+
//this.yyleng -= len;
|
369
|
+
this.offset -= len;
|
370
|
+
var oldLines = this.match.split(/(?:\r\n?|\n)/g);
|
371
|
+
this.match = this.match.substr(0, this.match.length-1);
|
372
|
+
this.matched = this.matched.substr(0, this.matched.length-1);
|
373
|
+
|
374
|
+
if (lines.length-1) this.yylineno -= lines.length-1;
|
375
|
+
var r = this.yylloc.range;
|
376
|
+
|
377
|
+
this.yylloc = {first_line: this.yylloc.first_line,
|
378
|
+
last_line: this.yylineno+1,
|
379
|
+
first_column: this.yylloc.first_column,
|
380
|
+
last_column: lines ?
|
381
|
+
(lines.length === oldLines.length ? this.yylloc.first_column : 0) + oldLines[oldLines.length - lines.length].length - lines[0].length:
|
382
|
+
this.yylloc.first_column - len
|
383
|
+
};
|
384
|
+
|
385
|
+
if (this.options.ranges) {
|
386
|
+
this.yylloc.range = [r[0], r[0] + this.yyleng - len];
|
387
|
+
}
|
326
388
|
return this;
|
327
389
|
},
|
328
390
|
more:function () {
|
329
391
|
this._more = true;
|
330
392
|
return this;
|
331
393
|
},
|
394
|
+
less:function (n) {
|
395
|
+
this.unput(this.match.slice(n));
|
396
|
+
},
|
332
397
|
pastInput:function () {
|
333
398
|
var past = this.matched.substr(0, this.matched.length - this.match.length);
|
334
399
|
return (past.length > 20 ? '...':'') + past.substr(-20).replace(/\n/g, "");
|
@@ -353,6 +418,8 @@ next:function () {
|
|
353
418
|
|
354
419
|
var token,
|
355
420
|
match,
|
421
|
+
tempMatch,
|
422
|
+
index,
|
356
423
|
col,
|
357
424
|
lines;
|
358
425
|
if (!this._more) {
|
@@ -361,30 +428,39 @@ next:function () {
|
|
361
428
|
}
|
362
429
|
var rules = this._currentRules();
|
363
430
|
for (var i=0;i < rules.length; i++) {
|
364
|
-
|
365
|
-
if (match) {
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
last_line: this.yylineno+1,
|
370
|
-
first_column: this.yylloc.last_column,
|
371
|
-
last_column: lines ? lines[lines.length-1].length-1 : this.yylloc.last_column + match[0].length}
|
372
|
-
this.yytext += match[0];
|
373
|
-
this.match += match[0];
|
374
|
-
this.matches = match;
|
375
|
-
this.yyleng = this.yytext.length;
|
376
|
-
this._more = false;
|
377
|
-
this._input = this._input.slice(match[0].length);
|
378
|
-
this.matched += match[0];
|
379
|
-
token = this.performAction.call(this, this.yy, this, rules[i],this.conditionStack[this.conditionStack.length-1]);
|
380
|
-
if (token) return token;
|
381
|
-
else return;
|
431
|
+
tempMatch = this._input.match(this.rules[rules[i]]);
|
432
|
+
if (tempMatch && (!match || tempMatch[0].length > match[0].length)) {
|
433
|
+
match = tempMatch;
|
434
|
+
index = i;
|
435
|
+
if (!this.options.flex) break;
|
382
436
|
}
|
383
437
|
}
|
438
|
+
if (match) {
|
439
|
+
lines = match[0].match(/(?:\r\n?|\n).*/g);
|
440
|
+
if (lines) this.yylineno += lines.length;
|
441
|
+
this.yylloc = {first_line: this.yylloc.last_line,
|
442
|
+
last_line: this.yylineno+1,
|
443
|
+
first_column: this.yylloc.last_column,
|
444
|
+
last_column: lines ? lines[lines.length-1].length-lines[lines.length-1].match(/\r?\n?/)[0].length : this.yylloc.last_column + match[0].length};
|
445
|
+
this.yytext += match[0];
|
446
|
+
this.match += match[0];
|
447
|
+
this.matches = match;
|
448
|
+
this.yyleng = this.yytext.length;
|
449
|
+
if (this.options.ranges) {
|
450
|
+
this.yylloc.range = [this.offset, this.offset += this.yyleng];
|
451
|
+
}
|
452
|
+
this._more = false;
|
453
|
+
this._input = this._input.slice(match[0].length);
|
454
|
+
this.matched += match[0];
|
455
|
+
token = this.performAction.call(this, this.yy, this, rules[index],this.conditionStack[this.conditionStack.length-1]);
|
456
|
+
if (this.done && this._input) this.done = false;
|
457
|
+
if (token) return token;
|
458
|
+
else return;
|
459
|
+
}
|
384
460
|
if (this._input === "") {
|
385
461
|
return this.EOF;
|
386
462
|
} else {
|
387
|
-
this.parseError('Lexical error on line '+(this.yylineno+1)+'. Unrecognized text.\n'+this.showPosition(),
|
463
|
+
return this.parseError('Lexical error on line '+(this.yylineno+1)+'. Unrecognized text.\n'+this.showPosition(),
|
388
464
|
{text: "", token: null, line: this.yylineno});
|
389
465
|
}
|
390
466
|
},
|
@@ -411,6 +487,7 @@ topState:function () {
|
|
411
487
|
pushState:function begin(condition) {
|
412
488
|
this.begin(condition);
|
413
489
|
}});
|
490
|
+
lexer.options = {};
|
414
491
|
lexer.performAction = function anonymous(yy,yy_,$avoiding_name_collisions,YY_START) {
|
415
492
|
|
416
493
|
var YYSTATE=YY_START
|
@@ -419,78 +496,89 @@ case 0:
|
|
419
496
|
if(yy_.yytext.slice(-1) !== "\\") this.begin("mu");
|
420
497
|
if(yy_.yytext.slice(-1) === "\\") yy_.yytext = yy_.yytext.substr(0,yy_.yyleng-1), this.begin("emu");
|
421
498
|
if(yy_.yytext) return 14;
|
422
|
-
|
499
|
+
|
423
500
|
break;
|
424
|
-
case 1: return 14;
|
501
|
+
case 1: return 14;
|
425
502
|
break;
|
426
|
-
case 2:
|
503
|
+
case 2:
|
504
|
+
if(yy_.yytext.slice(-1) !== "\\") this.popState();
|
505
|
+
if(yy_.yytext.slice(-1) === "\\") yy_.yytext = yy_.yytext.substr(0,yy_.yyleng-1);
|
506
|
+
return 14;
|
507
|
+
|
427
508
|
break;
|
428
|
-
case 3: return 24;
|
509
|
+
case 3: return 24;
|
429
510
|
break;
|
430
|
-
case 4: return 16;
|
511
|
+
case 4: return 16;
|
431
512
|
break;
|
432
|
-
case 5: return 20;
|
513
|
+
case 5: return 20;
|
433
514
|
break;
|
434
|
-
case 6: return 19;
|
515
|
+
case 6: return 19;
|
435
516
|
break;
|
436
|
-
case 7: return 19;
|
517
|
+
case 7: return 19;
|
437
518
|
break;
|
438
|
-
case 8: return 23;
|
519
|
+
case 8: return 23;
|
439
520
|
break;
|
440
|
-
case 9: return 23;
|
521
|
+
case 9: return 23;
|
441
522
|
break;
|
442
|
-
case 10: yy_.yytext = yy_.yytext.substr(3,yy_.yyleng-5); this.popState(); return 15;
|
523
|
+
case 10: yy_.yytext = yy_.yytext.substr(3,yy_.yyleng-5); this.popState(); return 15;
|
443
524
|
break;
|
444
|
-
case 11: return 22;
|
525
|
+
case 11: return 22;
|
445
526
|
break;
|
446
|
-
case 12: return
|
527
|
+
case 12: return 35;
|
447
528
|
break;
|
448
|
-
case 13: return
|
529
|
+
case 13: return 34;
|
449
530
|
break;
|
450
|
-
case 14: return
|
531
|
+
case 14: return 34;
|
451
532
|
break;
|
452
|
-
case 15: return
|
533
|
+
case 15: return 37;
|
453
534
|
break;
|
454
|
-
case 16: /*ignore whitespace*/
|
535
|
+
case 16: /*ignore whitespace*/
|
455
536
|
break;
|
456
|
-
case 17: this.popState(); return 18;
|
537
|
+
case 17: this.popState(); return 18;
|
457
538
|
break;
|
458
|
-
case 18: this.popState(); return 18;
|
539
|
+
case 18: this.popState(); return 18;
|
459
540
|
break;
|
460
|
-
case 19: yy_.yytext = yy_.yytext.substr(1,yy_.yyleng-2).replace(/\\"/g,'"'); return
|
541
|
+
case 19: yy_.yytext = yy_.yytext.substr(1,yy_.yyleng-2).replace(/\\"/g,'"'); return 29;
|
461
542
|
break;
|
462
|
-
case 20: return
|
543
|
+
case 20: yy_.yytext = yy_.yytext.substr(1,yy_.yyleng-2).replace(/\\"/g,'"'); return 29;
|
463
544
|
break;
|
464
|
-
case 21: return
|
545
|
+
case 21: yy_.yytext = yy_.yytext.substr(1); return 27;
|
465
546
|
break;
|
466
|
-
case 22: return
|
547
|
+
case 22: return 31;
|
467
548
|
break;
|
468
|
-
case 23: return
|
549
|
+
case 23: return 31;
|
469
550
|
break;
|
470
|
-
case 24:
|
551
|
+
case 24: return 30;
|
471
552
|
break;
|
472
|
-
case 25: return
|
553
|
+
case 25: return 34;
|
473
554
|
break;
|
474
|
-
case 26: return
|
555
|
+
case 26: yy_.yytext = yy_.yytext.substr(1, yy_.yyleng-2); return 34;
|
556
|
+
break;
|
557
|
+
case 27: return 'INVALID';
|
558
|
+
break;
|
559
|
+
case 28: return 5;
|
475
560
|
break;
|
476
561
|
}
|
477
562
|
};
|
478
|
-
lexer.rules = [/^[^\x00]*?(?=(\{\{))/,/^[^\x00]
|
479
|
-
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,
|
563
|
+
lexer.rules = [/^(?:[^\x00]*?(?=(\{\{)))/,/^(?:[^\x00]+)/,/^(?:[^\x00]{2,}?(?=(\{\{|$)))/,/^(?:\{\{>)/,/^(?:\{\{#)/,/^(?:\{\{\/)/,/^(?:\{\{\^)/,/^(?:\{\{\s*else\b)/,/^(?:\{\{\{)/,/^(?:\{\{&)/,/^(?:\{\{![\s\S]*?\}\})/,/^(?:\{\{)/,/^(?:=)/,/^(?:\.(?=[} ]))/,/^(?:\.\.)/,/^(?:[\/.])/,/^(?:\s+)/,/^(?:\}\}\})/,/^(?:\}\})/,/^(?:"(\\["]|[^"])*")/,/^(?:'(\\[']|[^'])*')/,/^(?:@[a-zA-Z]+)/,/^(?:true(?=[}\s]))/,/^(?:false(?=[}\s]))/,/^(?:[0-9]+(?=[}\s]))/,/^(?:[a-zA-Z0-9_$-]+(?=[=}\s\/.]))/,/^(?:\[[^\]]*\])/,/^(?:.)/,/^(?:$)/];
|
564
|
+
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,27,28],"inclusive":false},"emu":{"rules":[2],"inclusive":false},"INITIAL":{"rules":[0,1,28],"inclusive":true}};
|
565
|
+
return lexer;})()
|
480
566
|
parser.lexer = lexer;
|
481
|
-
|
567
|
+
function Parser () { this.yy = {}; }Parser.prototype = parser;parser.Parser = Parser;
|
568
|
+
return new Parser;
|
482
569
|
})();
|
483
570
|
if (typeof require !== 'undefined' && typeof exports !== 'undefined') {
|
484
571
|
exports.parser = handlebars;
|
572
|
+
exports.Parser = handlebars.Parser;
|
485
573
|
exports.parse = function () { return handlebars.parse.apply(handlebars, arguments); }
|
486
574
|
exports.main = function commonjsMain(args) {
|
487
575
|
if (!args[1])
|
488
576
|
throw new Error('Usage: '+args[0]+' FILE');
|
577
|
+
var source, cwd;
|
489
578
|
if (typeof process !== 'undefined') {
|
490
|
-
|
579
|
+
source = require('fs').readFileSync(require('path').resolve(args[1]), "utf8");
|
491
580
|
} else {
|
492
|
-
|
493
|
-
var source = cwd.join(args[1]).read({charset: "utf-8"});
|
581
|
+
source = require("file").path(require("file").cwd()).join(args[1]).read({charset: "utf-8"});
|
494
582
|
}
|
495
583
|
return exports.parser.parse(source);
|
496
584
|
}
|
@@ -531,12 +619,26 @@ Handlebars.log = function(level, str) { Handlebars.logger.log(level, str); };
|
|
531
619
|
if(inverse) { this.inverse = new Handlebars.AST.ProgramNode(inverse); }
|
532
620
|
};
|
533
621
|
|
534
|
-
Handlebars.AST.MustacheNode = function(
|
622
|
+
Handlebars.AST.MustacheNode = function(rawParams, hash, unescaped) {
|
535
623
|
this.type = "mustache";
|
536
|
-
this.id = params[0];
|
537
|
-
this.params = params.slice(1);
|
538
|
-
this.hash = hash;
|
539
624
|
this.escaped = !unescaped;
|
625
|
+
this.hash = hash;
|
626
|
+
|
627
|
+
var id = this.id = rawParams[0];
|
628
|
+
var params = this.params = rawParams.slice(1);
|
629
|
+
|
630
|
+
// a mustache is an eligible helper if:
|
631
|
+
// * its id is simple (a single part, not `this` or `..`)
|
632
|
+
var eligibleHelper = this.eligibleHelper = id.isSimple;
|
633
|
+
|
634
|
+
// a mustache is definitely a helper if:
|
635
|
+
// * it is an eligible helper, and
|
636
|
+
// * it has at least one parameter or hash segment
|
637
|
+
this.isHelper = eligibleHelper && (params.length || hash);
|
638
|
+
|
639
|
+
// if a mustache is an eligible helper but not a definite
|
640
|
+
// helper, it is ambiguous, and will be resolved in a later
|
641
|
+
// pass or at runtime.
|
540
642
|
};
|
541
643
|
|
542
644
|
Handlebars.AST.PartialNode = function(id, context) {
|
@@ -554,18 +656,16 @@ Handlebars.log = function(level, str) { Handlebars.logger.log(level, str); };
|
|
554
656
|
}
|
555
657
|
};
|
556
658
|
|
557
|
-
Handlebars.AST.BlockNode = function(mustache, program, close) {
|
659
|
+
Handlebars.AST.BlockNode = function(mustache, program, inverse, close) {
|
558
660
|
verifyMatch(mustache.id, close);
|
559
661
|
this.type = "block";
|
560
662
|
this.mustache = mustache;
|
561
663
|
this.program = program;
|
562
|
-
|
664
|
+
this.inverse = inverse;
|
563
665
|
|
564
|
-
|
565
|
-
|
566
|
-
|
567
|
-
this.mustache = mustache;
|
568
|
-
this.program = program;
|
666
|
+
if (this.inverse && !this.program) {
|
667
|
+
this.isInverse = true;
|
668
|
+
}
|
569
669
|
};
|
570
670
|
|
571
671
|
Handlebars.AST.ContentNode = function(string) {
|
@@ -595,7 +695,15 @@ Handlebars.log = function(level, str) { Handlebars.logger.log(level, str); };
|
|
595
695
|
this.parts = dig;
|
596
696
|
this.string = dig.join('.');
|
597
697
|
this.depth = depth;
|
598
|
-
|
698
|
+
|
699
|
+
// an ID is simple if it only has one part, and that part is not
|
700
|
+
// `..` or `this`.
|
701
|
+
this.isSimple = parts.length === 1 && !this.isScoped && depth === 0;
|
702
|
+
};
|
703
|
+
|
704
|
+
Handlebars.AST.DataNode = function(id) {
|
705
|
+
this.type = "DATA";
|
706
|
+
this.id = id;
|
599
707
|
};
|
600
708
|
|
601
709
|
Handlebars.AST.StringNode = function(string) {
|
@@ -629,7 +737,7 @@ Handlebars.Exception = function(message) {
|
|
629
737
|
|
630
738
|
this.message = tmp.message;
|
631
739
|
};
|
632
|
-
Handlebars.Exception.prototype = new Error;
|
740
|
+
Handlebars.Exception.prototype = new Error();
|
633
741
|
|
634
742
|
// Build out our basic SafeString type
|
635
743
|
Handlebars.SafeString = function(string) {
|
@@ -641,6 +749,7 @@ Handlebars.SafeString.prototype.toString = function() {
|
|
641
749
|
|
642
750
|
(function() {
|
643
751
|
var escape = {
|
752
|
+
"&": "&",
|
644
753
|
"<": "<",
|
645
754
|
">": ">",
|
646
755
|
'"': """,
|
@@ -648,7 +757,7 @@ Handlebars.SafeString.prototype.toString = function() {
|
|
648
757
|
"`": "`"
|
649
758
|
};
|
650
759
|
|
651
|
-
var badChars =
|
760
|
+
var badChars = /[&<>"'`]/g;
|
652
761
|
var possible = /[&<>"'`]/;
|
653
762
|
|
654
763
|
var escapeChar = function(chr) {
|
@@ -684,88 +793,38 @@ Handlebars.SafeString.prototype.toString = function() {
|
|
684
793
|
};
|
685
794
|
})();;
|
686
795
|
// lib/handlebars/compiler/compiler.js
|
796
|
+
|
797
|
+
/*jshint eqnull:true*/
|
687
798
|
Handlebars.Compiler = function() {};
|
688
799
|
Handlebars.JavaScriptCompiler = function() {};
|
689
800
|
|
690
801
|
(function(Compiler, JavaScriptCompiler) {
|
691
|
-
|
692
|
-
|
693
|
-
|
694
|
-
|
695
|
-
lookup: 4,
|
696
|
-
append: 5,
|
697
|
-
invokeMustache: 6,
|
698
|
-
appendEscaped: 7,
|
699
|
-
pushString: 8,
|
700
|
-
truthyOrFallback: 9,
|
701
|
-
functionOrFallback: 10,
|
702
|
-
invokeProgram: 11,
|
703
|
-
invokePartial: 12,
|
704
|
-
push: 13,
|
705
|
-
assignToHash: 15,
|
706
|
-
pushStringParam: 16
|
707
|
-
};
|
708
|
-
|
709
|
-
Compiler.MULTI_PARAM_OPCODES = {
|
710
|
-
appendContent: 1,
|
711
|
-
getContext: 1,
|
712
|
-
lookupWithHelpers: 2,
|
713
|
-
lookup: 1,
|
714
|
-
invokeMustache: 3,
|
715
|
-
pushString: 1,
|
716
|
-
truthyOrFallback: 1,
|
717
|
-
functionOrFallback: 1,
|
718
|
-
invokeProgram: 3,
|
719
|
-
invokePartial: 1,
|
720
|
-
push: 1,
|
721
|
-
assignToHash: 1,
|
722
|
-
pushStringParam: 1
|
723
|
-
};
|
724
|
-
|
725
|
-
Compiler.DISASSEMBLE_MAP = {};
|
726
|
-
|
727
|
-
for(var prop in Compiler.OPCODE_MAP) {
|
728
|
-
var value = Compiler.OPCODE_MAP[prop];
|
729
|
-
Compiler.DISASSEMBLE_MAP[value] = prop;
|
730
|
-
}
|
731
|
-
|
732
|
-
Compiler.multiParamSize = function(code) {
|
733
|
-
return Compiler.MULTI_PARAM_OPCODES[Compiler.DISASSEMBLE_MAP[code]];
|
734
|
-
};
|
802
|
+
// the foundHelper register will disambiguate helper lookup from finding a
|
803
|
+
// function in a context. This is necessary for mustache compatibility, which
|
804
|
+
// requires that context functions in blocks are evaluated by blockHelperMissing,
|
805
|
+
// and then proceed as if the resulting value was provided to blockHelperMissing.
|
735
806
|
|
736
807
|
Compiler.prototype = {
|
737
808
|
compiler: Compiler,
|
738
809
|
|
739
810
|
disassemble: function() {
|
740
|
-
var opcodes = this.opcodes, opcode,
|
741
|
-
var out = [], str, name, value;
|
811
|
+
var opcodes = this.opcodes, opcode, out = [], params, param;
|
742
812
|
|
743
|
-
for(var i=0, l=opcodes.length; i<l; i++) {
|
813
|
+
for (var i=0, l=opcodes.length; i<l; i++) {
|
744
814
|
opcode = opcodes[i];
|
745
815
|
|
746
|
-
if(opcode === 'DECLARE') {
|
747
|
-
name =
|
748
|
-
value = opcodes[++i];
|
749
|
-
out.push("DECLARE " + name + " = " + value);
|
816
|
+
if (opcode.opcode === 'DECLARE') {
|
817
|
+
out.push("DECLARE " + opcode.name + "=" + opcode.value);
|
750
818
|
} else {
|
751
|
-
|
752
|
-
|
753
|
-
|
754
|
-
|
755
|
-
|
756
|
-
for(var j=0; j<extraParams; j++) {
|
757
|
-
nextCode = opcodes[++i];
|
758
|
-
|
759
|
-
if(typeof nextCode === "string") {
|
760
|
-
nextCode = "\"" + nextCode.replace("\n", "\\n") + "\"";
|
819
|
+
params = [];
|
820
|
+
for (var j=0; j<opcode.args.length; j++) {
|
821
|
+
param = opcode.args[j];
|
822
|
+
if (typeof param === "string") {
|
823
|
+
param = "\"" + param.replace("\n", "\\n") + "\"";
|
761
824
|
}
|
762
|
-
|
763
|
-
codes.push(nextCode);
|
825
|
+
params.push(param);
|
764
826
|
}
|
765
|
-
|
766
|
-
str = str + " " + codes.join(" ");
|
767
|
-
|
768
|
-
out.push(str);
|
827
|
+
out.push(opcode.opcode + " " + params.join(" "));
|
769
828
|
}
|
770
829
|
}
|
771
830
|
|
@@ -822,7 +881,7 @@ Handlebars.JavaScriptCompiler = function() {};
|
|
822
881
|
|
823
882
|
compileProgram: function(program) {
|
824
883
|
var result = new this.compiler().compile(program, this.options);
|
825
|
-
var guid = this.guid
|
884
|
+
var guid = this.guid++, depth;
|
826
885
|
|
827
886
|
this.usePartial = this.usePartial || result.usePartial;
|
828
887
|
|
@@ -839,32 +898,42 @@ Handlebars.JavaScriptCompiler = function() {};
|
|
839
898
|
},
|
840
899
|
|
841
900
|
block: function(block) {
|
842
|
-
var mustache = block.mustache
|
843
|
-
|
901
|
+
var mustache = block.mustache,
|
902
|
+
program = block.program,
|
903
|
+
inverse = block.inverse;
|
844
904
|
|
845
|
-
|
846
|
-
|
847
|
-
var programGuid = this.compileProgram(block.program);
|
848
|
-
|
849
|
-
if(block.program.inverse) {
|
850
|
-
inverseGuid = this.compileProgram(block.program.inverse);
|
851
|
-
this.declare('inverse', inverseGuid);
|
905
|
+
if (program) {
|
906
|
+
program = this.compileProgram(program);
|
852
907
|
}
|
853
908
|
|
854
|
-
|
855
|
-
|
856
|
-
|
857
|
-
},
|
909
|
+
if (inverse) {
|
910
|
+
inverse = this.compileProgram(inverse);
|
911
|
+
}
|
858
912
|
|
859
|
-
|
860
|
-
var params = this.setupStackForMustache(block.mustache);
|
913
|
+
var type = this.classifyMustache(mustache);
|
861
914
|
|
862
|
-
|
915
|
+
if (type === "helper") {
|
916
|
+
this.helperMustache(mustache, program, inverse);
|
917
|
+
} else if (type === "simple") {
|
918
|
+
this.simpleMustache(mustache);
|
863
919
|
|
864
|
-
|
920
|
+
// now that the simple mustache is resolved, we need to
|
921
|
+
// evaluate it by executing `blockHelperMissing`
|
922
|
+
this.opcode('pushProgram', program);
|
923
|
+
this.opcode('pushProgram', inverse);
|
924
|
+
this.opcode('pushLiteral', '{}');
|
925
|
+
this.opcode('blockValue');
|
926
|
+
} else {
|
927
|
+
this.ambiguousMustache(mustache, program, inverse);
|
928
|
+
|
929
|
+
// now that the simple mustache is resolved, we need to
|
930
|
+
// evaluate it by executing `blockHelperMissing`
|
931
|
+
this.opcode('pushProgram', program);
|
932
|
+
this.opcode('pushProgram', inverse);
|
933
|
+
this.opcode('pushLiteral', '{}');
|
934
|
+
this.opcode('ambiguousBlockValue');
|
935
|
+
}
|
865
936
|
|
866
|
-
this.opcode('invokeProgram', null, params.length, !!block.mustache.hash);
|
867
|
-
this.declare('inverse', null);
|
868
937
|
this.opcode('append');
|
869
938
|
},
|
870
939
|
|
@@ -901,44 +970,140 @@ Handlebars.JavaScriptCompiler = function() {};
|
|
901
970
|
},
|
902
971
|
|
903
972
|
mustache: function(mustache) {
|
904
|
-
var
|
973
|
+
var options = this.options;
|
974
|
+
var type = this.classifyMustache(mustache);
|
905
975
|
|
906
|
-
|
976
|
+
if (type === "simple") {
|
977
|
+
this.simpleMustache(mustache);
|
978
|
+
} else if (type === "helper") {
|
979
|
+
this.helperMustache(mustache);
|
980
|
+
} else {
|
981
|
+
this.ambiguousMustache(mustache);
|
982
|
+
}
|
907
983
|
|
908
|
-
if(mustache.escaped && !
|
984
|
+
if(mustache.escaped && !options.noEscape) {
|
909
985
|
this.opcode('appendEscaped');
|
910
986
|
} else {
|
911
987
|
this.opcode('append');
|
912
988
|
}
|
913
989
|
},
|
914
990
|
|
991
|
+
ambiguousMustache: function(mustache, program, inverse) {
|
992
|
+
var id = mustache.id, name = id.parts[0];
|
993
|
+
|
994
|
+
this.opcode('getContext', id.depth);
|
995
|
+
|
996
|
+
this.opcode('pushProgram', program);
|
997
|
+
this.opcode('pushProgram', inverse);
|
998
|
+
|
999
|
+
this.opcode('invokeAmbiguous', name);
|
1000
|
+
},
|
1001
|
+
|
1002
|
+
simpleMustache: function(mustache, program, inverse) {
|
1003
|
+
var id = mustache.id;
|
1004
|
+
|
1005
|
+
if (id.type === 'DATA') {
|
1006
|
+
this.DATA(id);
|
1007
|
+
} else if (id.parts.length) {
|
1008
|
+
this.ID(id);
|
1009
|
+
} else {
|
1010
|
+
// Simplified ID for `this`
|
1011
|
+
this.addDepth(id.depth);
|
1012
|
+
this.opcode('getContext', id.depth);
|
1013
|
+
this.opcode('pushContext');
|
1014
|
+
}
|
1015
|
+
|
1016
|
+
this.opcode('resolvePossibleLambda');
|
1017
|
+
},
|
1018
|
+
|
1019
|
+
helperMustache: function(mustache, program, inverse) {
|
1020
|
+
var params = this.setupFullMustacheParams(mustache, program, inverse),
|
1021
|
+
name = mustache.id.parts[0];
|
1022
|
+
|
1023
|
+
if (this.options.knownHelpers[name]) {
|
1024
|
+
this.opcode('invokeKnownHelper', params.length, name);
|
1025
|
+
} else if (this.knownHelpersOnly) {
|
1026
|
+
throw new Error("You specified knownHelpersOnly, but used the unknown helper " + name);
|
1027
|
+
} else {
|
1028
|
+
this.opcode('invokeHelper', params.length, name);
|
1029
|
+
}
|
1030
|
+
},
|
1031
|
+
|
915
1032
|
ID: function(id) {
|
916
1033
|
this.addDepth(id.depth);
|
917
|
-
|
918
1034
|
this.opcode('getContext', id.depth);
|
919
1035
|
|
920
|
-
|
1036
|
+
var name = id.parts[0];
|
1037
|
+
if (!name) {
|
1038
|
+
this.opcode('pushContext');
|
1039
|
+
} else {
|
1040
|
+
this.opcode('lookupOnContext', id.parts[0]);
|
1041
|
+
}
|
921
1042
|
|
922
1043
|
for(var i=1, l=id.parts.length; i<l; i++) {
|
923
1044
|
this.opcode('lookup', id.parts[i]);
|
924
1045
|
}
|
925
1046
|
},
|
926
1047
|
|
1048
|
+
DATA: function(data) {
|
1049
|
+
this.options.data = true;
|
1050
|
+
this.opcode('lookupData', data.id);
|
1051
|
+
},
|
1052
|
+
|
927
1053
|
STRING: function(string) {
|
928
1054
|
this.opcode('pushString', string.string);
|
929
1055
|
},
|
930
1056
|
|
931
1057
|
INTEGER: function(integer) {
|
932
|
-
this.opcode('
|
1058
|
+
this.opcode('pushLiteral', integer.integer);
|
933
1059
|
},
|
934
1060
|
|
935
1061
|
BOOLEAN: function(bool) {
|
936
|
-
this.opcode('
|
1062
|
+
this.opcode('pushLiteral', bool.bool);
|
937
1063
|
},
|
938
1064
|
|
939
1065
|
comment: function() {},
|
940
1066
|
|
941
1067
|
// HELPERS
|
1068
|
+
opcode: function(name) {
|
1069
|
+
this.opcodes.push({ opcode: name, args: [].slice.call(arguments, 1) });
|
1070
|
+
},
|
1071
|
+
|
1072
|
+
declare: function(name, value) {
|
1073
|
+
this.opcodes.push({ opcode: 'DECLARE', name: name, value: value });
|
1074
|
+
},
|
1075
|
+
|
1076
|
+
addDepth: function(depth) {
|
1077
|
+
if(isNaN(depth)) { throw new Error("EWOT"); }
|
1078
|
+
if(depth === 0) { return; }
|
1079
|
+
|
1080
|
+
if(!this.depths[depth]) {
|
1081
|
+
this.depths[depth] = true;
|
1082
|
+
this.depths.list.push(depth);
|
1083
|
+
}
|
1084
|
+
},
|
1085
|
+
|
1086
|
+
classifyMustache: function(mustache) {
|
1087
|
+
var isHelper = mustache.isHelper;
|
1088
|
+
var isEligible = mustache.eligibleHelper;
|
1089
|
+
var options = this.options;
|
1090
|
+
|
1091
|
+
// if ambiguous, we can possibly resolve the ambiguity now
|
1092
|
+
if (isEligible && !isHelper) {
|
1093
|
+
var name = mustache.id.parts[0];
|
1094
|
+
|
1095
|
+
if (options.knownHelpers[name]) {
|
1096
|
+
isHelper = true;
|
1097
|
+
} else if (options.knownHelpersOnly) {
|
1098
|
+
isEligible = false;
|
1099
|
+
}
|
1100
|
+
}
|
1101
|
+
|
1102
|
+
if (isHelper) { return "helper"; }
|
1103
|
+
else if (isEligible) { return "ambiguous"; }
|
1104
|
+
else { return "simple"; }
|
1105
|
+
},
|
1106
|
+
|
942
1107
|
pushParams: function(params) {
|
943
1108
|
var i = params.length, param;
|
944
1109
|
|
@@ -958,54 +1123,52 @@ Handlebars.JavaScriptCompiler = function() {};
|
|
958
1123
|
}
|
959
1124
|
},
|
960
1125
|
|
961
|
-
|
962
|
-
|
963
|
-
|
964
|
-
if(val2 !== undefined) { this.opcodes.push(val2); }
|
965
|
-
if(val3 !== undefined) { this.opcodes.push(val3); }
|
966
|
-
},
|
967
|
-
|
968
|
-
declare: function(name, value) {
|
969
|
-
this.opcodes.push('DECLARE');
|
970
|
-
this.opcodes.push(name);
|
971
|
-
this.opcodes.push(value);
|
972
|
-
},
|
973
|
-
|
974
|
-
addDepth: function(depth) {
|
975
|
-
if(depth === 0) { return; }
|
1126
|
+
setupMustacheParams: function(mustache) {
|
1127
|
+
var params = mustache.params;
|
1128
|
+
this.pushParams(params);
|
976
1129
|
|
977
|
-
if(
|
978
|
-
this.
|
979
|
-
|
1130
|
+
if(mustache.hash) {
|
1131
|
+
this.hash(mustache.hash);
|
1132
|
+
} else {
|
1133
|
+
this.opcode('pushLiteral', '{}');
|
980
1134
|
}
|
1135
|
+
|
1136
|
+
return params;
|
981
1137
|
},
|
982
1138
|
|
983
|
-
|
1139
|
+
// this will replace setupMustacheParams when we're done
|
1140
|
+
setupFullMustacheParams: function(mustache, program, inverse) {
|
984
1141
|
var params = mustache.params;
|
985
|
-
|
986
1142
|
this.pushParams(params);
|
987
1143
|
|
1144
|
+
this.opcode('pushProgram', program);
|
1145
|
+
this.opcode('pushProgram', inverse);
|
1146
|
+
|
988
1147
|
if(mustache.hash) {
|
989
1148
|
this.hash(mustache.hash);
|
1149
|
+
} else {
|
1150
|
+
this.opcode('pushLiteral', '{}');
|
990
1151
|
}
|
991
1152
|
|
992
|
-
this.ID(mustache.id);
|
993
|
-
|
994
1153
|
return params;
|
995
1154
|
}
|
996
1155
|
};
|
997
1156
|
|
1157
|
+
var Literal = function(value) {
|
1158
|
+
this.value = value;
|
1159
|
+
};
|
1160
|
+
|
998
1161
|
JavaScriptCompiler.prototype = {
|
999
1162
|
// PUBLIC API: You can override these methods in a subclass to provide
|
1000
1163
|
// alternative compiled forms for name lookup and buffering semantics
|
1001
1164
|
nameLookup: function(parent, name, type) {
|
1002
|
-
|
1165
|
+
if (/^[0-9]+$/.test(name)) {
|
1003
1166
|
return parent + "[" + name + "]";
|
1004
1167
|
} else if (JavaScriptCompiler.isValidJavaScriptVariableName(name)) {
|
1005
|
-
|
1006
|
-
|
1007
|
-
|
1008
|
-
|
1168
|
+
return parent + "." + name;
|
1169
|
+
}
|
1170
|
+
else {
|
1171
|
+
return parent + "['" + name + "']";
|
1009
1172
|
}
|
1010
1173
|
},
|
1011
1174
|
|
@@ -1028,18 +1191,21 @@ Handlebars.JavaScriptCompiler = function() {};
|
|
1028
1191
|
this.environment = environment;
|
1029
1192
|
this.options = options || {};
|
1030
1193
|
|
1194
|
+
Handlebars.log(Handlebars.logger.DEBUG, this.environment.disassemble() + "\n\n");
|
1195
|
+
|
1031
1196
|
this.name = this.environment.name;
|
1032
1197
|
this.isChild = !!context;
|
1033
1198
|
this.context = context || {
|
1034
1199
|
programs: [],
|
1035
|
-
aliases: {
|
1036
|
-
registers: {list: []}
|
1200
|
+
aliases: { }
|
1037
1201
|
};
|
1038
1202
|
|
1039
1203
|
this.preamble();
|
1040
1204
|
|
1041
1205
|
this.stackSlot = 0;
|
1042
1206
|
this.stackVars = [];
|
1207
|
+
this.registers = { list: [] };
|
1208
|
+
this.compileStack = [];
|
1043
1209
|
|
1044
1210
|
this.compileChildren(environment, options);
|
1045
1211
|
|
@@ -1048,59 +1214,35 @@ Handlebars.JavaScriptCompiler = function() {};
|
|
1048
1214
|
this.i = 0;
|
1049
1215
|
|
1050
1216
|
for(l=opcodes.length; this.i<l; this.i++) {
|
1051
|
-
opcode = this.
|
1217
|
+
opcode = opcodes[this.i];
|
1052
1218
|
|
1053
|
-
if(opcode
|
1054
|
-
this.
|
1055
|
-
this[opcode[1]] = opcode[2];
|
1219
|
+
if(opcode.opcode === 'DECLARE') {
|
1220
|
+
this[opcode.name] = opcode.value;
|
1056
1221
|
} else {
|
1057
|
-
this.
|
1058
|
-
this[opcode[0]].apply(this, opcode[1]);
|
1222
|
+
this[opcode.opcode].apply(this, opcode.args);
|
1059
1223
|
}
|
1060
1224
|
}
|
1061
1225
|
|
1062
1226
|
return this.createFunctionContext(asObject);
|
1063
1227
|
},
|
1064
1228
|
|
1065
|
-
nextOpcode: function(
|
1066
|
-
var opcodes = this.environment.opcodes, opcode = opcodes[this.i +
|
1067
|
-
|
1068
|
-
|
1069
|
-
if(opcode === 'DECLARE') {
|
1070
|
-
name = opcodes[this.i + 1];
|
1071
|
-
val = opcodes[this.i + 2];
|
1072
|
-
return ['DECLARE', name, val];
|
1073
|
-
} else {
|
1074
|
-
name = Compiler.DISASSEMBLE_MAP[opcode];
|
1075
|
-
|
1076
|
-
extraParams = Compiler.multiParamSize(opcode);
|
1077
|
-
codes = [];
|
1078
|
-
|
1079
|
-
for(var j=0; j<extraParams; j++) {
|
1080
|
-
codes.push(opcodes[this.i + j + 1 + n]);
|
1081
|
-
}
|
1082
|
-
|
1083
|
-
return [name, codes];
|
1084
|
-
}
|
1229
|
+
nextOpcode: function() {
|
1230
|
+
var opcodes = this.environment.opcodes, opcode = opcodes[this.i + 1];
|
1231
|
+
return opcodes[this.i + 1];
|
1085
1232
|
},
|
1086
1233
|
|
1087
1234
|
eat: function(opcode) {
|
1088
|
-
this.i = this.i +
|
1235
|
+
this.i = this.i + 1;
|
1089
1236
|
},
|
1090
1237
|
|
1091
1238
|
preamble: function() {
|
1092
1239
|
var out = [];
|
1093
1240
|
|
1094
|
-
// this register will disambiguate helper lookup from finding a function in
|
1095
|
-
// a context. This is necessary for mustache compatibility, which requires
|
1096
|
-
// that context functions in blocks are evaluated by blockHelperMissing, and
|
1097
|
-
// then proceed as if the resulting value was provided to blockHelperMissing.
|
1098
|
-
this.useRegister('foundHelper');
|
1099
|
-
|
1100
1241
|
if (!this.isChild) {
|
1101
1242
|
var namespace = this.namespace;
|
1102
1243
|
var copies = "helpers = helpers || " + namespace + ".helpers;";
|
1103
|
-
if(this.environment.usePartial) { copies = copies + " partials = partials || " + namespace + ".partials;"; }
|
1244
|
+
if (this.environment.usePartial) { copies = copies + " partials = partials || " + namespace + ".partials;"; }
|
1245
|
+
if (this.options.data) { copies = copies + " data = data || {};"; }
|
1104
1246
|
out.push(copies);
|
1105
1247
|
} else {
|
1106
1248
|
out.push('');
|
@@ -1119,10 +1261,7 @@ Handlebars.JavaScriptCompiler = function() {};
|
|
1119
1261
|
},
|
1120
1262
|
|
1121
1263
|
createFunctionContext: function(asObject) {
|
1122
|
-
var locals = this.stackVars;
|
1123
|
-
if (!this.isChild) {
|
1124
|
-
locals = locals.concat(this.context.registers.list);
|
1125
|
-
}
|
1264
|
+
var locals = this.stackVars.concat(this.registers.list);
|
1126
1265
|
|
1127
1266
|
if(locals.length > 0) {
|
1128
1267
|
this.source[1] = this.source[1] + ", " + locals.join(", ");
|
@@ -1130,7 +1269,7 @@ Handlebars.JavaScriptCompiler = function() {};
|
|
1130
1269
|
|
1131
1270
|
// Generate minimizer alias mappings
|
1132
1271
|
if (!this.isChild) {
|
1133
|
-
var aliases = []
|
1272
|
+
var aliases = [];
|
1134
1273
|
for (var alias in this.context.aliases) {
|
1135
1274
|
this.source[1] = this.source[1] + ', ' + alias + '=' + this.context.aliases[alias];
|
1136
1275
|
}
|
@@ -1166,10 +1305,64 @@ Handlebars.JavaScriptCompiler = function() {};
|
|
1166
1305
|
}
|
1167
1306
|
},
|
1168
1307
|
|
1308
|
+
// [blockValue]
|
1309
|
+
//
|
1310
|
+
// On stack, before: hash, inverse, program, value
|
1311
|
+
// On stack, after: return value of blockHelperMissing
|
1312
|
+
//
|
1313
|
+
// The purpose of this opcode is to take a block of the form
|
1314
|
+
// `{{#foo}}...{{/foo}}`, resolve the value of `foo`, and
|
1315
|
+
// replace it on the stack with the result of properly
|
1316
|
+
// invoking blockHelperMissing.
|
1317
|
+
blockValue: function() {
|
1318
|
+
this.context.aliases.blockHelperMissing = 'helpers.blockHelperMissing';
|
1319
|
+
|
1320
|
+
var params = ["depth0"];
|
1321
|
+
this.setupParams(0, params);
|
1322
|
+
|
1323
|
+
this.replaceStack(function(current) {
|
1324
|
+
params.splice(1, 0, current);
|
1325
|
+
return current + " = blockHelperMissing.call(" + params.join(", ") + ")";
|
1326
|
+
});
|
1327
|
+
},
|
1328
|
+
|
1329
|
+
// [ambiguousBlockValue]
|
1330
|
+
//
|
1331
|
+
// On stack, before: hash, inverse, program, value
|
1332
|
+
// Compiler value, before: lastHelper=value of last found helper, if any
|
1333
|
+
// On stack, after, if no lastHelper: same as [blockValue]
|
1334
|
+
// On stack, after, if lastHelper: value
|
1335
|
+
ambiguousBlockValue: function() {
|
1336
|
+
this.context.aliases.blockHelperMissing = 'helpers.blockHelperMissing';
|
1337
|
+
|
1338
|
+
var params = ["depth0"];
|
1339
|
+
this.setupParams(0, params);
|
1340
|
+
|
1341
|
+
var current = this.topStack();
|
1342
|
+
params.splice(1, 0, current);
|
1343
|
+
|
1344
|
+
this.source.push("if (!" + this.lastHelper + ") { " + current + " = blockHelperMissing.call(" + params.join(", ") + "); }");
|
1345
|
+
},
|
1346
|
+
|
1347
|
+
// [appendContent]
|
1348
|
+
//
|
1349
|
+
// On stack, before: ...
|
1350
|
+
// On stack, after: ...
|
1351
|
+
//
|
1352
|
+
// Appends the string value of `content` to the current buffer
|
1169
1353
|
appendContent: function(content) {
|
1170
1354
|
this.source.push(this.appendToBuffer(this.quotedString(content)));
|
1171
1355
|
},
|
1172
1356
|
|
1357
|
+
// [append]
|
1358
|
+
//
|
1359
|
+
// On stack, before: value, ...
|
1360
|
+
// On stack, after: ...
|
1361
|
+
//
|
1362
|
+
// Coerces `value` to a String and appends it to the current buffer.
|
1363
|
+
//
|
1364
|
+
// If `value` is truthy, or 0, it is coerced into a string and appended
|
1365
|
+
// Otherwise, the empty string is appended
|
1173
1366
|
append: function() {
|
1174
1367
|
var local = this.popStack();
|
1175
1368
|
this.source.push("if(" + local + " || " + local + " === 0) { " + this.appendToBuffer(local) + " }");
|
@@ -1178,163 +1371,242 @@ Handlebars.JavaScriptCompiler = function() {};
|
|
1178
1371
|
}
|
1179
1372
|
},
|
1180
1373
|
|
1374
|
+
// [appendEscaped]
|
1375
|
+
//
|
1376
|
+
// On stack, before: value, ...
|
1377
|
+
// On stack, after: ...
|
1378
|
+
//
|
1379
|
+
// Escape `value` and append it to the buffer
|
1181
1380
|
appendEscaped: function() {
|
1182
|
-
var opcode = this.nextOpcode(
|
1381
|
+
var opcode = this.nextOpcode(), extra = "";
|
1183
1382
|
this.context.aliases.escapeExpression = 'this.escapeExpression';
|
1184
1383
|
|
1185
|
-
if(opcode
|
1186
|
-
extra = " + " + this.quotedString(opcode[
|
1384
|
+
if(opcode && opcode.opcode === 'appendContent') {
|
1385
|
+
extra = " + " + this.quotedString(opcode.args[0]);
|
1187
1386
|
this.eat(opcode);
|
1188
1387
|
}
|
1189
1388
|
|
1190
1389
|
this.source.push(this.appendToBuffer("escapeExpression(" + this.popStack() + ")" + extra));
|
1191
1390
|
},
|
1192
1391
|
|
1392
|
+
// [getContext]
|
1393
|
+
//
|
1394
|
+
// On stack, before: ...
|
1395
|
+
// On stack, after: ...
|
1396
|
+
// Compiler value, after: lastContext=depth
|
1397
|
+
//
|
1398
|
+
// Set the value of the `lastContext` compiler value to the depth
|
1193
1399
|
getContext: function(depth) {
|
1194
1400
|
if(this.lastContext !== depth) {
|
1195
1401
|
this.lastContext = depth;
|
1196
1402
|
}
|
1197
1403
|
},
|
1198
1404
|
|
1199
|
-
|
1200
|
-
|
1201
|
-
|
1202
|
-
|
1203
|
-
|
1204
|
-
|
1205
|
-
|
1206
|
-
|
1207
|
-
|
1208
|
-
|
1209
|
-
|
1210
|
-
|
1211
|
-
|
1212
|
-
|
1213
|
-
|
1214
|
-
|
1215
|
-
|
1216
|
-
|
1217
|
-
|
1218
|
-
|
1219
|
-
|
1220
|
-
|
1405
|
+
// [lookupOnContext]
|
1406
|
+
//
|
1407
|
+
// On stack, before: ...
|
1408
|
+
// On stack, after: currentContext[name], ...
|
1409
|
+
//
|
1410
|
+
// Looks up the value of `name` on the current context and pushes
|
1411
|
+
// it onto the stack.
|
1412
|
+
lookupOnContext: function(name) {
|
1413
|
+
this.pushStack(this.nameLookup('depth' + this.lastContext, name, 'context'));
|
1414
|
+
},
|
1415
|
+
|
1416
|
+
// [pushContext]
|
1417
|
+
//
|
1418
|
+
// On stack, before: ...
|
1419
|
+
// On stack, after: currentContext, ...
|
1420
|
+
//
|
1421
|
+
// Pushes the value of the current context onto the stack.
|
1422
|
+
pushContext: function() {
|
1423
|
+
this.pushStackLiteral('depth' + this.lastContext);
|
1424
|
+
},
|
1425
|
+
|
1426
|
+
// [resolvePossibleLambda]
|
1427
|
+
//
|
1428
|
+
// On stack, before: value, ...
|
1429
|
+
// On stack, after: resolved value, ...
|
1430
|
+
//
|
1431
|
+
// If the `value` is a lambda, replace it on the stack by
|
1432
|
+
// the return value of the lambda
|
1433
|
+
resolvePossibleLambda: function() {
|
1434
|
+
this.context.aliases.functionType = '"function"';
|
1435
|
+
|
1436
|
+
this.replaceStack(function(current) {
|
1437
|
+
return "typeof " + current + " === functionType ? " + current + "() : " + current;
|
1438
|
+
});
|
1221
1439
|
},
|
1222
1440
|
|
1441
|
+
// [lookup]
|
1442
|
+
//
|
1443
|
+
// On stack, before: value, ...
|
1444
|
+
// On stack, after: value[name], ...
|
1445
|
+
//
|
1446
|
+
// Replace the value on the stack with the result of looking
|
1447
|
+
// up `name` on `value`
|
1223
1448
|
lookup: function(name) {
|
1224
|
-
|
1225
|
-
|
1226
|
-
|
1449
|
+
this.replaceStack(function(current) {
|
1450
|
+
return current + " == null || " + current + " === false ? " + current + " : " + this.nameLookup(current, name, 'context');
|
1451
|
+
});
|
1227
1452
|
},
|
1228
1453
|
|
1454
|
+
// [lookupData]
|
1455
|
+
//
|
1456
|
+
// On stack, before: ...
|
1457
|
+
// On stack, after: data[id], ...
|
1458
|
+
//
|
1459
|
+
// Push the result of looking up `id` on the current data
|
1460
|
+
lookupData: function(id) {
|
1461
|
+
this.pushStack(this.nameLookup('data', id, 'data'));
|
1462
|
+
},
|
1463
|
+
|
1464
|
+
// [pushStringParam]
|
1465
|
+
//
|
1466
|
+
// On stack, before: ...
|
1467
|
+
// On stack, after: string, currentContext, ...
|
1468
|
+
//
|
1469
|
+
// This opcode is designed for use in string mode, which
|
1470
|
+
// provides the string value of a parameter along with its
|
1471
|
+
// depth rather than resolving it immediately.
|
1229
1472
|
pushStringParam: function(string) {
|
1230
|
-
this.
|
1473
|
+
this.pushStackLiteral('depth' + this.lastContext);
|
1231
1474
|
this.pushString(string);
|
1232
1475
|
},
|
1233
1476
|
|
1477
|
+
// [pushString]
|
1478
|
+
//
|
1479
|
+
// On stack, before: ...
|
1480
|
+
// On stack, after: quotedString(string), ...
|
1481
|
+
//
|
1482
|
+
// Push a quoted version of `string` onto the stack
|
1234
1483
|
pushString: function(string) {
|
1235
|
-
this.
|
1236
|
-
},
|
1237
|
-
|
1238
|
-
push
|
1239
|
-
|
1240
|
-
|
1241
|
-
|
1242
|
-
|
1243
|
-
|
1244
|
-
|
1245
|
-
|
1246
|
-
|
1247
|
-
|
1248
|
-
|
1249
|
-
|
1250
|
-
|
1251
|
-
|
1252
|
-
|
1253
|
-
|
1254
|
-
|
1255
|
-
|
1256
|
-
|
1257
|
-
|
1258
|
-
|
1259
|
-
|
1260
|
-
|
1261
|
-
|
1262
|
-
|
1263
|
-
|
1264
|
-
|
1265
|
-
|
1266
|
-
|
1267
|
-
|
1268
|
-
|
1269
|
-
|
1270
|
-
|
1271
|
-
|
1272
|
-
if (needsRegister) {
|
1273
|
-
this.register('tmp1', program);
|
1274
|
-
stringOptions = 'tmp1';
|
1484
|
+
this.pushStackLiteral(this.quotedString(string));
|
1485
|
+
},
|
1486
|
+
|
1487
|
+
// [push]
|
1488
|
+
//
|
1489
|
+
// On stack, before: ...
|
1490
|
+
// On stack, after: expr, ...
|
1491
|
+
//
|
1492
|
+
// Push an expression onto the stack
|
1493
|
+
push: function(expr) {
|
1494
|
+
this.pushStack(expr);
|
1495
|
+
},
|
1496
|
+
|
1497
|
+
// [pushLiteral]
|
1498
|
+
//
|
1499
|
+
// On stack, before: ...
|
1500
|
+
// On stack, after: value, ...
|
1501
|
+
//
|
1502
|
+
// Pushes a value onto the stack. This operation prevents
|
1503
|
+
// the compiler from creating a temporary variable to hold
|
1504
|
+
// it.
|
1505
|
+
pushLiteral: function(value) {
|
1506
|
+
this.pushStackLiteral(value);
|
1507
|
+
},
|
1508
|
+
|
1509
|
+
// [pushProgram]
|
1510
|
+
//
|
1511
|
+
// On stack, before: ...
|
1512
|
+
// On stack, after: program(guid), ...
|
1513
|
+
//
|
1514
|
+
// Push a program expression onto the stack. This takes
|
1515
|
+
// a compile-time guid and converts it into a runtime-accessible
|
1516
|
+
// expression.
|
1517
|
+
pushProgram: function(guid) {
|
1518
|
+
if (guid != null) {
|
1519
|
+
this.pushStackLiteral(this.programExpression(guid));
|
1275
1520
|
} else {
|
1276
|
-
|
1277
|
-
}
|
1278
|
-
|
1279
|
-
if (needsRegister) {
|
1280
|
-
var hash = (hasHash ? this.popStack() : '{}');
|
1281
|
-
this.source.push('tmp1.hash = ' + hash + ';');
|
1282
|
-
}
|
1283
|
-
|
1284
|
-
if(this.options.stringParams) {
|
1285
|
-
this.source.push('tmp1.contexts = [];');
|
1286
|
-
}
|
1287
|
-
|
1288
|
-
for(var i=0; i<paramSize; i++) {
|
1289
|
-
param = this.popStack();
|
1290
|
-
params.push(param);
|
1291
|
-
|
1292
|
-
if(this.options.stringParams) {
|
1293
|
-
this.source.push('tmp1.contexts.push(' + this.popStack() + ');');
|
1294
|
-
}
|
1295
|
-
}
|
1296
|
-
|
1297
|
-
if(inverse) {
|
1298
|
-
this.source.push('tmp1.fn = tmp1;');
|
1299
|
-
this.source.push('tmp1.inverse = ' + inverse + ';');
|
1300
|
-
}
|
1301
|
-
|
1302
|
-
if(this.options.data) {
|
1303
|
-
this.source.push('tmp1.data = data;');
|
1521
|
+
this.pushStackLiteral(null);
|
1304
1522
|
}
|
1305
|
-
|
1306
|
-
params.push(stringOptions);
|
1307
|
-
|
1308
|
-
this.populateCall(params, id, helperId || id, fn, program !== '{}');
|
1309
1523
|
},
|
1310
1524
|
|
1311
|
-
|
1312
|
-
|
1313
|
-
|
1314
|
-
|
1525
|
+
// [invokeHelper]
|
1526
|
+
//
|
1527
|
+
// On stack, before: hash, inverse, program, params..., ...
|
1528
|
+
// On stack, after: result of helper invocation
|
1529
|
+
//
|
1530
|
+
// Pops off the helper's parameters, invokes the helper,
|
1531
|
+
// and pushes the helper's return value onto the stack.
|
1532
|
+
//
|
1533
|
+
// If the helper is not found, `helperMissing` is called.
|
1534
|
+
invokeHelper: function(paramSize, name) {
|
1535
|
+
this.context.aliases.helperMissing = 'helpers.helperMissing';
|
1536
|
+
|
1537
|
+
var helper = this.lastHelper = this.setupHelper(paramSize, name);
|
1538
|
+
this.register('foundHelper', helper.name);
|
1539
|
+
|
1540
|
+
this.pushStack("foundHelper ? foundHelper.call(" +
|
1541
|
+
helper.callParams + ") " + ": helperMissing.call(" +
|
1542
|
+
helper.helperMissingParams + ")");
|
1543
|
+
},
|
1544
|
+
|
1545
|
+
// [invokeKnownHelper]
|
1546
|
+
//
|
1547
|
+
// On stack, before: hash, inverse, program, params..., ...
|
1548
|
+
// On stack, after: result of helper invocation
|
1549
|
+
//
|
1550
|
+
// This operation is used when the helper is known to exist,
|
1551
|
+
// so a `helperMissing` fallback is not required.
|
1552
|
+
invokeKnownHelper: function(paramSize, name) {
|
1553
|
+
var helper = this.setupHelper(paramSize, name);
|
1554
|
+
this.pushStack(helper.name + ".call(" + helper.callParams + ")");
|
1555
|
+
},
|
1556
|
+
|
1557
|
+
// [invokeAmbiguous]
|
1558
|
+
//
|
1559
|
+
// On stack, before: hash, inverse, program, params..., ...
|
1560
|
+
// On stack, after: result of disambiguation
|
1561
|
+
//
|
1562
|
+
// This operation is used when an expression like `{{foo}}`
|
1563
|
+
// is provided, but we don't know at compile-time whether it
|
1564
|
+
// is a helper or a path.
|
1565
|
+
//
|
1566
|
+
// This operation emits more code than the other options,
|
1567
|
+
// and can be avoided by passing the `knownHelpers` and
|
1568
|
+
// `knownHelpersOnly` flags at compile-time.
|
1569
|
+
invokeAmbiguous: function(name) {
|
1570
|
+
this.context.aliases.functionType = '"function"';
|
1571
|
+
|
1572
|
+
this.pushStackLiteral('{}');
|
1573
|
+
var helper = this.setupHelper(0, name);
|
1574
|
+
|
1575
|
+
var helperName = this.lastHelper = this.nameLookup('helpers', name, 'helper');
|
1576
|
+
this.register('foundHelper', helperName);
|
1577
|
+
|
1578
|
+
var nonHelper = this.nameLookup('depth' + this.lastContext, name, 'context');
|
1315
1579
|
var nextStack = this.nextStack();
|
1316
1580
|
|
1317
|
-
if (
|
1318
|
-
|
1319
|
-
} else {
|
1320
|
-
this.context.aliases.functionType = '"function"';
|
1321
|
-
var condition = program ? "foundHelper && " : ""
|
1322
|
-
this.source.push("if(" + condition + "typeof " + id + " === functionType) { " + nextStack + " = " + id + ".call(" + paramString + "); }");
|
1323
|
-
}
|
1324
|
-
fn.call(this, nextStack, helperMissingString, id);
|
1325
|
-
this.usingKnownHelper = false;
|
1581
|
+
this.source.push('if (foundHelper) { ' + nextStack + ' = foundHelper.call(' + helper.callParams + '); }');
|
1582
|
+
this.source.push('else { ' + nextStack + ' = ' + nonHelper + '; ' + nextStack + ' = typeof ' + nextStack + ' === functionType ? ' + nextStack + '() : ' + nextStack + '; }');
|
1326
1583
|
},
|
1327
1584
|
|
1328
|
-
invokePartial
|
1329
|
-
|
1585
|
+
// [invokePartial]
|
1586
|
+
//
|
1587
|
+
// On stack, before: context, ...
|
1588
|
+
// On stack after: result of partial invocation
|
1589
|
+
//
|
1590
|
+
// This operation pops off a context, invokes a partial with that context,
|
1591
|
+
// and pushes the result of the invocation back.
|
1592
|
+
invokePartial: function(name) {
|
1593
|
+
var params = [this.nameLookup('partials', name, 'partial'), "'" + name + "'", this.popStack(), "helpers", "partials"];
|
1330
1594
|
|
1331
1595
|
if (this.options.data) {
|
1332
1596
|
params.push("data");
|
1333
1597
|
}
|
1334
1598
|
|
1599
|
+
this.context.aliases.self = "this";
|
1335
1600
|
this.pushStack("self.invokePartial(" + params.join(", ") + ");");
|
1336
1601
|
},
|
1337
1602
|
|
1603
|
+
// [assignToHash]
|
1604
|
+
//
|
1605
|
+
// On stack, before: value, hash, ...
|
1606
|
+
// On stack, after: hash, ...
|
1607
|
+
//
|
1608
|
+
// Pops a value and hash off the stack, assigns `hash[key] = value`
|
1609
|
+
// and pushes the hash back onto the stack.
|
1338
1610
|
assignToHash: function(key) {
|
1339
1611
|
var value = this.popStack();
|
1340
1612
|
var hash = this.topStack();
|
@@ -1362,10 +1634,15 @@ Handlebars.JavaScriptCompiler = function() {};
|
|
1362
1634
|
},
|
1363
1635
|
|
1364
1636
|
programExpression: function(guid) {
|
1365
|
-
|
1637
|
+
this.context.aliases.self = "this";
|
1638
|
+
|
1639
|
+
if(guid == null) {
|
1640
|
+
return "self.noop";
|
1641
|
+
}
|
1366
1642
|
|
1367
1643
|
var child = this.environment.children[guid],
|
1368
|
-
depths = child.depths.list;
|
1644
|
+
depths = child.depths.list, depth;
|
1645
|
+
|
1369
1646
|
var programParams = [child.index, child.name, "data"];
|
1370
1647
|
|
1371
1648
|
for(var i=0, l = depths.length; i<l; i++) {
|
@@ -1389,29 +1666,61 @@ Handlebars.JavaScriptCompiler = function() {};
|
|
1389
1666
|
},
|
1390
1667
|
|
1391
1668
|
useRegister: function(name) {
|
1392
|
-
if(!this.
|
1393
|
-
this.
|
1394
|
-
this.
|
1669
|
+
if(!this.registers[name]) {
|
1670
|
+
this.registers[name] = true;
|
1671
|
+
this.registers.list.push(name);
|
1395
1672
|
}
|
1396
1673
|
},
|
1397
1674
|
|
1675
|
+
pushStackLiteral: function(item) {
|
1676
|
+
this.compileStack.push(new Literal(item));
|
1677
|
+
return item;
|
1678
|
+
},
|
1679
|
+
|
1398
1680
|
pushStack: function(item) {
|
1399
|
-
this.source.push(this.
|
1681
|
+
this.source.push(this.incrStack() + " = " + item + ";");
|
1682
|
+
this.compileStack.push("stack" + this.stackSlot);
|
1683
|
+
return "stack" + this.stackSlot;
|
1684
|
+
},
|
1685
|
+
|
1686
|
+
replaceStack: function(callback) {
|
1687
|
+
var item = callback.call(this, this.topStack());
|
1688
|
+
|
1689
|
+
this.source.push(this.topStack() + " = " + item + ";");
|
1400
1690
|
return "stack" + this.stackSlot;
|
1401
1691
|
},
|
1402
1692
|
|
1403
|
-
nextStack: function() {
|
1693
|
+
nextStack: function(skipCompileStack) {
|
1694
|
+
var name = this.incrStack();
|
1695
|
+
this.compileStack.push("stack" + this.stackSlot);
|
1696
|
+
return name;
|
1697
|
+
},
|
1698
|
+
|
1699
|
+
incrStack: function() {
|
1404
1700
|
this.stackSlot++;
|
1405
1701
|
if(this.stackSlot > this.stackVars.length) { this.stackVars.push("stack" + this.stackSlot); }
|
1406
1702
|
return "stack" + this.stackSlot;
|
1407
1703
|
},
|
1408
1704
|
|
1409
1705
|
popStack: function() {
|
1410
|
-
|
1706
|
+
var item = this.compileStack.pop();
|
1707
|
+
|
1708
|
+
if (item instanceof Literal) {
|
1709
|
+
return item.value;
|
1710
|
+
} else {
|
1711
|
+
this.stackSlot--;
|
1712
|
+
return item;
|
1713
|
+
}
|
1411
1714
|
},
|
1412
1715
|
|
1413
1716
|
topStack: function() {
|
1414
|
-
|
1717
|
+
var item = this.compileStack[this.compileStack.length - 1];
|
1718
|
+
|
1719
|
+
if (item instanceof Literal) {
|
1720
|
+
return item.value;
|
1721
|
+
} else {
|
1722
|
+
return item;
|
1723
|
+
}
|
1415
1724
|
},
|
1416
1725
|
|
1417
1726
|
quotedString: function(str) {
|
@@ -1420,6 +1729,67 @@ Handlebars.JavaScriptCompiler = function() {};
|
|
1420
1729
|
.replace(/"/g, '\\"')
|
1421
1730
|
.replace(/\n/g, '\\n')
|
1422
1731
|
.replace(/\r/g, '\\r') + '"';
|
1732
|
+
},
|
1733
|
+
|
1734
|
+
setupHelper: function(paramSize, name) {
|
1735
|
+
var params = [];
|
1736
|
+
this.setupParams(paramSize, params);
|
1737
|
+
var foundHelper = this.nameLookup('helpers', name, 'helper');
|
1738
|
+
|
1739
|
+
return {
|
1740
|
+
params: params,
|
1741
|
+
name: foundHelper,
|
1742
|
+
callParams: ["depth0"].concat(params).join(", "),
|
1743
|
+
helperMissingParams: ["depth0", this.quotedString(name)].concat(params).join(", ")
|
1744
|
+
};
|
1745
|
+
},
|
1746
|
+
|
1747
|
+
// the params and contexts arguments are passed in arrays
|
1748
|
+
// to fill in
|
1749
|
+
setupParams: function(paramSize, params) {
|
1750
|
+
var options = [], contexts = [], param, inverse, program;
|
1751
|
+
|
1752
|
+
options.push("hash:" + this.popStack());
|
1753
|
+
|
1754
|
+
inverse = this.popStack();
|
1755
|
+
program = this.popStack();
|
1756
|
+
|
1757
|
+
// Avoid setting fn and inverse if neither are set. This allows
|
1758
|
+
// helpers to do a check for `if (options.fn)`
|
1759
|
+
if (program || inverse) {
|
1760
|
+
if (!program) {
|
1761
|
+
this.context.aliases.self = "this";
|
1762
|
+
program = "self.noop";
|
1763
|
+
}
|
1764
|
+
|
1765
|
+
if (!inverse) {
|
1766
|
+
this.context.aliases.self = "this";
|
1767
|
+
inverse = "self.noop";
|
1768
|
+
}
|
1769
|
+
|
1770
|
+
options.push("inverse:" + inverse);
|
1771
|
+
options.push("fn:" + program);
|
1772
|
+
}
|
1773
|
+
|
1774
|
+
for(var i=0; i<paramSize; i++) {
|
1775
|
+
param = this.popStack();
|
1776
|
+
params.push(param);
|
1777
|
+
|
1778
|
+
if(this.options.stringParams) {
|
1779
|
+
contexts.push(this.popStack());
|
1780
|
+
}
|
1781
|
+
}
|
1782
|
+
|
1783
|
+
if (this.options.stringParams) {
|
1784
|
+
options.push("contexts:[" + contexts.join(",") + "]");
|
1785
|
+
}
|
1786
|
+
|
1787
|
+
if(this.options.data) {
|
1788
|
+
options.push("data:data");
|
1789
|
+
}
|
1790
|
+
|
1791
|
+
params.push("{" + options.join(",") + "}");
|
1792
|
+
return params.join(", ");
|
1423
1793
|
}
|
1424
1794
|
};
|
1425
1795
|
|
@@ -1447,12 +1817,12 @@ Handlebars.JavaScriptCompiler = function() {};
|
|
1447
1817
|
compilerWords[reservedWords[i]] = true;
|
1448
1818
|
}
|
1449
1819
|
|
1450
|
-
|
1451
|
-
|
1452
|
-
|
1453
|
-
|
1454
|
-
|
1455
|
-
|
1820
|
+
JavaScriptCompiler.isValidJavaScriptVariableName = function(name) {
|
1821
|
+
if(!JavaScriptCompiler.RESERVED_WORDS[name] && /^[a-zA-Z_$][0-9a-zA-Z_$]+$/.test(name)) {
|
1822
|
+
return true;
|
1823
|
+
}
|
1824
|
+
return false;
|
1825
|
+
};
|
1456
1826
|
|
1457
1827
|
})(Handlebars.Compiler, Handlebars.JavaScriptCompiler);
|
1458
1828
|
|
@@ -1531,7 +1901,7 @@ Handlebars.VM = {
|
|
1531
1901
|
},
|
1532
1902
|
noop: function() { return ""; },
|
1533
1903
|
invokePartial: function(partial, name, context, helpers, partials, data) {
|
1534
|
-
options = { helpers: helpers, partials: partials, data: data };
|
1904
|
+
var options = { helpers: helpers, partials: partials, data: data };
|
1535
1905
|
|
1536
1906
|
if(partial === undefined) {
|
1537
1907
|
throw new Handlebars.Exception("The partial " + name + " could not be found");
|
@@ -1540,7 +1910,7 @@ Handlebars.VM = {
|
|
1540
1910
|
} else if (!Handlebars.compile) {
|
1541
1911
|
throw new Handlebars.Exception("The partial " + name + " could not be compiled when running in runtime-only mode");
|
1542
1912
|
} else {
|
1543
|
-
partials[name] = Handlebars.compile(partial);
|
1913
|
+
partials[name] = Handlebars.compile(partial, {data: data !== undefined});
|
1544
1914
|
return partials[name](context, options);
|
1545
1915
|
}
|
1546
1916
|
}
|