handlebars 0.3.2 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (34) hide show
  1. data/lib/handlebars/context.rb +3 -5
  2. data/lib/handlebars/version.rb +1 -1
  3. data/spec/handlebars_spec.rb +3 -3
  4. data/vendor/handlebars/.gitignore +3 -1
  5. data/vendor/handlebars/.jshintrc +2 -0
  6. data/vendor/handlebars/.npmignore +0 -1
  7. data/vendor/handlebars/.rspec +1 -0
  8. data/vendor/handlebars/Gemfile +1 -1
  9. data/vendor/handlebars/LICENSE +0 -1
  10. data/vendor/handlebars/README.markdown +8 -6
  11. data/vendor/handlebars/Rakefile +14 -21
  12. data/vendor/handlebars/bench/benchwarmer.js +1 -1
  13. data/vendor/handlebars/bench/handlebars.js +43 -34
  14. data/vendor/handlebars/bin/handlebars +56 -2
  15. data/vendor/handlebars/dist/handlebars.js +2201 -0
  16. data/vendor/handlebars/dist/handlebars.runtime.js +321 -0
  17. data/vendor/handlebars/lib/handlebars/base.js +68 -15
  18. data/vendor/handlebars/lib/handlebars/compiler/ast.js +50 -20
  19. data/vendor/handlebars/lib/handlebars/compiler/base.js +7 -13
  20. data/vendor/handlebars/lib/handlebars/compiler/compiler.js +758 -299
  21. data/vendor/handlebars/lib/handlebars/compiler/printer.js +24 -30
  22. data/vendor/handlebars/lib/handlebars/runtime.js +23 -3
  23. data/vendor/handlebars/lib/handlebars/utils.js +9 -10
  24. data/vendor/handlebars/package.json +15 -5
  25. data/vendor/handlebars/spec/acceptance_spec.rb +5 -5
  26. data/vendor/handlebars/spec/parser_spec.rb +201 -32
  27. data/vendor/handlebars/spec/qunit_spec.js +462 -159
  28. data/vendor/handlebars/spec/spec_helper.rb +7 -7
  29. data/vendor/handlebars/spec/tokenizer_spec.rb +55 -8
  30. data/vendor/handlebars/src/handlebars.l +14 -3
  31. data/vendor/handlebars/src/handlebars.yy +15 -5
  32. data/vendor/handlebars/src/parser-prefix.js +1 -0
  33. data/vendor/handlebars/src/parser-suffix.js +4 -0
  34. metadata +8 -3
@@ -47,15 +47,15 @@ module Handlebars
47
47
  def self.load_helpers(context)
48
48
  context["exports"] = nil
49
49
 
50
- context["p"] = proc do |val|
50
+ context["p"] = proc do |this, val|
51
51
  p val if ENV["DEBUG_JS"]
52
52
  end
53
53
 
54
- context["puts"] = proc do |val|
54
+ context["puts"] = proc do |this, val|
55
55
  puts val if ENV["DEBUG_JS"]
56
56
  end
57
57
 
58
- context["puts_node"] = proc do |val|
58
+ context["puts_node"] = proc do |this, val|
59
59
  puts context["Handlebars"]["PrintVisitor"].new.accept(val)
60
60
  puts
61
61
  end
@@ -82,12 +82,12 @@ module Handlebars
82
82
 
83
83
  context["CompilerContext"] = {}
84
84
  CompilerContext = context["CompilerContext"]
85
- CompilerContext["compile"] = proc do |*args|
85
+ CompilerContext["compile"] = proc do |this, *args|
86
86
  template, options = args[0], args[1] || nil
87
87
  templateSpec = COMPILE_CONTEXT["Handlebars"]["precompile"].call(template, options);
88
88
  context["Handlebars"]["template"].call(context.eval("(#{templateSpec})"));
89
89
  end
90
- CompilerContext["compileWithPartial"] = proc do |*args|
90
+ CompilerContext["compileWithPartial"] = proc do |this, *args|
91
91
  template, options = args[0], args[1] || nil
92
92
  FULL_CONTEXT["Handlebars"]["compile"].call(template, options);
93
93
  end
@@ -108,7 +108,7 @@ module Handlebars
108
108
 
109
109
  context["Handlebars"]["logger"]["level"] = ENV["DEBUG_JS"] ? context["Handlebars"]["logger"][ENV["DEBUG_JS"]] : 4
