handlebars 0.3.2 → 0.4.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/lib/handlebars/context.rb +3 -5
- data/lib/handlebars/version.rb +1 -1
- data/spec/handlebars_spec.rb +3 -3
- data/vendor/handlebars/.gitignore +3 -1
- data/vendor/handlebars/.jshintrc +2 -0
- data/vendor/handlebars/.npmignore +0 -1
- data/vendor/handlebars/.rspec +1 -0
- data/vendor/handlebars/Gemfile +1 -1
- data/vendor/handlebars/LICENSE +0 -1
- data/vendor/handlebars/README.markdown +8 -6
- data/vendor/handlebars/Rakefile +14 -21
- data/vendor/handlebars/bench/benchwarmer.js +1 -1
- data/vendor/handlebars/bench/handlebars.js +43 -34
- data/vendor/handlebars/bin/handlebars +56 -2
- data/vendor/handlebars/dist/handlebars.js +2201 -0
- data/vendor/handlebars/dist/handlebars.runtime.js +321 -0
- data/vendor/handlebars/lib/handlebars/base.js +68 -15
- data/vendor/handlebars/lib/handlebars/compiler/ast.js +50 -20
- data/vendor/handlebars/lib/handlebars/compiler/base.js +7 -13
- data/vendor/handlebars/lib/handlebars/compiler/compiler.js +758 -299
- data/vendor/handlebars/lib/handlebars/compiler/printer.js +24 -30
- data/vendor/handlebars/lib/handlebars/runtime.js +23 -3
- data/vendor/handlebars/lib/handlebars/utils.js +9 -10
- data/vendor/handlebars/package.json +15 -5
- data/vendor/handlebars/spec/acceptance_spec.rb +5 -5
- data/vendor/handlebars/spec/parser_spec.rb +201 -32
- data/vendor/handlebars/spec/qunit_spec.js +462 -159
- data/vendor/handlebars/spec/spec_helper.rb +7 -7
- data/vendor/handlebars/spec/tokenizer_spec.rb +55 -8
- data/vendor/handlebars/src/handlebars.l +14 -3
- data/vendor/handlebars/src/handlebars.yy +15 -5
- data/vendor/handlebars/src/parser-prefix.js +1 -0
- data/vendor/handlebars/src/parser-suffix.js +4 -0
- metadata +8 -3
@@ -18,31 +18,17 @@ Handlebars.PrintVisitor.prototype.pad = function(string, newline) {
|
|
18
18
|
};
|
19
19
|
|
20
20
|
Handlebars.PrintVisitor.prototype.program = function(program) {
|
21
|
-
var out =
|
21
|
+
var out = "",
|
22
22
|
statements = program.statements,
|
23
23
|
inverse = program.inverse,
|
24
24
|
i, l;
|
25
25
|
|
26
|
-
this.padding++;
|
27
|
-
|
28
26
|
for(i=0, l=statements.length; i<l; i++) {
|
29
27
|
out = out + this.accept(statements[i]);
|
30
28
|
}
|
31
29
|
|
32
30
|
this.padding--;
|
33
31
|
|
34
|
-
if(inverse) {
|
35
|
-
out = out + this.pad("{{^}}");
|
36
|
-
|
37
|
-
this.padding++;
|
38
|
-
|
39
|
-
for(i=0, l=inverse.statements.length; i<l; i++) {
|
40
|
-
out = out + this.accept(inverse.statements[i]);
|
41
|
-
}
|
42
|
-
}
|
43
|
-
|
44
|
-
this.padding--;
|
45
|
-
|
46
32
|
return out;
|
47
33
|
};
|
48
34
|
|
@@ -52,25 +38,25 @@ Handlebars.PrintVisitor.prototype.block = function(block) {
|
|
52
38
|
out = out + this.pad("BLOCK:");
|
53
39
|
this.padding++;
|
54
40
|
out = out + this.accept(block.mustache);
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
41
|
+
if (block.program) {
|
42
|
+
out = out + this.pad("PROGRAM:");
|
43
|
+
this.padding++;
|
44
|
+
out = out + this.accept(block.program);
|
45
|
+
this.padding--;
|
46
|
+
}
|
47
|
+
if (block.inverse) {
|
48
|
+
if (block.program) { this.padding++; }
|
49
|
+
out = out + this.pad("{{^}}");
|
50
|
+
this.padding++;
|
51
|
+
out = out + this.accept(block.inverse);
|
52
|
+
this.padding--;
|
53
|
+
if (block.program) { this.padding--; }
|
54
|
+
}
|
68
55
|
this.padding--;
|
69
56
|
|
70
57
|
return out;
|
71
58
|
};
|
72
59
|
|
73
|
-
|
74
60
|
Handlebars.PrintVisitor.prototype.mustache = function(mustache) {
|
75
61
|
var params = mustache.params, paramStrings = [], hash;
|
76
62
|
|
@@ -86,7 +72,7 @@ Handlebars.PrintVisitor.prototype.mustache = function(mustache) {
|
|
86
72
|
};
|
87
73
|
|
88
74
|
Handlebars.PrintVisitor.prototype.partial = function(partial) {
|
89
|
-
var content = this.accept(partial.
|
75
|
+
var content = this.accept(partial.partialName);
|
90
76
|
if(partial.context) { content = content + " " + this.accept(partial.context); }
|
91
77
|
return this.pad("{{> " + content + " }}");
|
92
78
|
};
|
@@ -125,6 +111,14 @@ Handlebars.PrintVisitor.prototype.ID = function(id) {
|
|
125
111
|
}
|
126
112
|
};
|
127
113
|
|
114
|
+
Handlebars.PrintVisitor.prototype.PARTIAL_NAME = function(partialName) {
|
115
|
+
return "PARTIAL:" + partialName.name;
|
116
|
+
};
|
117
|
+
|
118
|
+
Handlebars.PrintVisitor.prototype.DATA = function(data) {
|
119
|
+
return "@" + data.id;
|
120
|
+
};
|
121
|
+
|
128
122
|
Handlebars.PrintVisitor.prototype.content = function(content) {
|
129
123
|
return this.pad("CONTENT[ '" + content.string + "' ]");
|
130
124
|
};
|
@@ -20,12 +20,32 @@ Handlebars.VM = {
|
|
20
20
|
}
|
21
21
|
},
|
22
22
|
programWithDepth: Handlebars.VM.programWithDepth,
|
23
|
-
noop: Handlebars.VM.noop
|
23
|
+
noop: Handlebars.VM.noop,
|
24
|
+
compilerInfo: null
|
24
25
|
};
|
25
26
|
|
26
27
|
return function(context, options) {
|
27
28
|
options = options || {};
|
28
|
-
|
29
|
+
var result = templateSpec.call(container, Handlebars, context, options.helpers, options.partials, options.data);
|
30
|
+
|
31
|
+
var compilerInfo = container.compilerInfo || [],
|
32
|
+
compilerRevision = compilerInfo[0] || 1,
|
33
|
+
currentRevision = Handlebars.COMPILER_REVISION;
|
34
|
+
|
35
|
+
if (compilerRevision !== currentRevision) {
|
36
|
+
if (compilerRevision < currentRevision) {
|
37
|
+
var runtimeVersions = Handlebars.REVISION_CHANGES[currentRevision],
|
38
|
+
compilerVersions = Handlebars.REVISION_CHANGES[compilerRevision];
|
39
|
+
throw "Template was precompiled with an older version of Handlebars than the current runtime. "+
|
40
|
+
"Please update your precompiler to a newer version ("+runtimeVersions+") or downgrade your runtime to an older version ("+compilerVersions+").";
|
41
|
+
} else {
|
42
|
+
// Use the embedded version info since the runtime doesn't know about this revision yet
|
43
|
+
throw "Template was precompiled with a newer version of Handlebars than the current runtime. "+
|
44
|
+
"Please update your runtime to a newer version ("+compilerInfo[1]+").";
|
45
|
+
}
|
46
|
+
}
|
47
|
+
|
48
|
+
return result;
|
29
49
|
};
|
30
50
|
},
|
31
51
|
|
@@ -56,7 +76,7 @@ Handlebars.VM = {
|
|
56
76
|
} else if (!Handlebars.compile) {
|
57
77
|
throw new Handlebars.Exception("The partial " + name + " could not be compiled when running in runtime-only mode");
|
58
78
|
} else {
|
59
|
-
partials[name] = Handlebars.compile(partial);
|
79
|
+
partials[name] = Handlebars.compile(partial, {data: data !== undefined});
|
60
80
|
return partials[name](context, options);
|
61
81
|
}
|
62
82
|
}
|
@@ -1,14 +1,16 @@
|
|
1
1
|
var Handlebars = require("./base");
|
2
2
|
|
3
3
|
// BEGIN(BROWSER)
|
4
|
+
|
5
|
+
var errorProps = ['description', 'fileName', 'lineNumber', 'message', 'name', 'number', 'stack'];
|
6
|
+
|
4
7
|
Handlebars.Exception = function(message) {
|
5
8
|
var tmp = Error.prototype.constructor.apply(this, arguments);
|
6
9
|
|
7
|
-
|
8
|
-
|
10
|
+
// Unfortunately errors are not enumerable in Chrome (at least), so `for prop in tmp` doesn't work.
|
11
|
+
for (var idx = 0; idx < errorProps.length; idx++) {
|
12
|
+
this[errorProps[idx]] = tmp[errorProps[idx]];
|
9
13
|
}
|
10
|
-
|
11
|
-
this.message = tmp.message;
|
12
14
|
};
|
13
15
|
Handlebars.Exception.prototype = new Error();
|
14
16
|
|
@@ -22,6 +24,7 @@ Handlebars.SafeString.prototype.toString = function() {
|
|
22
24
|
|
23
25
|
(function() {
|
24
26
|
var escape = {
|
27
|
+
"&": "&",
|
25
28
|
"<": "<",
|
26
29
|
">": ">",
|
27
30
|
'"': """,
|
@@ -29,7 +32,7 @@ Handlebars.SafeString.prototype.toString = function() {
|
|
29
32
|
"`": "`"
|
30
33
|
};
|
31
34
|
|
32
|
-
var badChars =
|
35
|
+
var badChars = /[&<>"'`]/g;
|
33
36
|
var possible = /[&<>"'`]/;
|
34
37
|
|
35
38
|
var escapeChar = function(chr) {
|
@@ -50,11 +53,7 @@ Handlebars.SafeString.prototype.toString = function() {
|
|
50
53
|
},
|
51
54
|
|
52
55
|
isEmpty: function(value) {
|
53
|
-
if (
|
54
|
-
return true;
|
55
|
-
} else if (value === null) {
|
56
|
-
return true;
|
57
|
-
} else if (value === false) {
|
56
|
+
if (!value && value !== 0) {
|
58
57
|
return true;
|
59
58
|
} else if(Object.prototype.toString.call(value) === "[object Array]" && value.length === 0) {
|
60
59
|
return true;
|
@@ -1,14 +1,14 @@
|
|
1
1
|
{
|
2
2
|
"name": "handlebars",
|
3
3
|
"description": "Extension of the Mustache logicless template language",
|
4
|
-
"version": "1.0.
|
4
|
+
"version": "1.0.8",
|
5
5
|
"homepage": "http://www.handlebarsjs.com/",
|
6
6
|
"keywords": [
|
7
7
|
"handlebars mustache template html"
|
8
8
|
],
|
9
9
|
"repository": {
|
10
10
|
"type": "git",
|
11
|
-
"url": "git://github.com/
|
11
|
+
"url": "git://github.com/wycats/handlebars.js.git"
|
12
12
|
},
|
13
13
|
"engines": {
|
14
14
|
"node": ">=0.4.7"
|
@@ -17,9 +17,19 @@
|
|
17
17
|
"optimist": "~0.3",
|
18
18
|
"uglify-js": "~1.2"
|
19
19
|
},
|
20
|
-
"devDependencies": {
|
20
|
+
"devDependencies": {
|
21
|
+
"benchmark": "~1.0",
|
22
|
+
"dust": "~0.3",
|
23
|
+
"jison": "~0.3",
|
24
|
+
"mocha": "*",
|
25
|
+
"mustache": "~0.7.2"
|
26
|
+
},
|
21
27
|
"main": "lib/handlebars.js",
|
22
28
|
"bin": {
|
23
29
|
"handlebars": "bin/handlebars"
|
24
|
-
}
|
25
|
-
|
30
|
+
},
|
31
|
+
"scripts": {
|
32
|
+
"test": "node_modules/.bin/mocha -u qunit spec/qunit_spec.js"
|
33
|
+
},
|
34
|
+
"optionalDependencies": {}
|
35
|
+
}
|
@@ -39,11 +39,11 @@ Module.new do
|
|
39
39
|
end
|
40
40
|
end
|
41
41
|
|
42
|
-
js_context["p"] = proc do |str|
|
42
|
+
js_context["p"] = proc do |this, str|
|
43
43
|
p str
|
44
44
|
end
|
45
45
|
|
46
|
-
js_context["ok"] = proc do |ok, message|
|
46
|
+
js_context["ok"] = proc do |this, ok, message|
|
47
47
|
js_context["$$RSPEC1$$"] = ok
|
48
48
|
|
49
49
|
result = js_context.eval("!!$$RSPEC1$$")
|
@@ -58,7 +58,7 @@ Module.new do
|
|
58
58
|
assert result, message
|
59
59
|
end
|
60
60
|
|
61
|
-
js_context["equals"] = proc do |first, second, message|
|
61
|
+
js_context["equals"] = proc do |this, first, second, message|
|
62
62
|
js_context["$$RSPEC1$$"] = first
|
63
63
|
js_context["$$RSPEC2$$"] = second
|
64
64
|
|
@@ -77,11 +77,11 @@ Module.new do
|
|
77
77
|
|
78
78
|
js_context["equal"] = js_context["equals"]
|
79
79
|
|
80
|
-
js_context["
|
80
|
+
js_context["suite"] = proc do |this, name|
|
81
81
|
test_context.module(name)
|
82
82
|
end
|
83
83
|
|
84
|
-
js_context["test"] = proc do |name, function|
|
84
|
+
js_context["test"] = proc do |this, name, function|
|
85
85
|
test_context.test(name, function)
|
86
86
|
end
|
87
87
|
|
@@ -7,11 +7,9 @@ describe "Parser" do
|
|
7
7
|
@compiles = true
|
8
8
|
end
|
9
9
|
|
10
|
-
def
|
10
|
+
def root(&block)
|
11
11
|
ASTBuilder.build do
|
12
|
-
|
13
|
-
instance_eval(&block)
|
14
|
-
end
|
12
|
+
instance_eval(&block)
|
15
13
|
end
|
16
14
|
end
|
17
15
|
|
@@ -112,115 +110,143 @@ describe "Parser" do
|
|
112
110
|
"ID:#{id}"
|
113
111
|
end
|
114
112
|
|
113
|
+
def data(id)
|
114
|
+
"@#{id}"
|
115
|
+
end
|
116
|
+
|
117
|
+
def partial_name(name)
|
118
|
+
"PARTIAL:#{name}"
|
119
|
+
end
|
120
|
+
|
115
121
|
def path(*parts)
|
116
122
|
"PATH:#{parts.join("/")}"
|
117
123
|
end
|
118
124
|
end
|
119
125
|
|
120
126
|
it "parses simple mustaches" do
|
121
|
-
ast_for("{{foo}}").should ==
|
127
|
+
ast_for("{{foo}}").should == root { mustache id("foo") }
|
128
|
+
end
|
129
|
+
|
130
|
+
it "parses simple mustaches with data" do
|
131
|
+
ast_for("{{@foo}}").should == root { mustache data("foo") }
|
122
132
|
end
|
123
133
|
|
124
134
|
it "parses mustaches with paths" do
|
125
|
-
ast_for("{{foo/bar}}").should ==
|
135
|
+
ast_for("{{foo/bar}}").should == root { mustache path("foo", "bar") }
|
126
136
|
end
|
127
137
|
|
128
138
|
it "parses mustaches with this/foo" do
|
129
|
-
ast_for("{{this/foo}}").should ==
|
139
|
+
ast_for("{{this/foo}}").should == root { mustache id("foo") }
|
130
140
|
end
|
131
141
|
|
132
142
|
it "parses mustaches with - in a path" do
|
133
|
-
ast_for("{{foo-bar}}").should ==
|
143
|
+
ast_for("{{foo-bar}}").should == root { mustache id("foo-bar") }
|
134
144
|
end
|
135
145
|
|
136
146
|
it "parses mustaches with parameters" do
|
137
|
-
ast_for("{{foo bar}}").should ==
|
147
|
+
ast_for("{{foo bar}}").should == root { mustache id("foo"), [id("bar")] }
|
138
148
|
end
|
139
149
|
|
140
150
|
it "parses mustaches with hash arguments" do
|
141
|
-
ast_for("{{foo bar=baz}}").should ==
|
151
|
+
ast_for("{{foo bar=baz}}").should == root do
|
142
152
|
mustache id("foo"), [], hash(["bar", id("baz")])
|
143
153
|
end
|
144
154
|
|
145
|
-
ast_for("{{foo bar=1}}").should ==
|
155
|
+
ast_for("{{foo bar=1}}").should == root do
|
146
156
|
mustache id("foo"), [], hash(["bar", integer("1")])
|
147
157
|
end
|
148
158
|
|
149
|
-
ast_for("{{foo bar=true}}").should ==
|
159
|
+
ast_for("{{foo bar=true}}").should == root do
|
150
160
|
mustache id("foo"), [], hash(["bar", boolean("true")])
|
151
161
|
end
|
152
162
|
|
153
|
-
ast_for("{{foo bar=false}}").should ==
|
163
|
+
ast_for("{{foo bar=false}}").should == root do
|
154
164
|
mustache id("foo"), [], hash(["bar", boolean("false")])
|
155
165
|
end
|
156
166
|
|
157
|
-
ast_for("{{foo bar
|
167
|
+
ast_for("{{foo bar=@baz}}").should == root do
|
168
|
+
mustache id("foo"), [], hash(["bar", data("baz")])
|
169
|
+
end
|
170
|
+
|
171
|
+
ast_for("{{foo bar=baz bat=bam}}").should == root do
|
158
172
|
mustache id("foo"), [], hash(["bar", "ID:baz"], ["bat", "ID:bam"])
|
159
173
|
end
|
160
174
|
|
161
|
-
ast_for("{{foo bar=baz bat=\"bam\"}}").should ==
|
175
|
+
ast_for("{{foo bar=baz bat=\"bam\"}}").should == root do
|
162
176
|
mustache id("foo"), [], hash(["bar", "ID:baz"], ["bat", "\"bam\""])
|
163
177
|
end
|
164
178
|
|
165
|
-
ast_for("{{foo
|
179
|
+
ast_for("{{foo bat='bam'}}").should == root do
|
180
|
+
mustache id("foo"), [], hash(["bat", "\"bam\""])
|
181
|
+
end
|
182
|
+
|
183
|
+
ast_for("{{foo omg bar=baz bat=\"bam\"}}").should == root do
|
166
184
|
mustache id("foo"), [id("omg")], hash(["bar", id("baz")], ["bat", string("bam")])
|
167
185
|
end
|
168
186
|
|
169
|
-
ast_for("{{foo omg bar=baz bat=\"bam\" baz=1}}").should ==
|
187
|
+
ast_for("{{foo omg bar=baz bat=\"bam\" baz=1}}").should == root do
|
170
188
|
mustache id("foo"), [id("omg")], hash(["bar", id("baz")], ["bat", string("bam")], ["baz", integer("1")])
|
171
189
|
end
|
172
190
|
|
173
|
-
ast_for("{{foo omg bar=baz bat=\"bam\" baz=true}}").should ==
|
191
|
+
ast_for("{{foo omg bar=baz bat=\"bam\" baz=true}}").should == root do
|
174
192
|
mustache id("foo"), [id("omg")], hash(["bar", id("baz")], ["bat", string("bam")], ["baz", boolean("true")])
|
175
193
|
end
|
176
194
|
|
177
|
-
ast_for("{{foo omg bar=baz bat=\"bam\" baz=false}}").should ==
|
195
|
+
ast_for("{{foo omg bar=baz bat=\"bam\" baz=false}}").should == root do
|
178
196
|
mustache id("foo"), [id("omg")], hash(["bar", id("baz")], ["bat", string("bam")], ["baz", boolean("false")])
|
179
197
|
end
|
180
198
|
end
|
181
199
|
|
182
200
|
it "parses mustaches with string parameters" do
|
183
|
-
ast_for("{{foo bar \"baz\" }}").should ==
|
201
|
+
ast_for("{{foo bar \"baz\" }}").should == root { mustache id("foo"), [id("bar"), string("baz")] }
|
184
202
|
end
|
185
203
|
|
186
204
|
it "parses mustaches with INTEGER parameters" do
|
187
|
-
ast_for("{{foo 1}}").should ==
|
205
|
+
ast_for("{{foo 1}}").should == root { mustache id("foo"), [integer("1")] }
|
188
206
|
end
|
189
207
|
|
190
208
|
it "parses mustaches with BOOLEAN parameters" do
|
191
|
-
ast_for("{{foo true}}").should ==
|
192
|
-
ast_for("{{foo false}}").should ==
|
209
|
+
ast_for("{{foo true}}").should == root { mustache id("foo"), [boolean("true")] }
|
210
|
+
ast_for("{{foo false}}").should == root { mustache id("foo"), [boolean("false")] }
|
211
|
+
end
|
212
|
+
|
213
|
+
it "parses mutaches with DATA parameters" do
|
214
|
+
ast_for("{{foo @bar}}").should == root { mustache id("foo"), [data("bar")] }
|
193
215
|
end
|
194
216
|
|
195
217
|
it "parses contents followed by a mustache" do
|
196
|
-
ast_for("foo bar {{baz}}").should ==
|
218
|
+
ast_for("foo bar {{baz}}").should == root do
|
197
219
|
content "foo bar "
|
198
220
|
mustache id("baz")
|
199
221
|
end
|
200
222
|
end
|
201
223
|
|
202
224
|
it "parses a partial" do
|
203
|
-
ast_for("{{> foo }}").should ==
|
225
|
+
ast_for("{{> foo }}").should == root { partial partial_name("foo") }
|
204
226
|
end
|
205
227
|
|
206
228
|
it "parses a partial with context" do
|
207
|
-
ast_for("{{> foo bar}}").should ==
|
229
|
+
ast_for("{{> foo bar}}").should == root { partial partial_name("foo"), id("bar") }
|
230
|
+
end
|
231
|
+
|
232
|
+
it "parses a partial with a complex name" do
|
233
|
+
ast_for("{{> shared/partial}}").should == root { partial partial_name("shared/partial") }
|
208
234
|
end
|
209
235
|
|
210
236
|
it "parses a comment" do
|
211
|
-
ast_for("{{! this is a comment }}").should ==
|
237
|
+
ast_for("{{! this is a comment }}").should == root do
|
212
238
|
comment " this is a comment "
|
213
239
|
end
|
214
240
|
end
|
215
241
|
|
216
242
|
it "parses a multi-line comment" do
|
217
|
-
ast_for("{{!\nthis is a multi-line comment\n}}").should ==
|
243
|
+
ast_for("{{!\nthis is a multi-line comment\n}}").should == root do
|
218
244
|
multiline_comment "this is a multi-line comment"
|
219
245
|
end
|
220
246
|
end
|
221
247
|
|
222
248
|
it "parses an inverse section" do
|
223
|
-
ast_for("{{#foo}} bar {{^}} baz {{/foo}}").should ==
|
249
|
+
ast_for("{{#foo}} bar {{^}} baz {{/foo}}").should == root do
|
224
250
|
block do
|
225
251
|
mustache id("foo")
|
226
252
|
|
@@ -235,12 +261,136 @@ describe "Parser" do
|
|
235
261
|
end
|
236
262
|
end
|
237
263
|
|
238
|
-
it "parses
|
239
|
-
ast_for("{{
|
240
|
-
|
264
|
+
it "parses an inverse ('else'-style) section" do
|
265
|
+
ast_for("{{#foo}} bar {{else}} baz {{/foo}}").should == root do
|
266
|
+
block do
|
267
|
+
mustache id("foo")
|
268
|
+
|
269
|
+
program do
|
270
|
+
content " bar "
|
271
|
+
end
|
272
|
+
|
273
|
+
inverse do
|
274
|
+
content " baz "
|
275
|
+
end
|
276
|
+
end
|
277
|
+
end
|
278
|
+
end
|
279
|
+
|
280
|
+
it "parses empty blocks" do
|
281
|
+
ast_for("{{#foo}}{{/foo}}").should == root do
|
282
|
+
block do
|
241
283
|
mustache id("foo")
|
242
284
|
|
243
285
|
program do
|
286
|
+
# empty program
|
287
|
+
end
|
288
|
+
end
|
289
|
+
end
|
290
|
+
end
|
291
|
+
|
292
|
+
it "parses empty blocks with empty inverse section" do
|
293
|
+
ast_for("{{#foo}}{{^}}{{/foo}}").should == root do
|
294
|
+
block do
|
295
|
+
mustache id("foo")
|
296
|
+
|
297
|
+
program do
|
298
|
+
# empty program
|
299
|
+
end
|
300
|
+
|
301
|
+
inverse do
|
302
|
+
# empty inverse
|
303
|
+
end
|
304
|
+
end
|
305
|
+
end
|
306
|
+
end
|
307
|
+
|
308
|
+
it "parses empty blocks with empty inverse ('else'-style) section" do
|
309
|
+
ast_for("{{#foo}}{{else}}{{/foo}}").should == root do
|
310
|
+
block do
|
311
|
+
mustache id("foo")
|
312
|
+
|
313
|
+
program do
|
314
|
+
# empty program
|
315
|
+
end
|
316
|
+
|
317
|
+
inverse do
|
318
|
+
# empty inverse
|
319
|
+
end
|
320
|
+
end
|
321
|
+
end
|
322
|
+
end
|
323
|
+
|
324
|
+
it "parses non-empty blocks with empty inverse section" do
|
325
|
+
ast_for("{{#foo}} bar {{^}}{{/foo}}").should == root do
|
326
|
+
block do
|
327
|
+
mustache id("foo")
|
328
|
+
|
329
|
+
program do
|
330
|
+
content " bar "
|
331
|
+
end
|
332
|
+
|
333
|
+
inverse do
|
334
|
+
# empty inverse
|
335
|
+
end
|
336
|
+
end
|
337
|
+
end
|
338
|
+
end
|
339
|
+
|
340
|
+
it "parses non-empty blocks with empty inverse ('else'-style) section" do
|
341
|
+
ast_for("{{#foo}} bar {{else}}{{/foo}}").should == root do
|
342
|
+
block do
|
343
|
+
mustache id("foo")
|
344
|
+
|
345
|
+
program do
|
346
|
+
content " bar "
|
347
|
+
end
|
348
|
+
|
349
|
+
inverse do
|
350
|
+
# empty inverse
|
351
|
+
end
|
352
|
+
end
|
353
|
+
end
|
354
|
+
end
|
355
|
+
|
356
|
+
it "parses empty blocks with non-empty inverse section" do
|
357
|
+
ast_for("{{#foo}}{{^}} bar {{/foo}}").should == root do
|
358
|
+
block do
|
359
|
+
mustache id("foo")
|
360
|
+
|
361
|
+
program do
|
362
|
+
# empty program
|
363
|
+
end
|
364
|
+
|
365
|
+
inverse do
|
366
|
+
content " bar "
|
367
|
+
end
|
368
|
+
end
|
369
|
+
end
|
370
|
+
end
|
371
|
+
|
372
|
+
it "parses empty blocks with non-empty inverse ('else'-style) section" do
|
373
|
+
ast_for("{{#foo}}{{else}} bar {{/foo}}").should == root do
|
374
|
+
block do
|
375
|
+
mustache id("foo")
|
376
|
+
|
377
|
+
program do
|
378
|
+
# empty program
|
379
|
+
end
|
380
|
+
|
381
|
+
inverse do
|
382
|
+
content " bar "
|
383
|
+
end
|
384
|
+
end
|
385
|
+
end
|
386
|
+
end
|
387
|
+
|
388
|
+
it "parses a standalone inverse section" do
|
389
|
+
ast_for("{{^foo}}bar{{/foo}}").should == root do
|
390
|
+
block do
|
391
|
+
mustache id("foo")
|
392
|
+
|
393
|
+
inverse do
|
244
394
|
content "bar"
|
245
395
|
end
|
246
396
|
end
|
@@ -261,4 +411,23 @@ describe "Parser" do
|
|
261
411
|
it "knows how to report the correct line number in errors when the first character is a newline" do
|
262
412
|
lambda { ast_for("\n\nhello\n\nmy\n\n{{foo}") }.should raise_error(V8::JSError, /Parse error on line 7/m)
|
263
413
|
end
|
414
|
+
|
415
|
+
context "externally compiled AST" do
|
416
|
+
|
417
|
+
it "can pass through an already-compiled AST" do
|
418
|
+
ast_for(@context.eval('new Handlebars.AST.ProgramNode([ new Handlebars.AST.ContentNode("Hello")]);')).should == root do
|
419
|
+
content "Hello"
|
420
|
+
end
|
421
|
+
end
|
422
|
+
|
423
|
+
it "can pass through an already-compiled AST via compile/precompile" do
|
424
|
+
@context = Handlebars::Spec::FULL_CONTEXT
|
425
|
+
|
426
|
+
code = 'Handlebars.compile(new Handlebars.AST.ProgramNode([ new Handlebars.AST.ContentNode("Hello")]))();'
|
427
|
+
@context.eval(code).should == "Hello"
|
428
|
+
|
429
|
+
code = @context.eval 'Handlebars.precompile(new Handlebars.AST.ProgramNode([ new Handlebars.AST.ContentNode("Hello")]))'
|
430
|
+
@context.eval("(#{code})(this)").should == "Hello"
|
431
|
+
end
|
432
|
+
end
|
264
433
|
end
|