handlebars 0.4.0 → 0.5.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.
Files changed (43) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +1 -2
  3. data/README.mdown +15 -7
  4. data/handlebars.gemspec +2 -5
  5. data/lib/handlebars.rb +5 -5
  6. data/lib/handlebars/context.rb +3 -12
  7. data/lib/handlebars/version.rb +1 -1
  8. data/spec/handlebars_spec.rb +1 -1
  9. metadata +47 -58
  10. data/.gitmodules +0 -3
  11. data/vendor/handlebars/.gitignore +0 -8
  12. data/vendor/handlebars/.jshintrc +0 -52
  13. data/vendor/handlebars/.npmignore +0 -10
  14. data/vendor/handlebars/.rspec +0 -1
  15. data/vendor/handlebars/Gemfile +0 -5
  16. data/vendor/handlebars/LICENSE +0 -19
  17. data/vendor/handlebars/README.markdown +0 -317
  18. data/vendor/handlebars/Rakefile +0 -109
  19. data/vendor/handlebars/bench/benchwarmer.js +0 -149
  20. data/vendor/handlebars/bench/handlebars.js +0 -172
  21. data/vendor/handlebars/bin/handlebars +0 -193
  22. data/vendor/handlebars/dist/handlebars.js +0 -2201
  23. data/vendor/handlebars/dist/handlebars.runtime.js +0 -321
  24. data/vendor/handlebars/lib/handlebars.js +0 -14
  25. data/vendor/handlebars/lib/handlebars/base.js +0 -154
  26. data/vendor/handlebars/lib/handlebars/compiler/ast.js +0 -133
  27. data/vendor/handlebars/lib/handlebars/compiler/base.js +0 -21
  28. data/vendor/handlebars/lib/handlebars/compiler/compiler.js +0 -1267
  29. data/vendor/handlebars/lib/handlebars/compiler/index.js +0 -7
  30. data/vendor/handlebars/lib/handlebars/compiler/printer.js +0 -131
  31. data/vendor/handlebars/lib/handlebars/compiler/visitor.js +0 -13
  32. data/vendor/handlebars/lib/handlebars/runtime.js +0 -88
  33. data/vendor/handlebars/lib/handlebars/utils.js +0 -67
  34. data/vendor/handlebars/package.json +0 -35
  35. data/vendor/handlebars/spec/acceptance_spec.rb +0 -101
  36. data/vendor/handlebars/spec/parser_spec.rb +0 -433
  37. data/vendor/handlebars/spec/qunit_spec.js +0 -1370
  38. data/vendor/handlebars/spec/spec_helper.rb +0 -157
  39. data/vendor/handlebars/spec/tokenizer_spec.rb +0 -301
  40. data/vendor/handlebars/src/handlebars.l +0 -53
  41. data/vendor/handlebars/src/handlebars.yy +0 -109
  42. data/vendor/handlebars/src/parser-prefix.js +0 -1
  43. data/vendor/handlebars/src/parser-suffix.js +0 -4