110
110
 
111
- context["Handlebars"]["logger"]["log"] = proc do |level, str|
111
+ context["Handlebars"]["logger"]["log"] = proc do |this, level, str|
112
112
  logger_level = context["Handlebars"]["logger"]["level"].to_i
113
113
 
114
114
  if logger_level <= level
@@ -133,7 +133,7 @@ module Handlebars
133
133
 
134
134
  context["Handlebars"]["logger"]["level"] = ENV["DEBUG_JS"] ? context["Handlebars"]["logger"][ENV["DEBUG_JS"]] : 4
135
135
 
136
- context["Handlebars"]["logger"]["log"] = proc do |level, str|
136
+ context["Handlebars"]["logger"]["log"] = proc do |this, level, str|
137
137
  logger_level = context["Handlebars"]["logger"]["level"].to_i
138
138
 
139
139
  if logger_level <= level
@@ -51,6 +51,15 @@ describe "Tokenizer" do
51
51
  result[4].should be_token("CONTENT", "{{bar}} ")
52
52
  end
53
53
 
54
+ it "supports escaping multiple delimiters" do
55
+ result = tokenize("{{foo}} \\{{bar}} \\{{baz}}")
56
+ result.should match_tokens(%w(OPEN ID CLOSE CONTENT CONTENT CONTENT))
57
+
58
+ result[3].should be_token("CONTENT", " ")
59
+ result[4].should be_token("CONTENT", "{{bar}} ")
60
+ result[5].should be_token("CONTENT", "{{baz}}")
61
+ end
62
+
54
63
  it "supports escaping a triple stash" do
55
64
  result = tokenize("{{foo}} \\{{{bar}}} {{baz}}")
56
65
  result.should match_tokens(%w(OPEN ID CLOSE CONTENT CONTENT OPEN ID CLOSE))
@@ -123,24 +132,24 @@ describe "Tokenizer" do
123
132
  result[4].should be_token("CONTENT", " baz")
124
133
  end
125
134
 
126
- it "tokenizes a partial as 'OPEN_PARTIAL ID CLOSE'" do
135
+ it "tokenizes a partial as 'OPEN_PARTIAL PARTIAL_NAME CLOSE'" do
127
136
  result = tokenize("{{> foo}}")
128
- result.should match_tokens(%w(OPEN_PARTIAL ID CLOSE))
137
+ result.should match_tokens(%w(OPEN_PARTIAL PARTIAL_NAME CLOSE))
129
138
  end
130
139
 
131
- it "tokenizes a partial with context as 'OPEN_PARTIAL ID ID CLOSE'" do
140
+ it "tokenizes a partial with context as 'OPEN_PARTIAL PARTIAL_NAME ID CLOSE'" do
132
141
  result = tokenize("{{> foo bar }}")
133
- result.should match_tokens(%w(OPEN_PARTIAL ID ID CLOSE))
142
+ result.should match_tokens(%w(OPEN_PARTIAL PARTIAL_NAME ID CLOSE))
134
143
  end
135
144
 
136
- it "tokenizes a partial without spaces as 'OPEN_PARTIAL ID CLOSE'" do
145
+ it "tokenizes a partial without spaces as 'OPEN_PARTIAL PARTIAL_NAME CLOSE'" do
137
146
  result = tokenize("{{>foo}}")
138
- result.should match_tokens(%w(OPEN_PARTIAL ID CLOSE))
147
+ result.should match_tokens(%w(OPEN_PARTIAL PARTIAL_NAME CLOSE))
139
148
  end
140
149
 
141
- it "tokenizes a partial space at the end as 'OPEN_PARTIAL ID CLOSE'" do
150
+ it "tokenizes a partial space at the end as 'OPEN_PARTIAL PARTIAL_NAME CLOSE'" do
142
151
  result = tokenize("{{>foo }}")
143
- result.should match_tokens(%w(OPEN_PARTIAL ID CLOSE))
152
+ result.should match_tokens(%w(OPEN_PARTIAL PARTIAL_NAME CLOSE))
144
153
  end
145
154
 
146
155
  it "tokenizes a comment as 'COMMENT'" do
@@ -149,6 +158,18 @@ describe "Tokenizer" do
149
158
  result[1].should be_token("COMMENT", " this is a comment ")
