handlebars_assets 0.8.2 → 0.9.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/CHANGELOG.md +5 -0
- data/Gemfile.lock +1 -1
- data/README.md +6 -13
- data/lib/handlebars_assets/tilt_handlebars.rb +1 -9
- data/lib/handlebars_assets/version.rb +1 -1
- data/test/handlebars_assets/tilt_handlebars_test.rb +1 -1
- data/vendor/assets/javascripts/handlebars.js +286 -78
- data/vendor/assets/javascripts/handlebars.runtime.js +25 -1
- metadata +2 -2
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,10 @@
|
|
1
1
|
## On master
|
2
2
|
|
3
|
+
## 0.9.0 (2013-07-25)
|
4
|
+
|
5
|
+
* Update to [this commit](https://github.com/wycats/handlebars.js/commit/a3376e24b1a25f72cf86d1d999bd2ea93fa4dc39) of `handlebars.js`
|
6
|
+
* The hack that converted partial names to underscored paths (`shared/_time` -> `_shared_time`) is no longer necessary and has been removed. You should change all the partial references in your app when going to v0.9.x.
|
7
|
+
|
3
8
|
## 0.8.2
|
4
9
|
|
5
10
|
* Update to [this commit](https://github.com/wycats/handlebars.js/commit/5e5f0dce9c352f490f1f1e58fd7d0f76dd006cac) of `handlebars.js`
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -6,11 +6,15 @@ Yea, I think so too. That is why I wrote **handlebars_assets**. Give your Handle
|
|
6
6
|
|
7
7
|
Using `sprockets` with Sinatra or another framework? **handlebars_assets** works outside of Rails too (as of v0.2.0)
|
8
8
|
|
9
|
+
# BREAKING CHANGE IN v0.9.0
|
10
|
+
|
11
|
+
My pull request to allow `/` in partials was pulled into Handlebars. The hack that converted partial names to underscored paths (`shared/_time` -> `_shared_time`) is no longer necessary and has been removed. You should change all the partial references in your app when going to v0.9.x.
|
12
|
+
|
9
13
|
## handlebars.js
|
10
14
|
|
11
15
|
**Please read**
|
12
16
|
|
13
|
-
|
17
|
+
`handlebars_assets` is packaged with an edge build of `handlebars.js` (this [commit](https://github.com/wycats/handlebars.js/commit/a3376e24b1a25f72cf86d1d999bd2ea93fa4dc39). See the section on using another version if that does not work for you.
|
14
18
|
|
15
19
|
## Installation with Rails 3.1+
|
16
20
|
|
@@ -132,18 +136,7 @@ The Haml will be pre-processed so that the Handlebars template is basically this
|
|
132
136
|
|
133
137
|
If you begin the name of the template with an underscore, it will be recognized as a partial. You can invoke partials inside a template using the Handlebars partial syntax:
|
134
138
|
|
135
|
-
Invoke a {{>
|
136
|
-
|
137
|
-
**Important!** Handlebars does not understand nested partials. To support them, partials are named based on their path using `_` instead of `/` (skid => slash). So given:
|
138
|
-
|
139
|
-
templates/
|
140
|
-
_form.hbs
|
141
|
-
contacts/
|
142
|
-
_form.hbs
|
143
|
-
todos/
|
144
|
-
_form.hbs
|
145
|
-
|
146
|
-
You will get three partials named `_form`, `_contacts_form`, and `_todos_form`; note that the partials begin with `_`.
|
139
|
+
Invoke a {{> path/to/_partial }}
|
147
140
|
|
148
141
|
## Using another version of `handlebars.js`
|
149
142
|
|
@@ -78,25 +78,17 @@ module HandlebarsAssets
|
|
78
78
|
end
|
79
79
|
|
80
80
|
def name
|
81
|
-
|
81
|
+
template_name
|
82
82
|
end
|
83
83
|
|
84
84
|
private
|
85
85
|
|
86
86
|
attr_accessor :full_path, :template_path
|
87
87
|
|
88
|
-
def forced_underscore_name
|
89
|
-
'_' + relative_path
|
90
|
-
end
|
91
|
-
|
92
88
|
def relative_path
|
93
89
|
template_path.gsub(/^#{HandlebarsAssets::Config.path_prefix}\/(.*)$/i, "\\1")
|
94
90
|
end
|
95
91
|
|
96
|
-
def partial_name
|
97
|
-
forced_underscore_name.gsub(/\//, '_').gsub(/__/, '_').dump
|
98
|
-
end
|
99
|
-
|
100
92
|
def template_name
|
101
93
|
relative_path.dump
|
102
94
|
end
|
@@ -63,7 +63,7 @@ module HandlebarsAssets
|
|
63
63
|
|
64
64
|
template2 = HandlebarsAssets::TiltHandlebars.new(scope2.pathname.to_s) { source }
|
65
65
|
|
66
|
-
assert_equal hbs_compiled_partial('
|
66
|
+
assert_equal hbs_compiled_partial('some/thing/_test_underscore', source), template2.render(scope2, {})
|
67
67
|
end
|
68
68
|
|
69
69
|
def test_without_known_helpers_opt
|
@@ -1,3 +1,27 @@
|
|
1
|
+
/*
|
2
|
+
|
3
|
+
Copyright (C) 2011 by Yehuda Katz
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
22
|
+
|
23
|
+
*/
|
24
|
+
|
1
25
|
// lib/handlebars/base.js
|
2
26
|
|
3
27
|
/*jshint eqnull:true*/
|
@@ -5,7 +29,7 @@ this.Handlebars = {};
|
|
5
29
|
|
6
30
|
(function(Handlebars) {
|
7
31
|
|
8
|
-
Handlebars.VERSION = "1.0.rc.
|
32
|
+
Handlebars.VERSION = "1.0.rc.2";
|
9
33
|
|
10
34
|
Handlebars.helpers = {};
|
11
35
|
Handlebars.partials = {};
|
@@ -702,8 +726,11 @@ Handlebars.print = function(ast) {
|
|
702
726
|
for(var i=0,l=parts.length; i<l; i++) {
|
703
727
|
var part = parts[i];
|
704
728
|
|
705
|
-
if(part === "..") {
|
706
|
-
|
729
|
+
if (part === ".." || part === "." || part === "this") {
|
730
|
+
if (dig.length > 0) { throw new Handlebars.Exception("Invalid path: " + this.original); }
|
731
|
+
else if (part === "..") { depth++; }
|
732
|
+
else { this.isScoped = true; }
|
733
|
+
}
|
707
734
|
else { dig.push(part); }
|
708
735
|
}
|
709
736
|
|
@@ -714,6 +741,8 @@ Handlebars.print = function(ast) {
|
|
714
741
|
// an ID is simple if it only has one part, and that part is not
|
715
742
|
// `..` or `this`.
|
716
743
|
this.isSimple = parts.length === 1 && !this.isScoped && depth === 0;
|
744
|
+
|
745
|
+
this.stringModeValue = this.string;
|
717
746
|
};
|
718
747
|
|
719
748
|
Handlebars.AST.PartialNameNode = function(name) {
|
@@ -729,16 +758,19 @@ Handlebars.print = function(ast) {
|
|
729
758
|
Handlebars.AST.StringNode = function(string) {
|
730
759
|
this.type = "STRING";
|
731
760
|
this.string = string;
|
761
|
+
this.stringModeValue = string;
|
732
762
|
};
|
733
763
|
|
734
764
|
Handlebars.AST.IntegerNode = function(integer) {
|
735
765
|
this.type = "INTEGER";
|
736
766
|
this.integer = integer;
|
767
|
+
this.stringModeValue = Number(integer);
|
737
768
|
};
|
738
769
|
|
739
770
|
Handlebars.AST.BooleanNode = function(bool) {
|
740
771
|
this.type = "BOOLEAN";
|
741
772
|
this.bool = bool;
|
773
|
+
this.stringModeValue = bool === "true";
|
742
774
|
};
|
743
775
|
|
744
776
|
Handlebars.AST.CommentNode = function(comment) {
|
@@ -848,6 +880,26 @@ Handlebars.JavaScriptCompiler = function() {};
|
|
848
880
|
|
849
881
|
return out.join("\n");
|
850
882
|
},
|
883
|
+
equals: function(other) {
|
884
|
+
var len = this.opcodes.length;
|
885
|
+
if (other.opcodes.length !== len) {
|
886
|
+
return false;
|
887
|
+
}
|
888
|
+
|
889
|
+
for (var i = 0; i < len; i++) {
|
890
|
+
var opcode = this.opcodes[i],
|
891
|
+
otherOpcode = other.opcodes[i];
|
892
|
+
if (opcode.opcode !== otherOpcode.opcode || opcode.args.length !== otherOpcode.args.length) {
|
893
|
+
return false;
|
894
|
+
}
|
895
|
+
for (var j = 0; j < opcode.args.length; j++) {
|
896
|
+
if (opcode.args[j] !== otherOpcode.args[j]) {
|
897
|
+
return false;
|
898
|
+
}
|
899
|
+
}
|
900
|
+
}
|
901
|
+
return true;
|
902
|
+
},
|
851
903
|
|
852
904
|
guid: 0,
|
853
905
|
|
@@ -939,7 +991,7 @@ Handlebars.JavaScriptCompiler = function() {};
|
|
939
991
|
// evaluate it by executing `blockHelperMissing`
|
940
992
|
this.opcode('pushProgram', program);
|
941
993
|
this.opcode('pushProgram', inverse);
|
942
|
-
this.opcode('
|
994
|
+
this.opcode('emptyHash');
|
943
995
|
this.opcode('blockValue');
|
944
996
|
} else {
|
945
997
|
this.ambiguousMustache(mustache, program, inverse);
|
@@ -948,7 +1000,7 @@ Handlebars.JavaScriptCompiler = function() {};
|
|
948
1000
|
// evaluate it by executing `blockHelperMissing`
|
949
1001
|
this.opcode('pushProgram', program);
|
950
1002
|
this.opcode('pushProgram', inverse);
|
951
|
-
this.opcode('
|
1003
|
+
this.opcode('emptyHash');
|
952
1004
|
this.opcode('ambiguousBlockValue');
|
953
1005
|
}
|
954
1006
|
|
@@ -958,15 +1010,21 @@ Handlebars.JavaScriptCompiler = function() {};
|
|
958
1010
|
hash: function(hash) {
|
959
1011
|
var pairs = hash.pairs, pair, val;
|
960
1012
|
|
961
|
-
this.opcode('
|
1013
|
+
this.opcode('pushHash');
|
962
1014
|
|
963
1015
|
for(var i=0, l=pairs.length; i<l; i++) {
|
964
1016
|
pair = pairs[i];
|
965
1017
|
val = pair[1];
|
966
1018
|
|
967
|
-
this.
|
1019
|
+
if (this.options.stringParams) {
|
1020
|
+
this.opcode('pushStringParam', val.stringModeValue, val.type);
|
1021
|
+
} else {
|
1022
|
+
this.accept(val);
|
1023
|
+
}
|
1024
|
+
|
968
1025
|
this.opcode('assignToHash', pair[0]);
|
969
1026
|
}
|
1027
|
+
this.opcode('popHash');
|
970
1028
|
},
|
971
1029
|
|
972
1030
|
partial: function(partial) {
|
@@ -1007,17 +1065,19 @@ Handlebars.JavaScriptCompiler = function() {};
|
|
1007
1065
|
},
|
1008
1066
|
|
1009
1067
|
ambiguousMustache: function(mustache, program, inverse) {
|
1010
|
-
var id = mustache.id,
|
1068
|
+
var id = mustache.id,
|
1069
|
+
name = id.parts[0],
|
1070
|
+
isBlock = program != null || inverse != null;
|
1011
1071
|
|
1012
1072
|
this.opcode('getContext', id.depth);
|
1013
1073
|
|
1014
1074
|
this.opcode('pushProgram', program);
|
1015
1075
|
this.opcode('pushProgram', inverse);
|
1016
1076
|
|
1017
|
-
this.opcode('invokeAmbiguous', name);
|
1077
|
+
this.opcode('invokeAmbiguous', name, isBlock);
|
1018
1078
|
},
|
1019
1079
|
|
1020
|
-
simpleMustache: function(mustache
|
1080
|
+
simpleMustache: function(mustache) {
|
1021
1081
|
var id = mustache.id;
|
1022
1082
|
|
1023
1083
|
if (id.type === 'DATA') {
|
@@ -1134,7 +1194,7 @@ Handlebars.JavaScriptCompiler = function() {};
|
|
1134
1194
|
}
|
1135
1195
|
|
1136
1196
|
this.opcode('getContext', param.depth || 0);
|
1137
|
-
this.opcode('pushStringParam', param.
|
1197
|
+
this.opcode('pushStringParam', param.stringModeValue, param.type);
|
1138
1198
|
} else {
|
1139
1199
|
this[param.type](param);
|
1140
1200
|
}
|
@@ -1148,7 +1208,7 @@ Handlebars.JavaScriptCompiler = function() {};
|
|
1148
1208
|
if(mustache.hash) {
|
1149
1209
|
this.hash(mustache.hash);
|
1150
1210
|
} else {
|
1151
|
-
this.opcode('
|
1211
|
+
this.opcode('emptyHash');
|
1152
1212
|
}
|
1153
1213
|
|
1154
1214
|
return params;
|
@@ -1165,7 +1225,7 @@ Handlebars.JavaScriptCompiler = function() {};
|
|
1165
1225
|
if(mustache.hash) {
|
1166
1226
|
this.hash(mustache.hash);
|
1167
1227
|
} else {
|
1168
|
-
this.opcode('
|
1228
|
+
this.opcode('emptyHash');
|
1169
1229
|
}
|
1170
1230
|
|
1171
1231
|
return params;
|
@@ -1179,7 +1239,7 @@ Handlebars.JavaScriptCompiler = function() {};
|
|
1179
1239
|
JavaScriptCompiler.prototype = {
|
1180
1240
|
// PUBLIC API: You can override these methods in a subclass to provide
|
1181
1241
|
// alternative compiled forms for name lookup and buffering semantics
|
1182
|
-
nameLookup: function(parent, name, type) {
|
1242
|
+
nameLookup: function(parent, name /* , type*/) {
|
1183
1243
|
if (/^[0-9]+$/.test(name)) {
|
1184
1244
|
return parent + "[" + name + "]";
|
1185
1245
|
} else if (JavaScriptCompiler.isValidJavaScriptVariableName(name)) {
|
@@ -1194,7 +1254,11 @@ Handlebars.JavaScriptCompiler = function() {};
|
|
1194
1254
|
if (this.environment.isSimple) {
|
1195
1255
|
return "return " + string + ";";
|
1196
1256
|
} else {
|
1197
|
-
return
|
1257
|
+
return {
|
1258
|
+
appendToBuffer: true,
|
1259
|
+
content: string,
|
1260
|
+
toString: function() { return "buffer += " + string + ";"; }
|
1261
|
+
};
|
1198
1262
|
}
|
1199
1263
|
},
|
1200
1264
|
|
@@ -1215,6 +1279,7 @@ Handlebars.JavaScriptCompiler = function() {};
|
|
1215
1279
|
this.isChild = !!context;
|
1216
1280
|
this.context = context || {
|
1217
1281
|
programs: [],
|
1282
|
+
environments: [],
|
1218
1283
|
aliases: { }
|
1219
1284
|
};
|
1220
1285
|
|
@@ -1224,6 +1289,7 @@ Handlebars.JavaScriptCompiler = function() {};
|
|
1224
1289
|
this.stackVars = [];
|
1225
1290
|
this.registers = { list: [] };
|
1226
1291
|
this.compileStack = [];
|
1292
|
+
this.inlineStack = [];
|
1227
1293
|
|
1228
1294
|
this.compileChildren(environment, options);
|
1229
1295
|
|
@@ -1245,11 +1311,11 @@ Handlebars.JavaScriptCompiler = function() {};
|
|
1245
1311
|
},
|
1246
1312
|
|
1247
1313
|
nextOpcode: function() {
|
1248
|
-
var opcodes = this.environment.opcodes
|
1314
|
+
var opcodes = this.environment.opcodes;
|
1249
1315
|
return opcodes[this.i + 1];
|
1250
1316
|
},
|
1251
1317
|
|
1252
|
-
eat: function(
|
1318
|
+
eat: function() {
|
1253
1319
|
this.i = this.i + 1;
|
1254
1320
|
},
|
1255
1321
|
|
@@ -1287,7 +1353,6 @@ Handlebars.JavaScriptCompiler = function() {};
|
|
1287
1353
|
|
1288
1354
|
// Generate minimizer alias mappings
|
1289
1355
|
if (!this.isChild) {
|
1290
|
-
var aliases = [];
|
1291
1356
|
for (var alias in this.context.aliases) {
|
1292
1357
|
this.source[1] = this.source[1] + ', ' + alias + '=' + this.context.aliases[alias];
|
1293
1358
|
}
|
@@ -1312,16 +1377,42 @@ Handlebars.JavaScriptCompiler = function() {};
|
|
1312
1377
|
params.push("depth" + this.environment.depths.list[i]);
|
1313
1378
|
}
|
1314
1379
|
|
1380
|
+
// Perform a second pass over the output to merge content when possible
|
1381
|
+
var source = this.mergeSource();
|
1382
|
+
|
1315
1383
|
if (asObject) {
|
1316
|
-
params.push(
|
1384
|
+
params.push(source);
|
1317
1385
|
|
1318
1386
|
return Function.apply(this, params);
|
1319
1387
|
} else {
|
1320
|
-
var functionSource = 'function ' + (this.name || '') + '(' + params.join(',') + ') {\n ' +
|
1388
|
+
var functionSource = 'function ' + (this.name || '') + '(' + params.join(',') + ') {\n ' + source + '}';
|
1321
1389
|
Handlebars.log(Handlebars.logger.DEBUG, functionSource + "\n\n");
|
1322
1390
|
return functionSource;
|
1323
1391
|
}
|
1324
1392
|
},
|
1393
|
+
mergeSource: function() {
|
1394
|
+
// WARN: We are not handling the case where buffer is still populated as the source should
|
1395
|
+
// not have buffer append operations as their final action.
|
1396
|
+
var source = '',
|
1397
|
+
buffer;
|
1398
|
+
for (var i = 0, len = this.source.length; i < len; i++) {
|
1399
|
+
var line = this.source[i];
|
1400
|
+
if (line.appendToBuffer) {
|
1401
|
+
if (buffer) {
|
1402
|
+
buffer = buffer + '\n + ' + line.content;
|
1403
|
+
} else {
|
1404
|
+
buffer = line.content;
|
1405
|
+
}
|
1406
|
+
} else {
|
1407
|
+
if (buffer) {
|
1408
|
+
source += 'buffer += ' + buffer + ';\n ';
|
1409
|
+
buffer = undefined;
|
1410
|
+
}
|
1411
|
+
source += line + '\n ';
|
1412
|
+
}
|
1413
|
+
}
|
1414
|
+
return source;
|
1415
|
+
},
|
1325
1416
|
|
1326
1417
|
// [blockValue]
|
1327
1418
|
//
|
@@ -1359,6 +1450,9 @@ Handlebars.JavaScriptCompiler = function() {};
|
|
1359
1450
|
var current = this.topStack();
|
1360
1451
|
params.splice(1, 0, current);
|
1361
1452
|
|
1453
|
+
// Use the options value generated from the invocation
|
1454
|
+
params[params.length-1] = 'options';
|
1455
|
+
|
1362
1456
|
this.source.push("if (!" + this.lastHelper + ") { " + current + " = blockHelperMissing.call(" + params.join(", ") + "); }");
|
1363
1457
|
},
|
1364
1458
|
|
@@ -1382,6 +1476,9 @@ Handlebars.JavaScriptCompiler = function() {};
|
|
1382
1476
|
// If `value` is truthy, or 0, it is coerced into a string and appended
|
1383
1477
|
// Otherwise, the empty string is appended
|
1384
1478
|
append: function() {
|
1479
|
+
// Force anything that is inlined onto the stack so we don't have duplication
|
1480
|
+
// when we examine local
|
1481
|
+
this.flushInline();
|
1385
1482
|
var local = this.popStack();
|
1386
1483
|
this.source.push("if(" + local + " || " + local + " === 0) { " + this.appendToBuffer(local) + " }");
|
1387
1484
|
if (this.environment.isSimple) {
|
@@ -1396,15 +1493,9 @@ Handlebars.JavaScriptCompiler = function() {};
|
|
1396
1493
|
//
|
1397
1494
|
// Escape `value` and append it to the buffer
|
1398
1495
|
appendEscaped: function() {
|
1399
|
-
var opcode = this.nextOpcode(), extra = "";
|
1400
1496
|
this.context.aliases.escapeExpression = 'this.escapeExpression';
|
1401
1497
|
|
1402
|
-
|
1403
|
-
extra = " + " + this.quotedString(opcode.args[0]);
|
1404
|
-
this.eat(opcode);
|
1405
|
-
}
|
1406
|
-
|
1407
|
-
this.source.push(this.appendToBuffer("escapeExpression(" + this.popStack() + ")" + extra));
|
1498
|
+
this.source.push(this.appendToBuffer("escapeExpression(" + this.popStack() + ")"));
|
1408
1499
|
},
|
1409
1500
|
|
1410
1501
|
// [getContext]
|
@@ -1428,7 +1519,7 @@ Handlebars.JavaScriptCompiler = function() {};
|
|
1428
1519
|
// Looks up the value of `name` on the current context and pushes
|
1429
1520
|
// it onto the stack.
|
1430
1521
|
lookupOnContext: function(name) {
|
1431
|
-
this.
|
1522
|
+
this.push(this.nameLookup('depth' + this.lastContext, name, 'context'));
|
1432
1523
|
},
|
1433
1524
|
|
1434
1525
|
// [pushContext]
|
@@ -1476,7 +1567,7 @@ Handlebars.JavaScriptCompiler = function() {};
|
|
1476
1567
|
//
|
1477
1568
|
// Push the result of looking up `id` on the current data
|
1478
1569
|
lookupData: function(id) {
|
1479
|
-
this.
|
1570
|
+
this.push(this.nameLookup('data', id, 'data'));
|
1480
1571
|
},
|
1481
1572
|
|
1482
1573
|
// [pushStringParam]
|
@@ -1487,9 +1578,36 @@ Handlebars.JavaScriptCompiler = function() {};
|
|
1487
1578
|
// This opcode is designed for use in string mode, which
|
1488
1579
|
// provides the string value of a parameter along with its
|
1489
1580
|
// depth rather than resolving it immediately.
|
1490
|
-
pushStringParam: function(string) {
|
1581
|
+
pushStringParam: function(string, type) {
|
1491
1582
|
this.pushStackLiteral('depth' + this.lastContext);
|
1492
|
-
|
1583
|
+
|
1584
|
+
this.pushString(type);
|
1585
|
+
|
1586
|
+
if (typeof string === 'string') {
|
1587
|
+
this.pushString(string);
|
1588
|
+
} else {
|
1589
|
+
this.pushStackLiteral(string);
|
1590
|
+
}
|
1591
|
+
},
|
1592
|
+
|
1593
|
+
emptyHash: function() {
|
1594
|
+
this.pushStackLiteral('{}');
|
1595
|
+
|
1596
|
+
if (this.options.stringParams) {
|
1597
|
+
this.register('hashTypes', '{}');
|
1598
|
+
}
|
1599
|
+
},
|
1600
|
+
pushHash: function() {
|
1601
|
+
this.hash = {values: [], types: []};
|
1602
|
+
},
|
1603
|
+
popHash: function() {
|
1604
|
+
var hash = this.hash;
|
1605
|
+
this.hash = undefined;
|
1606
|
+
|
1607
|
+
if (this.options.stringParams) {
|
1608
|
+
this.register('hashTypes', '{' + hash.types.join(',') + '}');
|
1609
|
+
}
|
1610
|
+
this.push('{\n ' + hash.values.join(',\n ') + '\n }');
|
1493
1611
|
},
|
1494
1612
|
|
1495
1613
|
// [pushString]
|
@@ -1509,7 +1627,8 @@ Handlebars.JavaScriptCompiler = function() {};
|
|
1509
1627
|
//
|
1510
1628
|
// Push an expression onto the stack
|
1511
1629
|
push: function(expr) {
|
1512
|
-
this.
|
1630
|
+
this.inlineStack.push(expr);
|
1631
|
+
return expr;
|
1513
1632
|
},
|
1514
1633
|
|
1515
1634
|
// [pushLiteral]
|
@@ -1552,12 +1671,14 @@ Handlebars.JavaScriptCompiler = function() {};
|
|
1552
1671
|
invokeHelper: function(paramSize, name) {
|
1553
1672
|
this.context.aliases.helperMissing = 'helpers.helperMissing';
|
1554
1673
|
|
1555
|
-
var helper = this.lastHelper = this.setupHelper(paramSize, name);
|
1556
|
-
this.register('foundHelper', helper.name);
|
1674
|
+
var helper = this.lastHelper = this.setupHelper(paramSize, name, true);
|
1557
1675
|
|
1558
|
-
this.
|
1559
|
-
|
1560
|
-
|
1676
|
+
this.push(helper.name);
|
1677
|
+
this.replaceStack(function(name) {
|
1678
|
+
return name + ' ? ' + name + '.call(' +
|
1679
|
+
helper.callParams + ") " + ": helperMissing.call(" +
|
1680
|
+
helper.helperMissingParams + ")";
|
1681
|
+
});
|
1561
1682
|
},
|
1562
1683
|
|
1563
1684
|
// [invokeKnownHelper]
|
@@ -1569,7 +1690,7 @@ Handlebars.JavaScriptCompiler = function() {};
|
|
1569
1690
|
// so a `helperMissing` fallback is not required.
|
1570
1691
|
invokeKnownHelper: function(paramSize, name) {
|
1571
1692
|
var helper = this.setupHelper(paramSize, name);
|
1572
|
-
this.
|
1693
|
+
this.push(helper.name + ".call(" + helper.callParams + ")");
|
1573
1694
|
},
|
1574
1695
|
|
1575
1696
|
// [invokeAmbiguous]
|
@@ -1584,19 +1705,18 @@ Handlebars.JavaScriptCompiler = function() {};
|
|
1584
1705
|
// This operation emits more code than the other options,
|
1585
1706
|
// and can be avoided by passing the `knownHelpers` and
|
1586
1707
|
// `knownHelpersOnly` flags at compile-time.
|
1587
|
-
invokeAmbiguous: function(name) {
|
1708
|
+
invokeAmbiguous: function(name, helperCall) {
|
1588
1709
|
this.context.aliases.functionType = '"function"';
|
1589
1710
|
|
1590
|
-
this.pushStackLiteral('{}');
|
1591
|
-
var helper = this.setupHelper(0, name);
|
1711
|
+
this.pushStackLiteral('{}'); // Hash value
|
1712
|
+
var helper = this.setupHelper(0, name, helperCall);
|
1592
1713
|
|
1593
1714
|
var helperName = this.lastHelper = this.nameLookup('helpers', name, 'helper');
|
1594
|
-
this.register('foundHelper', helperName);
|
1595
1715
|
|
1596
1716
|
var nonHelper = this.nameLookup('depth' + this.lastContext, name, 'context');
|
1597
1717
|
var nextStack = this.nextStack();
|
1598
1718
|
|
1599
|
-
this.source.push('if (
|
1719
|
+
this.source.push('if (' + nextStack + ' = ' + helperName + ') { ' + nextStack + ' = ' + nextStack + '.call(' + helper.callParams + '); }');
|
1600
1720
|
this.source.push('else { ' + nextStack + ' = ' + nonHelper + '; ' + nextStack + ' = typeof ' + nextStack + ' === functionType ? ' + nextStack + '.apply(depth0) : ' + nextStack + '; }');
|
1601
1721
|
},
|
1602
1722
|
|
@@ -1615,7 +1735,7 @@ Handlebars.JavaScriptCompiler = function() {};
|
|
1615
1735
|
}
|
1616
1736
|
|
1617
1737
|
this.context.aliases.self = "this";
|
1618
|
-
this.
|
1738
|
+
this.push("self.invokePartial(" + params.join(", ") + ")");
|
1619
1739
|
},
|
1620
1740
|
|
1621
1741
|
// [assignToHash]
|
@@ -1626,10 +1746,19 @@ Handlebars.JavaScriptCompiler = function() {};
|
|
1626
1746
|
// Pops a value and hash off the stack, assigns `hash[key] = value`
|
1627
1747
|
// and pushes the hash back onto the stack.
|
1628
1748
|
assignToHash: function(key) {
|
1629
|
-
var value = this.popStack()
|
1630
|
-
|
1749
|
+
var value = this.popStack(),
|
1750
|
+
type;
|
1631
1751
|
|
1632
|
-
this.
|
1752
|
+
if (this.options.stringParams) {
|
1753
|
+
type = this.popStack();
|
1754
|
+
this.popStack();
|
1755
|
+
}
|
1756
|
+
|
1757
|
+
var hash = this.hash;
|
1758
|
+
if (type) {
|
1759
|
+
hash.types.push("'" + key + "': " + type);
|
1760
|
+
}
|
1761
|
+
hash.values.push("'" + key + "': (" + value + ")");
|
1633
1762
|
},
|
1634
1763
|
|
1635
1764
|
// HELPERS
|
@@ -1643,11 +1772,27 @@ Handlebars.JavaScriptCompiler = function() {};
|
|
1643
1772
|
child = children[i];
|
1644
1773
|
compiler = new this.compiler();
|
1645
1774
|
|
1646
|
-
this.
|
1647
|
-
|
1648
|
-
|
1649
|
-
|
1650
|
-
|
1775
|
+
var index = this.matchExistingProgram(child);
|
1776
|
+
|
1777
|
+
if (index == null) {
|
1778
|
+
this.context.programs.push(''); // Placeholder to prevent name conflicts for nested children
|
1779
|
+
index = this.context.programs.length;
|
1780
|
+
child.index = index;
|
1781
|
+
child.name = 'program' + index;
|
1782
|
+
this.context.programs[index] = compiler.compile(child, options, this.context);
|
1783
|
+
this.context.environments[index] = child;
|
1784
|
+
} else {
|
1785
|
+
child.index = index;
|
1786
|
+
child.name = 'program' + index;
|
1787
|
+
}
|
1788
|
+
}
|
1789
|
+
},
|
1790
|
+
matchExistingProgram: function(child) {
|
1791
|
+
for (var i = 0, len = this.context.environments.length; i < len; i++) {
|
1792
|
+
var environment = this.context.environments[i];
|
1793
|
+
if (environment && environment.equals(child)) {
|
1794
|
+
return i;
|
1795
|
+
}
|
1651
1796
|
}
|
1652
1797
|
},
|
1653
1798
|
|
@@ -1691,57 +1836,111 @@ Handlebars.JavaScriptCompiler = function() {};
|
|
1691
1836
|
},
|
1692
1837
|
|
1693
1838
|
pushStackLiteral: function(item) {
|
1694
|
-
this.
|
1695
|
-
return item;
|
1839
|
+
return this.push(new Literal(item));
|
1696
1840
|
},
|
1697
1841
|
|
1698
1842
|
pushStack: function(item) {
|
1843
|
+
this.flushInline();
|
1844
|
+
|
1699
1845
|
var stack = this.incrStack();
|
1700
|
-
|
1846
|
+
if (item) {
|
1847
|
+
this.source.push(stack + " = " + item + ";");
|
1848
|
+
}
|
1701
1849
|
this.compileStack.push(stack);
|
1702
1850
|
return stack;
|
1703
1851
|
},
|
1704
1852
|
|
1705
1853
|
replaceStack: function(callback) {
|
1706
|
-
var
|
1707
|
-
|
1854
|
+
var prefix = '',
|
1855
|
+
inline = this.isInline(),
|
1856
|
+
stack;
|
1857
|
+
|
1858
|
+
// If we are currently inline then we want to merge the inline statement into the
|
1859
|
+
// replacement statement via ','
|
1860
|
+
if (inline) {
|
1861
|
+
var top = this.popStack(true);
|
1862
|
+
|
1863
|
+
if (top instanceof Literal) {
|
1864
|
+
// Literals do not need to be inlined
|
1865
|
+
stack = top.value;
|
1866
|
+
} else {
|
1867
|
+
// Get or create the current stack name for use by the inline
|
1868
|
+
var name = this.stackSlot ? this.topStackName() : this.incrStack();
|
1708
1869
|
|
1709
|
-
|
1710
|
-
|
1711
|
-
|
1870
|
+
prefix = '(' + this.push(name) + ' = ' + top + '),';
|
1871
|
+
stack = this.topStack();
|
1872
|
+
}
|
1873
|
+
} else {
|
1874
|
+
stack = this.topStack();
|
1712
1875
|
}
|
1713
1876
|
|
1714
|
-
|
1877
|
+
var item = callback.call(this, stack);
|
1878
|
+
|
1879
|
+
if (inline) {
|
1880
|
+
if (this.inlineStack.length || this.compileStack.length) {
|
1881
|
+
this.popStack();
|
1882
|
+
}
|
1883
|
+
this.push('(' + prefix + item + ')');
|
1884
|
+
} else {
|
1885
|
+
// Prevent modification of the context depth variable. Through replaceStack
|
1886
|
+
if (!/^stack/.test(stack)) {
|
1887
|
+
stack = this.nextStack();
|
1888
|
+
}
|
1889
|
+
|
1890
|
+
this.source.push(stack + " = (" + prefix + item + ");");
|
1891
|
+
}
|
1715
1892
|
return stack;
|
1716
1893
|
},
|
1717
1894
|
|
1718
|
-
nextStack: function(
|
1719
|
-
|
1720
|
-
this.compileStack.push(name);
|
1721
|
-
return name;
|
1895
|
+
nextStack: function() {
|
1896
|
+
return this.pushStack();
|
1722
1897
|
},
|
1723
1898
|
|
1724
1899
|
incrStack: function() {
|
1725
1900
|
this.stackSlot++;
|
1726
1901
|
if(this.stackSlot > this.stackVars.length) { this.stackVars.push("stack" + this.stackSlot); }
|
1902
|
+
return this.topStackName();
|
1903
|
+
},
|
1904
|
+
topStackName: function() {
|
1727
1905
|
return "stack" + this.stackSlot;
|
1728
1906
|
},
|
1907
|
+
flushInline: function() {
|
1908
|
+
var inlineStack = this.inlineStack;
|
1909
|
+
if (inlineStack.length) {
|
1910
|
+
this.inlineStack = [];
|
1911
|
+
for (var i = 0, len = inlineStack.length; i < len; i++) {
|
1912
|
+
var entry = inlineStack[i];
|
1913
|
+
if (entry instanceof Literal) {
|
1914
|
+
this.compileStack.push(entry);
|
1915
|
+
} else {
|
1916
|
+
this.pushStack(entry);
|
1917
|
+
}
|
1918
|
+
}
|
1919
|
+
}
|
1920
|
+
},
|
1921
|
+
isInline: function() {
|
1922
|
+
return this.inlineStack.length;
|
1923
|
+
},
|
1729
1924
|
|
1730
|
-
popStack: function() {
|
1731
|
-
var
|
1925
|
+
popStack: function(wrapped) {
|
1926
|
+
var inline = this.isInline(),
|
1927
|
+
item = (inline ? this.inlineStack : this.compileStack).pop();
|
1732
1928
|
|
1733
|
-
if (item instanceof Literal) {
|
1929
|
+
if (!wrapped && (item instanceof Literal)) {
|
1734
1930
|
return item.value;
|
1735
1931
|
} else {
|
1736
|
-
|
1932
|
+
if (!inline) {
|
1933
|
+
this.stackSlot--;
|
1934
|
+
}
|
1737
1935
|
return item;
|
1738
1936
|
}
|
1739
1937
|
},
|
1740
1938
|
|
1741
|
-
topStack: function() {
|
1742
|
-
var
|
1939
|
+
topStack: function(wrapped) {
|
1940
|
+
var stack = (this.isInline() ? this.inlineStack : this.compileStack),
|
1941
|
+
item = stack[stack.length - 1];
|
1743
1942
|
|
1744
|
-
if (item instanceof Literal) {
|
1943
|
+
if (!wrapped && (item instanceof Literal)) {
|
1745
1944
|
return item.value;
|
1746
1945
|
} else {
|
1747
1946
|
return item;
|
@@ -1756,23 +1955,23 @@ Handlebars.JavaScriptCompiler = function() {};
|
|
1756
1955
|
.replace(/\r/g, '\\r') + '"';
|
1757
1956
|
},
|
1758
1957
|
|
1759
|
-
setupHelper: function(paramSize, name) {
|
1958
|
+
setupHelper: function(paramSize, name, missingParams) {
|
1760
1959
|
var params = [];
|
1761
|
-
this.setupParams(paramSize, params);
|
1960
|
+
this.setupParams(paramSize, params, missingParams);
|
1762
1961
|
var foundHelper = this.nameLookup('helpers', name, 'helper');
|
1763
1962
|
|
1764
1963
|
return {
|
1765
1964
|
params: params,
|
1766
1965
|
name: foundHelper,
|
1767
1966
|
callParams: ["depth0"].concat(params).join(", "),
|
1768
|
-
helperMissingParams: ["depth0", this.quotedString(name)].concat(params).join(", ")
|
1967
|
+
helperMissingParams: missingParams && ["depth0", this.quotedString(name)].concat(params).join(", ")
|
1769
1968
|
};
|
1770
1969
|
},
|
1771
1970
|
|
1772
1971
|
// the params and contexts arguments are passed in arrays
|
1773
1972
|
// to fill in
|
1774
|
-
setupParams: function(paramSize, params) {
|
1775
|
-
var options = [], contexts = [], param, inverse, program;
|
1973
|
+
setupParams: function(paramSize, params, useRegister) {
|
1974
|
+
var options = [], contexts = [], types = [], param, inverse, program;
|
1776
1975
|
|
1777
1976
|
options.push("hash:" + this.popStack());
|
1778
1977
|
|
@@ -1801,19 +2000,28 @@ Handlebars.JavaScriptCompiler = function() {};
|
|
1801
2000
|
params.push(param);
|
1802
2001
|
|
1803
2002
|
if(this.options.stringParams) {
|
2003
|
+
types.push(this.popStack());
|
1804
2004
|
contexts.push(this.popStack());
|
1805
2005
|
}
|
1806
2006
|
}
|
1807
2007
|
|
1808
2008
|
if (this.options.stringParams) {
|
1809
2009
|
options.push("contexts:[" + contexts.join(",") + "]");
|
2010
|
+
options.push("types:[" + types.join(",") + "]");
|
2011
|
+
options.push("hashTypes:hashTypes");
|
1810
2012
|
}
|
1811
2013
|
|
1812
2014
|
if(this.options.data) {
|
1813
2015
|
options.push("data:data");
|
1814
2016
|
}
|
1815
2017
|
|
1816
|
-
|
2018
|
+
options = "{" + options.join(",") + "}";
|
2019
|
+
if (useRegister) {
|
2020
|
+
this.register('options', options);
|
2021
|
+
params.push('options');
|
2022
|
+
} else {
|
2023
|
+
params.push(options);
|
2024
|
+
}
|
1817
2025
|
return params.join(", ");
|
1818
2026
|
}
|
1819
2027
|
};
|
@@ -1,3 +1,27 @@
|
|
1
|
+
/*
|
2
|
+
|
3
|
+
Copyright (C) 2011 by Yehuda Katz
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
22
|
+
|
23
|
+
*/
|
24
|
+
|
1
25
|
// lib/handlebars/base.js
|
2
26
|
|
3
27
|
/*jshint eqnull:true*/
|
@@ -5,7 +29,7 @@ this.Handlebars = {};
|
|
5
29
|
|
6
30
|
(function(Handlebars) {
|
7
31
|
|
8
|
-
Handlebars.VERSION = "1.0.rc.
|
32
|
+
Handlebars.VERSION = "1.0.rc.2";
|
9
33
|
|
10
34
|
Handlebars.helpers = {};
|
11
35
|
Handlebars.partials = {};
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: handlebars_assets
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.9.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-01-
|
12
|
+
date: 2013-01-25 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: execjs
|