@@ -1,157 +0,0 @@
1
- require "v8"
2
-
3
- # Monkey patches due to bugs in RubyRacer
4
- class V8::JSError
5
- def initialize(try, to)
6
- @to = to
7
- begin
8
- super(initialize_unsafe(try))
9
- rescue Exception => e
10
- # Original code does not make an Array here
11
- @boundaries = [Boundary.new(:rbframes => e.backtrace)]
12
- @value = e
13
- super("BUG! please report. JSError#initialize failed!: #{e.message}")
14
- end
15
- end
16
-
17
- def parse_js_frames(try)
18
- raw = @to.rb(try.StackTrace())
19
- if raw && !raw.empty?
20
- raw.split("\n")[1..-1].tap do |frames|
21
- # Original code uses strip!, and the frames are not guaranteed to be strippable
22
- frames.each {|frame| frame.strip.chomp!(",")}
23
- end
24
- else
25
- []
26
- end
27
- end
28
- end
29
-
30
- module Handlebars
31
- module Spec
32
- def self.js_backtrace(context)
33
- begin
34
- context.eval("throw")
35
- rescue V8::JSError => e
36
- return e.backtrace(:javascript)
37
- end
38
- end
39
-
40
- def self.remove_exports(string)
41
- match = string.match(%r{\A(.*?)^// BEGIN\(BROWSER\)\n(.*)\n^// END\(BROWSER\)(.*?)\Z}m)
42
- prelines = match ? match[1].count("\n") + 1 : 0
43
- ret = match ? match[2] : string
44
- ("\n" * prelines) + ret
45
- end
46
-
47
- def self.load_helpers(context)
48
- context["exports"] = nil
49
-
50
- context["p"] = proc do |this, val|
51
- p val if ENV["DEBUG_JS"]
52
- end
53
-
54
- context["puts"] = proc do |this, val|
55
- puts val if ENV["DEBUG_JS"]
56
- end
57
-
58
- context["puts_node"] = proc do |this, val|
59
- puts context["Handlebars"]["PrintVisitor"].new.accept(val)
60
- puts
61
- end
62
-
63
- context["puts_caller"] = proc do
64
- puts "BACKTRACE:"
65
- puts Handlebars::Spec.js_backtrace(context)
66
- puts
67
- end
68
- end
69
-
70
- def self.js_load(context, file)
71
- str = File.read(file)
72
- context.eval(remove_exports(str), file)
73
- end
74
-
75
- CONTEXT = V8::Context.new
76
- CONTEXT.instance_eval do |context|
77
- Handlebars::Spec.load_helpers(context);
78
-
79
- Handlebars::Spec.js_load(context, 'lib/handlebars/base.js');
80
- Handlebars::Spec.js_load(context, 'lib/handlebars/utils.js');
81
- Handlebars::Spec.js_load(context, 'lib/handlebars/runtime.js');
82
-
83
- context["CompilerContext"] = {}
84
- CompilerContext = context["CompilerContext"]
85
- CompilerContext["compile"] = proc do |this, *args|
86
- template, options = args[0], args[1] || nil
87
- templateSpec = COMPILE_CONTEXT["Handlebars"]["precompile"].call(template, options);
88
- context["Handlebars"]["template"].call(context.eval("(#{templateSpec})"));
89
- end
90
- CompilerContext["compileWithPartial"] = proc do |this, *args|
91
- template, options = args[0], args[1] || nil
92
- FULL_CONTEXT["Handlebars"]["compile"].call(template, options);
93
- end
94
- end
95
-
96
- COMPILE_CONTEXT = V8::Context.new
97
- COMPILE_CONTEXT.instance_eval do |context|
98
- Handlebars::Spec.load_helpers(context);
99
-
100
- Handlebars::Spec.js_load(context, 'lib/handlebars/base.js');
101
- Handlebars::Spec.js_load(context, 'lib/handlebars/utils.js');
102
- Handlebars::Spec.js_load(context, 'lib/handlebars/compiler/parser.js');
103
- Handlebars::Spec.js_load(context, 'lib/handlebars/compiler/base.js');
104
- Handlebars::Spec.js_load(context, 'lib/handlebars/compiler/ast.js');
105
- Handlebars::Spec.js_load(context, 'lib/handlebars/compiler/visitor.js');
106
- Handlebars::Spec.js_load(context, 'lib/handlebars/compiler/printer.js');
107
- Handlebars::Spec.js_load(context, 'lib/handlebars/compiler/compiler.js');
108
-
109
- context["Handlebars"]["logger"]["level"] = ENV["DEBUG_JS"] ? context["Handlebars"]["logger"][ENV["DEBUG_JS"]] : 4
110
-
111
- context["Handlebars"]["logger"]["log"] = proc do |this, level, str|
112
- logger_level = context["Handlebars"]["logger"]["level"].to_i
113
-
114
- if logger_level <= level
115
- puts str
116
- end
117
- end
118
- end
119
-
120
- FULL_CONTEXT = V8::Context.new
121
- FULL_CONTEXT.instance_eval do |context|
122
- Handlebars::Spec.load_helpers(context);
123
-
124
- Handlebars::Spec.js_load(context, 'lib/handlebars/base.js');
125
- Handlebars::Spec.js_load(context, 'lib/handlebars/utils.js');
126
- Handlebars::Spec.js_load(context, 'lib/handlebars/compiler/parser.js');
127
- Handlebars::Spec.js_load(context, 'lib/handlebars/compiler/base.js');
128
- Handlebars::Spec.js_load(context, 'lib/handlebars/compiler/ast.js');
129
- Handlebars::Spec.js_load(context, 'lib/handlebars/compiler/visitor.js');
130
- Handlebars::Spec.js_load(context, 'lib/handlebars/compiler/printer.js');
131
- Handlebars::Spec.js_load(context, 'lib/handlebars/compiler/compiler.js');
132
- Handlebars::Spec.js_load(context, 'lib/handlebars/runtime.js');
133
-
134
- context["Handlebars"]["logger"]["level"] = ENV["DEBUG_JS"] ? context["Handlebars"]["logger"][ENV["DEBUG_JS"]] : 4
135
-
136
- context["Handlebars"]["logger"]["log"] = proc do |this, level, str|
137
- logger_level = context["Handlebars"]["logger"]["level"].to_i
138
-
139
- if logger_level <= level
140
- puts str
141
- end
142
- end
143
- end
144
- end
145
- end
146
-
147
-
148
- require "test/unit/assertions"
149
-
150
- RSpec.configure do |config|
151
- config.include Test::Unit::Assertions
152
-
153
- # Each is required to allow classes to mark themselves as compiler tests
154
- config.before(:each) do
155
- @context = @compiles ? Handlebars::Spec::COMPILE_CONTEXT : Handlebars::Spec::CONTEXT
156
- end
157
- end
@@ -1,301 +0,0 @@
1
- require "spec_helper"
2
- require "timeout"
3
-
4
- describe "Tokenizer" do
5
- let(:parser) { @context["handlebars"] }
6
- let(:lexer) { @context["handlebars"]["lexer"] }
7
-
8
- before(:all) do
9
- @compiles = true
10
- end
11
- Token = Struct.new(:name, :text)
12
-
13
- def tokenize(string)
14
- lexer.setInput(string)
15
- out = []
16
-
17
- while token = lexer.lex
18
- # p token
19
- result = parser.terminals_[token] || token
20
- # p result
21
- break if !result || result == "EOF" || result == "INVALID"
22
- out << Token.new(result, lexer.yytext)
23
- end
24
-
25
- out
26
- end
27
-
28
- RSpec::Matchers.define :match_tokens do |tokens|
29
- match do |result|
30
- result.map(&:name).should == tokens
31
- end
32
- end
33
-
34
- RSpec::Matchers.define :be_token do |name, string|
35
- match do |token|
36
- token.name.should == name
37
- token.text.should == string
38
- end
39
- end
40
-
41
- it "tokenizes a simple mustache as 'OPEN ID CLOSE'" do
42
- result = tokenize("{{foo}}")
43
- result.should match_tokens(%w(OPEN ID CLOSE))
44
- result[1].should be_token("ID", "foo")
45
- end
46
-
47
- it "supports escaping delimiters" do
48
- result = tokenize("{{foo}} \\{{bar}} {{baz}}")
49
- result.should match_tokens(%w(OPEN ID CLOSE CONTENT CONTENT OPEN ID CLOSE))
50
-
51
- result[4].should be_token("CONTENT", "{{bar}} ")
52
- end
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
-
63
- it "supports escaping a triple stash" do
64
- result = tokenize("{{foo}} \\{{{bar}}} {{baz}}")
65
- result.should match_tokens(%w(OPEN ID CLOSE CONTENT CONTENT OPEN ID CLOSE))
66
-
67
- result[4].should be_token("CONTENT", "{{{bar}}} ")
68
- end
69
-
70
- it "tokenizes a simple path" do
71
- result = tokenize("{{foo/bar}}")
72
- result.should match_tokens(%w(OPEN ID SEP ID CLOSE))
73
- end
74
-
75
- it "allows dot notation" do
76
- result = tokenize("{{foo.bar}}")
77
- result.should match_tokens(%w(OPEN ID SEP ID CLOSE))
78
-
79
- tokenize("{{foo.bar.baz}}").should match_tokens(%w(OPEN ID SEP ID SEP ID CLOSE))
80
- end
81
-
82
- it "allows path literals with []" do
83
- result = tokenize("{{foo.[bar]}}")
84
- result.should match_tokens(%w(OPEN ID SEP ID CLOSE))
85
- end
86
-
87
- it "allows multiple path literals on a line with []" do
88
- result = tokenize("{{foo.[bar]}}{{foo.[baz]}}")
89
- result.should match_tokens(%w(OPEN ID SEP ID CLOSE OPEN ID SEP ID CLOSE))
90
- end
91
-
92
- it "tokenizes {{.}} as OPEN ID CLOSE" do
93
- result = tokenize("{{.}}")
94
- result.should match_tokens(%w(OPEN ID CLOSE))
95
- end
96
-
97
- it "tokenizes a path as 'OPEN (ID SEP)* ID CLOSE'" do
98
- result = tokenize("{{../foo/bar}}")
99
- result.should match_tokens(%w(OPEN ID SEP ID SEP ID CLOSE))
100
- result[1].should be_token("ID", "..")
101
- end
102
-
103
- it "tokenizes a path with .. as a parent path" do
104
- result = tokenize("{{../foo.bar}}")
105
- result.should match_tokens(%w(OPEN ID SEP ID SEP ID CLOSE))
106
- result[1].should be_token("ID", "..")
107
- end
108
-
109
- it "tokenizes a path with this/foo as OPEN ID SEP ID CLOSE" do
110
- result = tokenize("{{this/foo}}")
111
- result.should match_tokens(%w(OPEN ID SEP ID CLOSE))
112
- result[1].should be_token("ID", "this")
113
- result[3].should be_token("ID", "foo")
114
- end
115
-
116
- it "tokenizes a simple mustache with spaces as 'OPEN ID CLOSE'" do
117
- result = tokenize("{{ foo }}")
118
- result.should match_tokens(%w(OPEN ID CLOSE))
119
- result[1].should be_token("ID", "foo")
120
- end
121
-
122
- it "tokenizes a simple mustache with line breaks as 'OPEN ID ID CLOSE'" do
123
- result = tokenize("{{ foo \n bar }}")
124
- result.should match_tokens(%w(OPEN ID ID CLOSE))
125
- result[1].should be_token("ID", "foo")
126
- end
127
-
128
- it "tokenizes raw content as 'CONTENT'" do
129
- result = tokenize("foo {{ bar }} baz")
130
- result.should match_tokens(%w(CONTENT OPEN ID CLOSE CONTENT))
131
- result[0].should be_token("CONTENT", "foo ")
132
- result[4].should be_token("CONTENT", " baz")
133
- end
134
-
135
- it "tokenizes a partial as 'OPEN_PARTIAL PARTIAL_NAME CLOSE'" do
136
- result = tokenize("{{> foo}}")
137
- result.should match_tokens(%w(OPEN_PARTIAL PARTIAL_NAME CLOSE))
138
- end
139
-
140
- it "tokenizes a partial with context as 'OPEN_PARTIAL PARTIAL_NAME ID CLOSE'" do
141
- result = tokenize("{{> foo bar }}")
142
- result.should match_tokens(%w(OPEN_PARTIAL PARTIAL_NAME ID CLOSE))
143
- end
144
-
145
- it "tokenizes a partial without spaces as 'OPEN_PARTIAL PARTIAL_NAME CLOSE'" do
146
- result = tokenize("{{>foo}}")
147
- result.should match_tokens(%w(OPEN_PARTIAL PARTIAL_NAME CLOSE))
148
- end
149
-
150
- it "tokenizes a partial space at the end as 'OPEN_PARTIAL PARTIAL_NAME CLOSE'" do
151
- result = tokenize("{{>foo }}")
152
- result.should match_tokens(%w(OPEN_PARTIAL PARTIAL_NAME CLOSE))
153
- end
154
-
155
- it "tokenizes a comment as 'COMMENT'" do
156
- result = tokenize("foo {{! this is a comment }} bar {{ baz }}")
157
- result.should match_tokens(%w(CONTENT COMMENT CONTENT OPEN ID CLOSE))
158
- result[1].should be_token("COMMENT", " this is a comment ")
159
- end
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
-
173
- it "tokenizes open and closing blocks as 'OPEN_BLOCK ID CLOSE ... OPEN_ENDBLOCK ID CLOSE'" do
174
- result = tokenize("{{#foo}}content{{/foo}}")
175
- result.should match_tokens(%w(OPEN_BLOCK ID CLOSE CONTENT OPEN_ENDBLOCK ID CLOSE))
176
- end
177
-
178
- it "tokenizes inverse sections as 'OPEN_INVERSE CLOSE'" do
179
- tokenize("{{^}}").should match_tokens(%w(OPEN_INVERSE CLOSE))
180
- tokenize("{{else}}").should match_tokens(%w(OPEN_INVERSE CLOSE))
181
- tokenize("{{ else }}").should match_tokens(%w(OPEN_INVERSE CLOSE))
182
- end
183
-
184
- it "tokenizes inverse sections with ID as 'OPEN_INVERSE ID CLOSE'" do
185
- result = tokenize("{{^foo}}")
186
- result.should match_tokens(%w(OPEN_INVERSE ID CLOSE))
187
- result[1].should be_token("ID", "foo")
188
- end
189
-
190
- it "tokenizes inverse sections with ID and spaces as 'OPEN_INVERSE ID CLOSE'" do
191
- result = tokenize("{{^ foo }}")
192
- result.should match_tokens(%w(OPEN_INVERSE ID CLOSE))
193
- result[1].should be_token("ID", "foo")
194
- end
195
-
196
- it "tokenizes mustaches with params as 'OPEN ID ID ID CLOSE'" do
197
- result = tokenize("{{ foo bar baz }}")
198
- result.should match_tokens(%w(OPEN ID ID ID CLOSE))
199
- result[1].should be_token("ID", "foo")
200
- result[2].should be_token("ID", "bar")
201
- result[3].should be_token("ID", "baz")
202
- end
203
-
204
- it "tokenizes mustaches with String params as 'OPEN ID ID STRING CLOSE'" do
205
- result = tokenize("{{ foo bar \"baz\" }}")
206
- result.should match_tokens(%w(OPEN ID ID STRING CLOSE))
207
- result[3].should be_token("STRING", "baz")
208
- end
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
-
216
- it "tokenizes String params with spaces inside as 'STRING'" do
217
- result = tokenize("{{ foo bar \"baz bat\" }}")
218
- result.should match_tokens(%w(OPEN ID ID STRING CLOSE))
219
- result[3].should be_token("STRING", "baz bat")
220
- end
221
-
222
- it "tokenizes String params with escapes quotes as 'STRING'" do
223
- result = tokenize(%|{{ foo "bar\\"baz" }}|)
224
- result.should match_tokens(%w(OPEN ID STRING CLOSE))
225
- result[2].should be_token("STRING", %{bar"baz})
226
- end
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
-
234
- it "tokenizes numbers" do
235
- result = tokenize(%|{{ foo 1 }}|)
236
- result.should match_tokens(%w(OPEN ID INTEGER CLOSE))
237
- result[2].should be_token("INTEGER", "1")
238
- end
239
-
240
- it "tokenizes booleans" do
241
- result = tokenize(%|{{ foo true }}|)
242
- result.should match_tokens(%w(OPEN ID BOOLEAN CLOSE))
243
- result[2].should be_token("BOOLEAN", "true")
244
-
245
- result = tokenize(%|{{ foo false }}|)
246
- result.should match_tokens(%w(OPEN ID BOOLEAN CLOSE))
247
- result[2].should be_token("BOOLEAN", "false")
248
- end
249
-
250
- it "tokenizes hash arguments" do
251
- result = tokenize("{{ foo bar=baz }}")
252
- result.should match_tokens %w(OPEN ID ID EQUALS ID CLOSE)
253
-
254
- result = tokenize("{{ foo bar baz=bat }}")
255
- result.should match_tokens %w(OPEN ID ID ID EQUALS ID CLOSE)
256
-
257
- result = tokenize("{{ foo bar baz=1 }}")
258
- result.should match_tokens %w(OPEN ID ID ID EQUALS INTEGER CLOSE)
259
-
260
- result = tokenize("{{ foo bar baz=true }}")
261
- result.should match_tokens %w(OPEN ID ID ID EQUALS BOOLEAN CLOSE)
262
-
263
- result = tokenize("{{ foo bar baz=false }}")
264
- result.should match_tokens %w(OPEN ID ID ID EQUALS BOOLEAN CLOSE)
265
-
266
- result = tokenize("{{ foo bar\n baz=bat }}")
267
- result.should match_tokens %w(OPEN ID ID ID EQUALS ID CLOSE)
268
-
269
- result = tokenize("{{ foo bar baz=\"bat\" }}")
270
- result.should match_tokens %w(OPEN ID ID ID EQUALS STRING CLOSE)
271
-
272
- result = tokenize("{{ foo bar baz=\"bat\" bam=wot }}")
273
- result.should match_tokens %w(OPEN ID ID ID EQUALS STRING ID EQUALS ID CLOSE)
274
-
275
- result = tokenize("{{foo omg bar=baz bat=\"bam\"}}")
276
- result.should match_tokens %w(OPEN ID ID ID EQUALS ID ID EQUALS STRING CLOSE)
277
- result[2].should be_token("ID", "omg")
278
- end
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
-
294
- it "does not time out in a mustache with a single } followed by EOF" do
295
- Timeout.timeout(1) { tokenize("{{foo}").should match_tokens(%w(OPEN ID)) }
296
- end
297
-
298
- it "does not time out in a mustache when invalid ID characters are used" do
299
- Timeout.timeout(1) { tokenize("{{foo & }}").should match_tokens(%w(OPEN ID)) }
300
- end
301
- end