150
159
  end
151
160
 
161
+ it "tokenizes a block comment as 'COMMENT'" do
162
+ result = tokenize("foo {{!-- this is a {{comment}} --}} bar {{ baz }}")
163
+ result.should match_tokens(%w(CONTENT COMMENT CONTENT OPEN ID CLOSE))
164
+ result[1].should be_token("COMMENT", " this is a {{comment}} ")
165
+ end
166
+
167
+ it "tokenizes a block comment with whitespace as 'COMMENT'" do
168
+ result = tokenize("foo {{!-- this is a\n{{comment}}\n--}} bar {{ baz }}")
169
+ result.should match_tokens(%w(CONTENT COMMENT CONTENT OPEN ID CLOSE))
170
+ result[1].should be_token("COMMENT", " this is a\n{{comment}}\n")
171
+ end
172
+
152
173
  it "tokenizes open and closing blocks as 'OPEN_BLOCK ID CLOSE ... OPEN_ENDBLOCK ID CLOSE'" do
153
174
  result = tokenize("{{#foo}}content{{/foo}}")
154
175
  result.should match_tokens(%w(OPEN_BLOCK ID CLOSE CONTENT OPEN_ENDBLOCK ID CLOSE))
@@ -186,6 +207,12 @@ describe "Tokenizer" do
186
207
  result[3].should be_token("STRING", "baz")
187
208
  end
188
209
 
210
+ it "tokenizes mustaches with String params using single quotes as 'OPEN ID ID STRING CLOSE'" do
211
+ result = tokenize("{{ foo bar \'baz\' }}")
212
+ result.should match_tokens(%w(OPEN ID ID STRING CLOSE))
213
+ result[3].should be_token("STRING", "baz")
214
+ end
215
+
189
216
  it "tokenizes String params with spaces inside as 'STRING'" do
190
217
  result = tokenize("{{ foo bar \"baz bat\" }}")
191
218
  result.should match_tokens(%w(OPEN ID ID STRING CLOSE))
@@ -198,6 +225,12 @@ describe "Tokenizer" do
198
225
  result[2].should be_token("STRING", %{bar"baz})
199
226
  end
200
227
 
228
+ it "tokenizes String params using single quotes with escapes quotes as 'STRING'" do
229
+ result = tokenize(%|{{ foo 'bar\\'baz' }}|)
230
+ result.should match_tokens(%w(OPEN ID STRING CLOSE))
231
+ result[2].should be_token("STRING", %{bar'baz})
232
+ end
233
+
201
234
  it "tokenizes numbers" do
202
235
  result = tokenize(%|{{ foo 1 }}|)
203
236
  result.should match_tokens(%w(OPEN ID INTEGER CLOSE))
@@ -244,6 +277,20 @@ describe "Tokenizer" do
244
277
  result[2].should be_token("ID", "omg")
245
278
  end
246
279
 
280
+ it "tokenizes special @ identifiers" do
281
+ result = tokenize("{{ @foo }}")
282
+ result.should match_tokens %w( OPEN DATA CLOSE )
283
+ result[1].should be_token("DATA", "foo")
284
+
285
+ result = tokenize("{{ foo @bar }}")
286
+ result.should match_tokens %w( OPEN ID DATA CLOSE )
287
+ result[2].should be_token("DATA", "bar")
288
+
289
+ result = tokenize("{{ foo bar=@baz }}")
290
+ result.should match_tokens %w( OPEN ID ID EQUALS DATA CLOSE )
291
+ result[4].should be_token("DATA", "baz")
292
+ end
293
+
247
294
  it "does not time out in a mustache with a single } followed by EOF" do
248
295
  Timeout.timeout(1) { tokenize("{{foo}").should match_tokens(%w(OPEN ID)) }
249
296
  end
@@ -1,5 +1,5 @@
1
1
 
2
- %x mu emu
2
+ %x mu emu com par
3
3
 
4
4
  %%
5
5
 
@@ -11,15 +11,22 @@
11
11
 
12
12
  [^\x00]+ { return 'CONTENT'; }
13
13
 
14
- <emu>[^\x00]{2,}?/("{{") { this.popState(); return 'CONTENT'; }
14
+ <emu>[^\x00]{2,}?/("{{"|<<EOF>>) {
15
+ if(yytext.slice(-1) !== "\\") this.popState();
16
+ if(yytext.slice(-1) === "\\") yytext = yytext.substr(0,yyleng-1);
17
+ return 'CONTENT';
18
+ }
19
+
20
+ <com>[\s\S]*?"--}}" { yytext = yytext.substr(0, yyleng-4); this.popState(); return 'COMMENT'; }
15
21
 
16
- <mu>"{{>" { return 'OPEN_PARTIAL'; }
22
+ <mu>"{{>" { this.begin("par"); return 'OPEN_PARTIAL'; }
17
23
  <mu>"{{#" { return 'OPEN_BLOCK'; }
18
24
  <mu>"{{/" { return 'OPEN_ENDBLOCK'; }
19
25
  <mu>"{{^" { return 'OPEN_INVERSE'; }
20
26
  <mu>"{{"\s*"else" { return 'OPEN_INVERSE'; }
21
27
  <mu>"{{{" { return 'OPEN_UNESCAPED'; }
22
28
  <mu>"{{&" { return 'OPEN_UNESCAPED'; }
29
+ <mu>"{{!--" { this.popState(); this.begin('com'); }
23
30
  <mu>"{{!"[\s\S]*?"}}" { yytext = yytext.substr(3,yyleng-5); this.popState(); return 'COMMENT'; }
24
31
  <mu>"{{" { return 'OPEN'; }
25
32
 
@@ -31,12 +38,16 @@
31
38
  <mu>"}}}" { this.popState(); return 'CLOSE'; }
32
39
  <mu>"}}" { this.popState(); return 'CLOSE'; }
33
40
  <mu>'"'("\\"["]|[^"])*'"' { yytext = yytext.substr(1,yyleng-2).replace(/\\"/g,'"'); return 'STRING'; }
41
+ <mu>"'"("\\"[']|[^'])*"'" { yytext = yytext.substr(1,yyleng-2).replace(/\\'/g,"'"); return 'STRING'; }
42
+ <mu>"@"[a-zA-Z]+ { yytext = yytext.substr(1); return 'DATA'; }
34
43
  <mu>"true"/[}\s] { return 'BOOLEAN'; }
35
44
  <mu>"false"/[}\s] { return 'BOOLEAN'; }
36
45
  <mu>[0-9]+/[}\s] { return 'INTEGER'; }
37
46
  <mu>[a-zA-Z0-9_$-]+/[=}\s\/.] { return 'ID'; }
38
47
  <mu>'['[^\]]*']' { yytext = yytext.substr(1, yyleng-2); return 'ID'; }
39
48
  <mu>. { return 'INVALID'; }
49
+ <par>\s+ { /*ignore whitespace*/ }
50
+ <par>[a-zA-Z0-9_$-/]+ { this.popState(); return 'PARTIAL_NAME'; }
40
51
 
41
52
  <INITIAL,mu><<EOF>> { return 'EOF'; }
42
53
 
@@ -7,8 +7,11 @@ root
7
7
  ;
8
8
 
9
9
  program
10
- : statements simpleInverse statements { $$ = new yy.ProgramNode($1, $3); }
10
+ : simpleInverse statements { $$ = new yy.ProgramNode([], $2); }
11
+ | statements simpleInverse statements { $$ = new yy.ProgramNode($1, $3); }
12
+ | statements simpleInverse { $$ = new yy.ProgramNode($1, []); }
11
13
  | statements { $$ = new yy.ProgramNode($1); }
14
+ | simpleInverse { $$ = new yy.ProgramNode([], []); }
12
15
  | "" { $$ = new yy.ProgramNode([]); }
13
16
  ;
14
17
 
@@ -18,8 +21,8 @@ statements
18
21
  ;
19
22
 
20
23
  statement
21
- : openInverse program closeBlock { $$ = new yy.InverseNode($1, $2, $3); }
22
- | openBlock program closeBlock { $$ = new yy.BlockNode($1, $2, $3); }
24
+ : openInverse program closeBlock { $$ = new yy.BlockNode($1, $2.inverse, $2, $3); }
25
+ | openBlock program closeBlock { $$ = new yy.BlockNode($1, $2, $2.inverse, $3); }
23
26
  | mustache { $$ = $1; }
24
27
  | partial { $$ = $1; }
25
28
  | CONTENT { $$ = new yy.ContentNode($1); }
@@ -45,8 +48,8 @@ mustache
45
48
 
46
49
 
47
50
  partial
48
- : OPEN_PARTIAL path CLOSE { $$ = new yy.PartialNode($2); }
49
- | OPEN_PARTIAL path path CLOSE { $$ = new yy.PartialNode($2, $3); }
51
+ : OPEN_PARTIAL partialName CLOSE { $$ = new yy.PartialNode($2); }
52
+ | OPEN_PARTIAL partialName path CLOSE { $$ = new yy.PartialNode($2, $3); }
50
53
  ;
51
54
 
52
55
  simpleInverse
@@ -58,6 +61,7 @@ inMustache
58
61
  | path params { $$ = [[$1].concat($2), null]; }
59
62
  | path hash { $$ = [[$1], $2]; }
60
63
  | path { $$ = [[$1], null]; }
64
+ | DATA { $$ = [[new yy.DataNode($1)], null]; }
61
65
  ;
62
66
 
63
67
  params
@@ -70,6 +74,7 @@ param
70
74
  | STRING { $$ = new yy.StringNode($1); }
71
75
  | INTEGER { $$ = new yy.IntegerNode($1); }
72
76
  | BOOLEAN { $$ = new yy.BooleanNode($1); }
77
+ | DATA { $$ = new yy.DataNode($1); }
73
78
  ;
74
79
 
75
80
  hash
@@ -86,6 +91,11 @@ hashSegment
86
91
  | ID EQUALS STRING { $$ = [$1, new yy.StringNode($3)]; }
87
92
  | ID EQUALS INTEGER { $$ = [$1, new yy.IntegerNode($3)]; }
88
93
  | ID EQUALS BOOLEAN { $$ = [$1, new yy.BooleanNode($3)]; }
94
+ | ID EQUALS DATA { $$ = [$1, new yy.DataNode($3)]; }
95
+ ;
96
+
97
+ partialName
98
+ : PARTIAL_NAME { $$ = new yy.PartialNameNode($1); }
89
99
  ;
90
100
 
91
101
  path
@@ -0,0 +1 @@
1
+ // BEGIN(BROWSER)
@@ -0,0 +1,4 @@
1
+
2
+ // END(BROWSER)
3
+
4
+ module.exports = handlebars;
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: handlebars
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.2
4
+ version: 0.4.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-08 00:00:00.000000000 Z
12
+ date: 2013-02-19 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: therubyracer
@@ -103,6 +103,7 @@ files:
103
103
  - vendor/handlebars/.gitignore
104
104
  - vendor/handlebars/.jshintrc
105
105
  - vendor/handlebars/.npmignore
106
+ - vendor/handlebars/.rspec
106
107
  - vendor/handlebars/Gemfile
107
108
  - vendor/handlebars/Gemfile.lock
108
109
  - vendor/handlebars/LICENSE
@@ -111,6 +112,8 @@ files:
111
112
  - vendor/handlebars/bench/benchwarmer.js
112
113
  - vendor/handlebars/bench/handlebars.js
113
114
  - vendor/handlebars/bin/handlebars
115
+ - vendor/handlebars/dist/handlebars.js
116
+ - vendor/handlebars/dist/handlebars.runtime.js
114
117
  - vendor/handlebars/lib/handlebars.js
115
118
  - vendor/handlebars/lib/handlebars/base.js
116
119
  - vendor/handlebars/lib/handlebars/compiler/ast.js
@@ -129,6 +132,8 @@ files:
129
132
  - vendor/handlebars/spec/tokenizer_spec.rb
130
133
  - vendor/handlebars/src/handlebars.l
131
134
  - vendor/handlebars/src/handlebars.yy
135
+ - vendor/handlebars/src/parser-prefix.js
136
+ - vendor/handlebars/src/parser-suffix.js
132
137
  - vendor/handlebars/lib/handlebars/compiler/parser.js
133
138
  homepage: http://github.com/cowboyd/handlebars.rb
134
139
  licenses: []
@@ -150,7 +155,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
150
155
  version: '0'
151
156
  requirements: []
152
157
  rubyforge_project: handlebars
153
- rubygems_version: 1.8.24
158
+ rubygems_version: 1.8.25
154
159
  signing_key:
155
160
  specification_version: 3
156
161
  summary: Ruby bindings for the handlebars.js templating library