grape-swagger-rails 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +5 -0
  3. data/.rubocop_todo.yml +61 -0
  4. data/.travis.yml +5 -2
  5. data/CHANGELOG.md +11 -0
  6. data/CONTRIBUTING.md +13 -10
  7. data/Gemfile +6 -0
  8. data/README.md +58 -2
  9. data/RELEASING.md +1 -1
  10. data/Rakefile +6 -6
  11. data/app/assets/images/grape_swagger_rails/favicon-16x16.png +0 -0
  12. data/app/assets/images/grape_swagger_rails/favicon-32x32.png +0 -0
  13. data/app/assets/images/grape_swagger_rails/favicon.ico +0 -0
  14. data/app/assets/javascripts/grape_swagger_rails/application.js +2 -3
  15. data/app/assets/javascripts/grape_swagger_rails/backbone-min.js +14 -37
  16. data/app/assets/javascripts/grape_swagger_rails/handlebars-2.0.0.js +28 -0
  17. data/app/assets/javascripts/grape_swagger_rails/jquery-1.8.0.min.js +1 -1
  18. data/app/assets/javascripts/grape_swagger_rails/marked.js +1272 -0
  19. data/app/assets/javascripts/grape_swagger_rails/swagger-oauth.js +133 -54
  20. data/app/assets/javascripts/grape_swagger_rails/swagger-ui.min.js +13 -1
  21. data/app/assets/javascripts/grape_swagger_rails/underscore-min.js +6 -32
  22. data/app/assets/javascripts/grape_swagger_rails/underscore-min.map +1 -0
  23. data/app/assets/stylesheets/grape_swagger_rails/print.css +1172 -0
  24. data/app/assets/stylesheets/grape_swagger_rails/screen.css.erb +68 -13
  25. data/app/assets/stylesheets/grape_swagger_rails/style.css +250 -0
  26. data/app/assets/stylesheets/grape_swagger_rails/typography.css +26 -0
  27. data/app/views/grape_swagger_rails/application/index.html.erb +15 -10
  28. data/config/routes.rb +1 -1
  29. data/grape-swagger-rails.gemspec +7 -3
  30. data/lib/grape-swagger-rails.rb +4 -3
  31. data/lib/grape-swagger-rails/version.rb +1 -1
  32. data/lib/tasks/swagger_ui.rake +43 -44
  33. data/spec/dummy/bin/rails +2 -2
  34. data/spec/dummy/bin/rake +1 -1
  35. data/spec/dummy/bin/spring +6 -6
  36. data/spec/dummy/config.ru +1 -1
  37. data/spec/dummy/config/application.rb +2 -1
  38. data/spec/dummy/config/environments/development.rb +3 -0
  39. data/spec/dummy/config/environments/production.rb +1 -1
  40. data/spec/dummy/config/environments/test.rb +4 -1
  41. data/spec/features/grape-swagger-rails_spec.rb +1 -1
  42. data/spec/features/swagger_spec.rb +71 -27
  43. data/spec/spec_helper.rb +1 -1
  44. metadata +108 -45
  45. data/app/assets/javascripts/grape_swagger_rails/handlebars-1.0.0.js +0 -2278
  46. data/app/assets/javascripts/grape_swagger_rails/shred.bundle.js +0 -2765
  47. data/app/assets/javascripts/grape_swagger_rails/shred/content.js +0 -193
  48. data/app/assets/javascripts/grape_swagger_rails/swagger.js +0 -1603
@@ -1,6 +1,6 @@
1
1
  ENV['RAILS_ENV'] ||= 'test'
2
2
 
3
- require File.expand_path("../dummy/config/environment.rb", __FILE__)
3
+ require File.expand_path('../dummy/config/environment.rb', __FILE__)
4
4
  require 'rspec/rails'
5
5
 
6
6
  Rails.backtrace_cleaner.remove_silencers!
metadata CHANGED
@@ -1,237 +1,293 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: grape-swagger-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alexander Logunov
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-02-05 00:00:00.000000000 Z
11
+ date: 2016-02-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: railties
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ">="
17
+ - - '>='
18
18
  - !ruby/object:Gem::Version
19
19
  version: 3.2.12
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - ">="
24
+ - - '>='
25
25
  - !ruby/object:Gem::Version
26
26
  version: 3.2.12
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: grape-swagger
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - ">="
31
+ - - '>='
32
32
  - !ruby/object:Gem::Version
33
33
  version: 0.7.2
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - ">="
38
+ - - '>='
39
39
  - !ruby/object:Gem::Version
40
40
  version: 0.7.2
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: bundler
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - "~>"
45
+ - - ~>
46
46
  - !ruby/object:Gem::Version
47
47
  version: '1.3'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - "~>"
52
+ - - ~>
53
53
  - !ruby/object:Gem::Version
54
54
  version: '1.3'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: rake
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - ">="
59
+ - - '>='
60
60
  - !ruby/object:Gem::Version
61
61
  version: '0'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - ">="
66
+ - - '>='
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: git
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
- - - ">="
73
+ - - '>='
74
74
  - !ruby/object:Gem::Version
75
75
  version: '0'
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
- - - ">="
80
+ - - '>='
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0'
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: rspec-rails
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
- - - ">="
87
+ - - '>='
88
88
  - !ruby/object:Gem::Version
89
89
  version: '0'
90
90
  type: :development
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
- - - ">="
94
+ - - '>='
95
95
  - !ruby/object:Gem::Version
96
96
  version: '0'
97
97
  - !ruby/object:Gem::Dependency
98
98
  name: capybara
99
99
  requirement: !ruby/object:Gem::Requirement
100
100
  requirements:
101
- - - ">="
101
+ - - '>='
102
102
  - !ruby/object:Gem::Version
103
103
  version: '0'
104
104
  type: :development
105
105
  prerelease: false
106
106
  version_requirements: !ruby/object:Gem::Requirement
107
107
  requirements:
108
- - - ">="
108
+ - - '>='
109
109
  - !ruby/object:Gem::Version
110
110
  version: '0'
111
111
  - !ruby/object:Gem::Dependency
112
112
  name: grape
113
113
  requirement: !ruby/object:Gem::Requirement
114
114
  requirements:
115
- - - ">="
115
+ - - '>='
116
116
  - !ruby/object:Gem::Version
117
117
  version: '0'
118
118
  type: :development
119
119
  prerelease: false
120
120
  version_requirements: !ruby/object:Gem::Requirement
121
121
  requirements:
122
- - - ">="
122
+ - - '>='
123
123
  - !ruby/object:Gem::Version
124
124
  version: '0'
125
125
  - !ruby/object:Gem::Dependency
126
126
  name: selenium-webdriver
127
127
  requirement: !ruby/object:Gem::Requirement
128
128
  requirements:
129
- - - ">="
129
+ - - '>='
130
130
  - !ruby/object:Gem::Version
131
131
  version: '0'
132
132
  type: :development
133
133
  prerelease: false
134
134
  version_requirements: !ruby/object:Gem::Requirement
135
135
  requirements:
136
- - - ">="
136
+ - - '>='
137
137
  - !ruby/object:Gem::Version
138
138
  version: '0'
139
139
  - !ruby/object:Gem::Dependency
140
140
  name: sass-rails
141
141
  requirement: !ruby/object:Gem::Requirement
142
142
  requirements:
143
- - - ">="
143
+ - - '>='
144
144
  - !ruby/object:Gem::Version
145
145
  version: '0'
146
146
  type: :development
147
147
  prerelease: false
148
148
  version_requirements: !ruby/object:Gem::Requirement
149
149
  requirements:
150
- - - ">="
150
+ - - '>='
151
151
  - !ruby/object:Gem::Version
152
152
  version: '0'
153
153
  - !ruby/object:Gem::Dependency
154
154
  name: uglifier
155
155
  requirement: !ruby/object:Gem::Requirement
156
156
  requirements:
157
- - - ">="
157
+ - - '>='
158
158
  - !ruby/object:Gem::Version
159
159
  version: '0'
160
160
  type: :development
161
161
  prerelease: false
162
162
  version_requirements: !ruby/object:Gem::Requirement
163
163
  requirements:
164
- - - ">="
164
+ - - '>='
165
165
  - !ruby/object:Gem::Version
166
166
  version: '0'
167
167
  - !ruby/object:Gem::Dependency
168
168
  name: coffee-rails
169
169
  requirement: !ruby/object:Gem::Requirement
170
170
  requirements:
171
- - - ">="
171
+ - - '>='
172
172
  - !ruby/object:Gem::Version
173
173
  version: '0'
174
174
  type: :development
175
175
  prerelease: false
176
176
  version_requirements: !ruby/object:Gem::Requirement
177
177
  requirements:
178
- - - ">="
178
+ - - '>='
179
179
  - !ruby/object:Gem::Version
180
180
  version: '0'
181
181
  - !ruby/object:Gem::Dependency
182
182
  name: jquery-rails
183
183
  requirement: !ruby/object:Gem::Requirement
184
184
  requirements:
185
- - - ">="
185
+ - - '>='
186
186
  - !ruby/object:Gem::Version
187
187
  version: '0'
188
188
  type: :development
189
189
  prerelease: false
190
190
  version_requirements: !ruby/object:Gem::Requirement
191
191
  requirements:
192
- - - ">="
192
+ - - '>='
193
193
  - !ruby/object:Gem::Version
194
194
  version: '0'
195
195
  - !ruby/object:Gem::Dependency
196
196
  name: grape-swagger-ui
197
197
  requirement: !ruby/object:Gem::Requirement
198
198
  requirements:
199
- - - ">="
199
+ - - '>='
200
200
  - !ruby/object:Gem::Version
201
201
  version: '0'
202
202
  type: :development
203
203
  prerelease: false
204
204
  version_requirements: !ruby/object:Gem::Requirement
205
205
  requirements:
206
- - - ">="
206
+ - - '>='
207
207
  - !ruby/object:Gem::Version
208
208
  version: '0'
209
209
  - !ruby/object:Gem::Dependency
210
210
  name: sprockets
211
211
  requirement: !ruby/object:Gem::Requirement
212
212
  requirements:
213
- - - ">="
213
+ - - '>='
214
214
  - !ruby/object:Gem::Version
215
215
  version: '0'
216
216
  type: :development
217
217
  prerelease: false
218
218
  version_requirements: !ruby/object:Gem::Requirement
219
219
  requirements:
220
- - - ">="
220
+ - - '>='
221
221
  - !ruby/object:Gem::Version
222
222
  version: '0'
223
+ - !ruby/object:Gem::Dependency
224
+ name: rack
225
+ requirement: !ruby/object:Gem::Requirement
226
+ requirements:
227
+ - - ~>
228
+ - !ruby/object:Gem::Version
229
+ version: '1.6'
230
+ type: :development
231
+ prerelease: false
232
+ version_requirements: !ruby/object:Gem::Requirement
233
+ requirements:
234
+ - - ~>
235
+ - !ruby/object:Gem::Version
236
+ version: '1.6'
223
237
  - !ruby/object:Gem::Dependency
224
238
  name: rack-cors
225
239
  requirement: !ruby/object:Gem::Requirement
226
240
  requirements:
227
- - - ">="
241
+ - - '>='
242
+ - !ruby/object:Gem::Version
243
+ version: '0'
244
+ type: :development
245
+ prerelease: false
246
+ version_requirements: !ruby/object:Gem::Requirement
247
+ requirements:
248
+ - - '>='
249
+ - !ruby/object:Gem::Version
250
+ version: '0'
251
+ - !ruby/object:Gem::Dependency
252
+ name: rubocop
253
+ requirement: !ruby/object:Gem::Requirement
254
+ requirements:
255
+ - - '='
256
+ - !ruby/object:Gem::Version
257
+ version: 0.33.0
258
+ type: :development
259
+ prerelease: false
260
+ version_requirements: !ruby/object:Gem::Requirement
261
+ requirements:
262
+ - - '='
263
+ - !ruby/object:Gem::Version
264
+ version: 0.33.0
265
+ - !ruby/object:Gem::Dependency
266
+ name: mime-types
267
+ requirement: !ruby/object:Gem::Requirement
268
+ requirements:
269
+ - - <
270
+ - !ruby/object:Gem::Version
271
+ version: '3.0'
272
+ type: :development
273
+ prerelease: false
274
+ version_requirements: !ruby/object:Gem::Requirement
275
+ requirements:
276
+ - - <
277
+ - !ruby/object:Gem::Version
278
+ version: '3.0'
279
+ - !ruby/object:Gem::Dependency
280
+ name: rack-no_animations
281
+ requirement: !ruby/object:Gem::Requirement
282
+ requirements:
283
+ - - '>='
228
284
  - !ruby/object:Gem::Version
229
285
  version: '0'
230
286
  type: :development
231
287
  prerelease: false
232
288
  version_requirements: !ruby/object:Gem::Requirement
233
289
  requirements:
234
- - - ">="
290
+ - - '>='
235
291
  - !ruby/object:Gem::Version
236
292
  version: '0'
237
293
  description: Swagger UI as Rails Engine for grape-swagger gem
@@ -241,9 +297,11 @@ executables: []
241
297
  extensions: []
242
298
  extra_rdoc_files: []
243
299
  files:
244
- - ".gitignore"
245
- - ".rspec"
246
- - ".travis.yml"
300
+ - .gitignore
301
+ - .rspec
302
+ - .rubocop.yml
303
+ - .rubocop_todo.yml
304
+ - .travis.yml
247
305
  - CHANGELOG.md
248
306
  - CONTRIBUTING.md
249
307
  - Gemfile
@@ -252,6 +310,9 @@ files:
252
310
  - RELEASING.md
253
311
  - Rakefile
254
312
  - app/assets/images/grape_swagger_rails/explorer_icons.png
313
+ - app/assets/images/grape_swagger_rails/favicon-16x16.png
314
+ - app/assets/images/grape_swagger_rails/favicon-32x32.png
315
+ - app/assets/images/grape_swagger_rails/favicon.ico
255
316
  - app/assets/images/grape_swagger_rails/logo_small.png
256
317
  - app/assets/images/grape_swagger_rails/pet_store_api.png
257
318
  - app/assets/images/grape_swagger_rails/throbber.gif
@@ -259,21 +320,23 @@ files:
259
320
  - app/assets/javascripts/grape_swagger_rails/application.js
260
321
  - app/assets/javascripts/grape_swagger_rails/backbone-min.js
261
322
  - app/assets/javascripts/grape_swagger_rails/base64.js
262
- - app/assets/javascripts/grape_swagger_rails/handlebars-1.0.0.js
323
+ - app/assets/javascripts/grape_swagger_rails/handlebars-2.0.0.js
263
324
  - app/assets/javascripts/grape_swagger_rails/highlight.7.3.pack.js
264
325
  - app/assets/javascripts/grape_swagger_rails/jquery-1.8.0.min.js
265
326
  - app/assets/javascripts/grape_swagger_rails/jquery.ba-bbq.min.js
266
327
  - app/assets/javascripts/grape_swagger_rails/jquery.slideto.min.js
267
328
  - app/assets/javascripts/grape_swagger_rails/jquery.wiggle.min.js
268
- - app/assets/javascripts/grape_swagger_rails/shred.bundle.js
269
- - app/assets/javascripts/grape_swagger_rails/shred/content.js
329
+ - app/assets/javascripts/grape_swagger_rails/marked.js
270
330
  - app/assets/javascripts/grape_swagger_rails/swagger-oauth.js
271
331
  - app/assets/javascripts/grape_swagger_rails/swagger-ui.min.js
272
- - app/assets/javascripts/grape_swagger_rails/swagger.js
273
332
  - app/assets/javascripts/grape_swagger_rails/underscore-min.js
333
+ - app/assets/javascripts/grape_swagger_rails/underscore-min.map
274
334
  - app/assets/stylesheets/grape_swagger_rails/application.css
335
+ - app/assets/stylesheets/grape_swagger_rails/print.css
275
336
  - app/assets/stylesheets/grape_swagger_rails/reset.css
276
337
  - app/assets/stylesheets/grape_swagger_rails/screen.css.erb
338
+ - app/assets/stylesheets/grape_swagger_rails/style.css
339
+ - app/assets/stylesheets/grape_swagger_rails/typography.css
277
340
  - app/controllers/grape_swagger_rails/application_controller.rb
278
341
  - app/views/grape_swagger_rails/application/index.html.erb
279
342
  - config/routes.rb
@@ -325,7 +388,7 @@ files:
325
388
  - spec/spec_helper.rb
326
389
  - spec/support/capybara.rb
327
390
  - spec/support/rails.rb
328
- homepage: https://github.com/TinkerDev/grape-swagger-rails
391
+ homepage: https://github.com/ruby-grape/grape-swagger-rails
329
392
  licenses:
330
393
  - MIT
331
394
  metadata: {}
@@ -335,17 +398,17 @@ require_paths:
335
398
  - lib
336
399
  required_ruby_version: !ruby/object:Gem::Requirement
337
400
  requirements:
338
- - - ">="
401
+ - - '>='
339
402
  - !ruby/object:Gem::Version
340
403
  version: '0'
341
404
  required_rubygems_version: !ruby/object:Gem::Requirement
342
405
  requirements:
343
- - - ">="
406
+ - - '>='
344
407
  - !ruby/object:Gem::Version
345
408
  version: '0'
346
409
  requirements: []
347
410
  rubyforge_project:
348
- rubygems_version: 2.2.2
411
+ rubygems_version: 2.4.5
349
412
  signing_key:
350
413
  specification_version: 4
351
414
  summary: Swagger UI as Rails Engine for grape-swagger gem
@@ -1,2278 +0,0 @@
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
-
25
- // lib/handlebars/browser-prefix.js
26
- var Handlebars = {};
27
-
28
- (function(Handlebars, undefined) {
29
- ;
30
- // lib/handlebars/base.js
31
-
32
- Handlebars.VERSION = "1.0.0";
33
- Handlebars.COMPILER_REVISION = 4;
34
-
35
- Handlebars.REVISION_CHANGES = {
36
- 1: '<= 1.0.rc.2', // 1.0.rc.2 is actually rev2 but doesn't report it
37
- 2: '== 1.0.0-rc.3',
38
- 3: '== 1.0.0-rc.4',
39
- 4: '>= 1.0.0'
40
- };
41
-
42
- Handlebars.helpers = {};
43
- Handlebars.partials = {};
44
-
45
- var toString = Object.prototype.toString,
46
- functionType = '[object Function]',
47
- objectType = '[object Object]';
48
-
49
- Handlebars.registerHelper = function(name, fn, inverse) {
50
- if (toString.call(name) === objectType) {
51
- if (inverse || fn) { throw new Handlebars.Exception('Arg not supported with multiple helpers'); }
52
- Handlebars.Utils.extend(this.helpers, name);
53
- } else {
54
- if (inverse) { fn.not = inverse; }
55
- this.helpers[name] = fn;
56
- }
57
- };
58
-
59
- Handlebars.registerPartial = function(name, str) {
60
- if (toString.call(name) === objectType) {
61
- Handlebars.Utils.extend(this.partials, name);
62
- } else {
63
- this.partials[name] = str;
64
- }
65
- };
66
-
67
- Handlebars.registerHelper('helperMissing', function(arg) {
68
- if(arguments.length === 2) {
69
- return undefined;
70
- } else {
71
- throw new Error("Missing helper: '" + arg + "'");
72
- }
73
- });
74
-
75
- Handlebars.registerHelper('blockHelperMissing', function(context, options) {
76
- var inverse = options.inverse || function() {}, fn = options.fn;
77
-
78
- var type = toString.call(context);
79
-
80
- if(type === functionType) { context = context.call(this); }
81
-
82
- if(context === true) {
83
- return fn(this);
84
- } else if(context === false || context == null) {
85
- return inverse(this);
86
- } else if(type === "[object Array]") {
87
- if(context.length > 0) {
88
- return Handlebars.helpers.each(context, options);
89
- } else {
90
- return inverse(this);
91
- }
92
- } else {
93
- return fn(context);
94
- }
95
- });
96
-
97
- Handlebars.K = function() {};
98
-
99
- Handlebars.createFrame = Object.create || function(object) {
100
- Handlebars.K.prototype = object;
101
- var obj = new Handlebars.K();
102
- Handlebars.K.prototype = null;
103
- return obj;
104
- };
105
-
106
- Handlebars.logger = {
107
- DEBUG: 0, INFO: 1, WARN: 2, ERROR: 3, level: 3,
108
-
109
- methodMap: {0: 'debug', 1: 'info', 2: 'warn', 3: 'error'},
110
-
111
- // can be overridden in the host environment
112
- log: function(level, obj) {
113
- if (Handlebars.logger.level <= level) {
114
- var method = Handlebars.logger.methodMap[level];
115
- if (typeof console !== 'undefined' && console[method]) {
116
- console[method].call(console, obj);
117
- }
118
- }
119
- }
120
- };
121
-
122
- Handlebars.log = function(level, obj) { Handlebars.logger.log(level, obj); };
123
-
124
- Handlebars.registerHelper('each', function(context, options) {
125
- var fn = options.fn, inverse = options.inverse;
126
- var i = 0, ret = "", data;
127
-
128
- var type = toString.call(context);
129
- if(type === functionType) { context = context.call(this); }
130
-
131
- if (options.data) {
132
- data = Handlebars.createFrame(options.data);
133
- }
134
-
135
- if(context && typeof context === 'object') {
136
- if(context instanceof Array){
137
- for(var j = context.length; i<j; i++) {
138
- if (data) { data.index = i; }
139
- ret = ret + fn(context[i], { data: data });
140
- }
141
- } else {
142
- for(var key in context) {
143
- if(context.hasOwnProperty(key)) {
144
- if(data) { data.key = key; }
145
- ret = ret + fn(context[key], {data: data});
146
- i++;
147
- }
148
- }
149
- }
150
- }
151
-
152
- if(i === 0){
153
- ret = inverse(this);
154
- }
155
-
156
- return ret;
157
- });
158
-
159
- Handlebars.registerHelper('if', function(conditional, options) {
160
- var type = toString.call(conditional);
161
- if(type === functionType) { conditional = conditional.call(this); }
162
-
163
- if(!conditional || Handlebars.Utils.isEmpty(conditional)) {
164
- return options.inverse(this);
165
- } else {
166
- return options.fn(this);
167
- }
168
- });
169
-
170
- Handlebars.registerHelper('unless', function(conditional, options) {
171
- return Handlebars.helpers['if'].call(this, conditional, {fn: options.inverse, inverse: options.fn});
172
- });
173
-
174
- Handlebars.registerHelper('with', function(context, options) {
175
- var type = toString.call(context);
176
- if(type === functionType) { context = context.call(this); }
177
-
178
- if (!Handlebars.Utils.isEmpty(context)) return options.fn(context);
179
- });
180
-
181
- Handlebars.registerHelper('log', function(context, options) {
182
- var level = options.data && options.data.level != null ? parseInt(options.data.level, 10) : 1;
183
- Handlebars.log(level, context);
184
- });
185
- ;
186
- // lib/handlebars/compiler/parser.js
187
- /* Jison generated parser */
188
- var handlebars = (function(){
189
- var parser = {trace: function trace() { },
190
- yy: {},
191
- symbols_: {"error":2,"root":3,"program":4,"EOF":5,"simpleInverse":6,"statements":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,"CLOSE_UNESCAPED":24,"OPEN_PARTIAL":25,"partialName":26,"params":27,"hash":28,"dataName":29,"param":30,"STRING":31,"INTEGER":32,"BOOLEAN":33,"hashSegments":34,"hashSegment":35,"ID":36,"EQUALS":37,"DATA":38,"pathSegments":39,"SEP":40,"$accept":0,"$end":1},
192
- 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:"CLOSE_UNESCAPED",25:"OPEN_PARTIAL",31:"STRING",32:"INTEGER",33:"BOOLEAN",36:"ID",37:"EQUALS",38:"DATA",40:"SEP"},
193
- productions_: [0,[3,2],[4,2],[4,3],[4,2],[4,1],[4,1],[4,0],[7,1],[7,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],[6,2],[17,3],[17,2],[17,2],[17,1],[17,1],[27,2],[27,1],[30,1],[30,1],[30,1],[30,1],[30,1],[28,1],[34,2],[34,1],[35,3],[35,3],[35,3],[35,3],[35,3],[26,1],[26,1],[26,1],[29,2],[21,1],[39,3],[39,1]],
194
- performAction: function anonymous(yytext,yyleng,yylineno,yy,yystate,$$,_$) {
195
-
196
- var $0 = $$.length - 1;
197
- switch (yystate) {
198
- case 1: return $$[$0-1];
199
- break;
200
- case 2: this.$ = new yy.ProgramNode([], $$[$0]);
201
- break;
202
- case 3: this.$ = new yy.ProgramNode($$[$0-2], $$[$0]);
203
- break;
204
- case 4: this.$ = new yy.ProgramNode($$[$0-1], []);
205
- break;
206
- case 5: this.$ = new yy.ProgramNode($$[$0]);
207
- break;
208
- case 6: this.$ = new yy.ProgramNode([], []);
209
- break;
210
- case 7: this.$ = new yy.ProgramNode([]);
211
- break;
212
- case 8: this.$ = [$$[$0]];
213
- break;
214
- case 9: $$[$0-1].push($$[$0]); this.$ = $$[$0-1];
215
- break;
216
- case 10: this.$ = new yy.BlockNode($$[$0-2], $$[$0-1].inverse, $$[$0-1], $$[$0]);
217
- break;
218
- case 11: this.$ = new yy.BlockNode($$[$0-2], $$[$0-1], $$[$0-1].inverse, $$[$0]);
219
- break;
220
- case 12: this.$ = $$[$0];
221
- break;
222
- case 13: this.$ = $$[$0];
223
- break;
224
- case 14: this.$ = new yy.ContentNode($$[$0]);
225
- break;
226
- case 15: this.$ = new yy.CommentNode($$[$0]);
227
- break;
228
- case 16: this.$ = new yy.MustacheNode($$[$0-1][0], $$[$0-1][1]);
229
- break;
230
- case 17: this.$ = new yy.MustacheNode($$[$0-1][0], $$[$0-1][1]);
231
- break;
232
- case 18: this.$ = $$[$0-1];
233
- break;
234
- case 19:
235
- // Parsing out the '&' escape token at this level saves ~500 bytes after min due to the removal of one parser node.
236
- this.$ = new yy.MustacheNode($$[$0-1][0], $$[$0-1][1], $$[$0-2][2] === '&');
237
-
238
- break;
239
- case 20: this.$ = new yy.MustacheNode($$[$0-1][0], $$[$0-1][1], true);
240
- break;
241
- case 21: this.$ = new yy.PartialNode($$[$0-1]);
242
- break;
243
- case 22: this.$ = new yy.PartialNode($$[$0-2], $$[$0-1]);
244
- break;
245
- case 23:
246
- break;
247
- case 24: this.$ = [[$$[$0-2]].concat($$[$0-1]), $$[$0]];
248
- break;
249
- case 25: this.$ = [[$$[$0-1]].concat($$[$0]), null];
250
- break;
251
- case 26: this.$ = [[$$[$0-1]], $$[$0]];
252
- break;
253
- case 27: this.$ = [[$$[$0]], null];
254
- break;
255
- case 28: this.$ = [[$$[$0]], null];
256
- break;
257
- case 29: $$[$0-1].push($$[$0]); this.$ = $$[$0-1];
258
- break;
259
- case 30: this.$ = [$$[$0]];
260
- break;
261
- case 31: this.$ = $$[$0];
262
- break;
263
- case 32: this.$ = new yy.StringNode($$[$0]);
264
- break;
265
- case 33: this.$ = new yy.IntegerNode($$[$0]);
266
- break;
267
- case 34: this.$ = new yy.BooleanNode($$[$0]);
268
- break;
269
- case 35: this.$ = $$[$0];
270
- break;
271
- case 36: this.$ = new yy.HashNode($$[$0]);
272
- break;
273
- case 37: $$[$0-1].push($$[$0]); this.$ = $$[$0-1];
274
- break;
275
- case 38: this.$ = [$$[$0]];
276
- break;
277
- case 39: this.$ = [$$[$0-2], $$[$0]];
278
- break;
279
- case 40: this.$ = [$$[$0-2], new yy.StringNode($$[$0])];
280
- break;
281
- case 41: this.$ = [$$[$0-2], new yy.IntegerNode($$[$0])];
282
- break;
283
- case 42: this.$ = [$$[$0-2], new yy.BooleanNode($$[$0])];
284
- break;
285
- case 43: this.$ = [$$[$0-2], $$[$0]];
286
- break;
287
- case 44: this.$ = new yy.PartialNameNode($$[$0]);
288
- break;
289
- case 45: this.$ = new yy.PartialNameNode(new yy.StringNode($$[$0]));
290
- break;
291
- case 46: this.$ = new yy.PartialNameNode(new yy.IntegerNode($$[$0]));
292
- break;
293
- case 47: this.$ = new yy.DataNode($$[$0]);
294
- break;
295
- case 48: this.$ = new yy.IdNode($$[$0]);
296
- break;
297
- case 49: $$[$0-2].push({part: $$[$0], separator: $$[$0-1]}); this.$ = $$[$0-2];
298
- break;
299
- case 50: this.$ = [{part: $$[$0]}];
300
- break;
301
- }
302
- },
303
- table: [{3:1,4:2,5:[2,7],6:3,7:4,8:6,9:7,11:8,12:9,13:10,14:[1,11],15:[1,12],16:[1,13],19:[1,5],22:[1,14],23:[1,15],25:[1,16]},{1:[3]},{5:[1,17]},{5:[2,6],7:18,8:6,9:7,11:8,12:9,13:10,14:[1,11],15:[1,12],16:[1,13],19:[1,19],20:[2,6],22:[1,14],23:[1,15],25:[1,16]},{5:[2,5],6:20,8:21,9:7,11:8,12:9,13:10,14:[1,11],15:[1,12],16:[1,13],19:[1,5],20:[2,5],22:[1,14],23:[1,15],25:[1,16]},{17:23,18:[1,22],21:24,29:25,36:[1,28],38:[1,27],39:26},{5:[2,8],14:[2,8],15:[2,8],16:[2,8],19:[2,8],20:[2,8],22:[2,8],23:[2,8],25:[2,8]},{4:29,6:3,7:4,8:6,9:7,11:8,12:9,13:10,14:[1,11],15:[1,12],16:[1,13],19:[1,5],20:[2,7],22:[1,14],23:[1,15],25:[1,16]},{4:30,6:3,7:4,8:6,9:7,11:8,12:9,13:10,14:[1,11],15:[1,12],16:[1,13],19:[1,5],20:[2,7],22:[1,14],23:[1,15],25:[1,16]},{5:[2,12],14:[2,12],15:[2,12],16:[2,12],19:[2,12],20:[2,12],22:[2,12],23:[2,12],25:[2,12]},{5:[2,13],14:[2,13],15:[2,13],16:[2,13],19:[2,13],20:[2,13],22:[2,13],23:[2,13],25:[2,13]},{5:[2,14],14:[2,14],15:[2,14],16:[2,14],19:[2,14],20:[2,14],22:[2,14],23:[2,14],25:[2,14]},{5:[2,15],14:[2,15],15:[2,15],16:[2,15],19:[2,15],20:[2,15],22:[2,15],23:[2,15],25:[2,15]},{17:31,21:24,29:25,36:[1,28],38:[1,27],39:26},{17:32,21:24,29:25,36:[1,28],38:[1,27],39:26},{17:33,21:24,29:25,36:[1,28],38:[1,27],39:26},{21:35,26:34,31:[1,36],32:[1,37],36:[1,28],39:26},{1:[2,1]},{5:[2,2],8:21,9:7,11:8,12:9,13:10,14:[1,11],15:[1,12],16:[1,13],19:[1,19],20:[2,2],22:[1,14],23:[1,15],25:[1,16]},{17:23,21:24,29:25,36:[1,28],38:[1,27],39:26},{5:[2,4],7:38,8:6,9:7,11:8,12:9,13:10,14:[1,11],15:[1,12],16:[1,13],19:[1,19],20:[2,4],22:[1,14],23:[1,15],25:[1,16]},{5:[2,9],14:[2,9],15:[2,9],16:[2,9],19:[2,9],20:[2,9],22:[2,9],23:[2,9],25:[2,9]},{5:[2,23],14:[2,23],15:[2,23],16:[2,23],19:[2,23],20:[2,23],22:[2,23],23:[2,23],25:[2,23]},{18:[1,39]},{18:[2,27],21:44,24:[2,27],27:40,28:41,29:48,30:42,31:[1,45],32:[1,46],33:[1,47],34:43,35:49,36:[1,50],38:[1,27],39:26},{18:[2,28],24:[2,28]},{18:[2,48],24:[2,48],31:[2,48],32:[2,48],33:[2,48],36:[2,48],38:[2,48],40:[1,51]},{21:52,36:[1,28],39:26},{18:[2,50],24:[2,50],31:[2,50],32:[2,50],33:[2,50],36:[2,50],38:[2,50],40:[2,50]},{10:53,20:[1,54]},{10:55,20:[1,54]},{18:[1,56]},{18:[1,57]},{24:[1,58]},{18:[1,59],21:60,36:[1,28],39:26},{18:[2,44],36:[2,44]},{18:[2,45],36:[2,45]},{18:[2,46],36:[2,46]},{5:[2,3],8:21,9:7,11:8,12:9,13:10,14:[1,11],15:[1,12],16:[1,13],19:[1,19],20:[2,3],22:[1,14],23:[1,15],25:[1,16]},{14:[2,17],15:[2,17],16:[2,17],19:[2,17],20:[2,17],22:[2,17],23:[2,17],25:[2,17]},{18:[2,25],21:44,24:[2,25],28:61,29:48,30:62,31:[1,45],32:[1,46],33:[1,47],34:43,35:49,36:[1,50],38:[1,27],39:26},{18:[2,26],24:[2,26]},{18:[2,30],24:[2,30],31:[2,30],32:[2,30],33:[2,30],36:[2,30],38:[2,30]},{18:[2,36],24:[2,36],35:63,36:[1,64]},{18:[2,31],24:[2,31],31:[2,31],32:[2,31],33:[2,31],36:[2,31],38:[2,31]},{18:[2,32],24:[2,32],31:[2,32],32:[2,32],33:[2,32],36:[2,32],38:[2,32]},{18:[2,33],24:[2,33],31:[2,33],32:[2,33],33:[2,33],36:[2,33],38:[2,33]},{18:[2,34],24:[2,34],31:[2,34],32:[2,34],33:[2,34],36:[2,34],38:[2,34]},{18:[2,35],24:[2,35],31:[2,35],32:[2,35],33:[2,35],36:[2,35],38:[2,35]},{18:[2,38],24:[2,38],36:[2,38]},{18:[2,50],24:[2,50],31:[2,50],32:[2,50],33:[2,50],36:[2,50],37:[1,65],38:[2,50],40:[2,50]},{36:[1,66]},{18:[2,47],24:[2,47],31:[2,47],32:[2,47],33:[2,47],36:[2,47],38:[2,47]},{5:[2,10],14:[2,10],15:[2,10],16:[2,10],19:[2,10],20:[2,10],22:[2,10],23:[2,10],25:[2,10]},{21:67,36:[1,28],39:26},{5:[2,11],14:[2,11],15:[2,11],16:[2,11],19:[2,11],20:[2,11],22:[2,11],23:[2,11],25:[2,11]},{14:[2,16],15:[2,16],16:[2,16],19:[2,16],20:[2,16],22:[2,16],23:[2,16],25:[2,16]},{5:[2,19],14:[2,19],15:[2,19],16:[2,19],19:[2,19],20:[2,19],22:[2,19],23:[2,19],25:[2,19]},{5:[2,20],14:[2,20],15:[2,20],16:[2,20],19:[2,20],20:[2,20],22:[2,20],23:[2,20],25:[2,20]},{5:[2,21],14:[2,21],15:[2,21],16:[2,21],19:[2,21],20:[2,21],22:[2,21],23:[2,21],25:[2,21]},{18:[1,68]},{18:[2,24],24:[2,24]},{18:[2,29],24:[2,29],31:[2,29],32:[2,29],33:[2,29],36:[2,29],38:[2,29]},{18:[2,37],24:[2,37],36:[2,37]},{37:[1,65]},{21:69,29:73,31:[1,70],32:[1,71],33:[1,72],36:[1,28],38:[1,27],39:26},{18:[2,49],24:[2,49],31:[2,49],32:[2,49],33:[2,49],36:[2,49],38:[2,49],40:[2,49]},{18:[1,74]},{5:[2,22],14:[2,22],15:[2,22],16:[2,22],19:[2,22],20:[2,22],22:[2,22],23:[2,22],25:[2,22]},{18:[2,39],24:[2,39],36:[2,39]},{18:[2,40],24:[2,40],36:[2,40]},{18:[2,41],24:[2,41],36:[2,41]},{18:[2,42],24:[2,42],36:[2,42]},{18:[2,43],24:[2,43],36:[2,43]},{5:[2,18],14:[2,18],15:[2,18],16:[2,18],19:[2,18],20:[2,18],22:[2,18],23:[2,18],25:[2,18]}],
304
- defaultActions: {17:[2,1]},
305
- parseError: function parseError(str, hash) {
306
- throw new Error(str);
307
- },
308
- parse: function parse(input) {
309
- var self = this, stack = [0], vstack = [null], lstack = [], table = this.table, yytext = "", yylineno = 0, yyleng = 0, recovering = 0, TERROR = 2, EOF = 1;
310
- this.lexer.setInput(input);
311
- this.lexer.yy = this.yy;
312
- this.yy.lexer = this.lexer;
313
- this.yy.parser = this;
314
- if (typeof this.lexer.yylloc == "undefined")
315
- this.lexer.yylloc = {};
316
- var yyloc = this.lexer.yylloc;
317
- lstack.push(yyloc);
318
- var ranges = this.lexer.options && this.lexer.options.ranges;
319
- if (typeof this.yy.parseError === "function")
320
- this.parseError = this.yy.parseError;
321
- function popStack(n) {
322
- stack.length = stack.length - 2 * n;
323
- vstack.length = vstack.length - n;
324
- lstack.length = lstack.length - n;
325
- }
326
- function lex() {
327
- var token;
328
- token = self.lexer.lex() || 1;
329
- if (typeof token !== "number") {
330
- token = self.symbols_[token] || token;
331
- }
332
- return token;
333
- }
334
- var symbol, preErrorSymbol, state, action, a, r, yyval = {}, p, len, newState, expected;
335
- while (true) {
336
- state = stack[stack.length - 1];
337
- if (this.defaultActions[state]) {
338
- action = this.defaultActions[state];
339
- } else {
340
- if (symbol === null || typeof symbol == "undefined") {
341
- symbol = lex();
342
- }
343
- action = table[state] && table[state][symbol];
344
- }
345
- if (typeof action === "undefined" || !action.length || !action[0]) {
346
- var errStr = "";
347
- if (!recovering) {
348
- expected = [];
349
- for (p in table[state])
350
- if (this.terminals_[p] && p > 2) {
351
- expected.push("'" + this.terminals_[p] + "'");
352
- }
353
- if (this.lexer.showPosition) {
354
- errStr = "Parse error on line " + (yylineno + 1) + ":\n" + this.lexer.showPosition() + "\nExpecting " + expected.join(", ") + ", got '" + (this.terminals_[symbol] || symbol) + "'";
355
- } else {
356
- errStr = "Parse error on line " + (yylineno + 1) + ": Unexpected " + (symbol == 1?"end of input":"'" + (this.terminals_[symbol] || symbol) + "'");
357
- }
358
- this.parseError(errStr, {text: this.lexer.match, token: this.terminals_[symbol] || symbol, line: this.lexer.yylineno, loc: yyloc, expected: expected});
359
- }
360
- }
361
- if (action[0] instanceof Array && action.length > 1) {
362
- throw new Error("Parse Error: multiple actions possible at state: " + state + ", token: " + symbol);
363
- }
364
- switch (action[0]) {
365
- case 1:
366
- stack.push(symbol);
367
- vstack.push(this.lexer.yytext);
368
- lstack.push(this.lexer.yylloc);
369
- stack.push(action[1]);
370
- symbol = null;
371
- if (!preErrorSymbol) {
372
- yyleng = this.lexer.yyleng;
373
- yytext = this.lexer.yytext;
374
- yylineno = this.lexer.yylineno;
375
- yyloc = this.lexer.yylloc;
376
- if (recovering > 0)
377
- recovering--;
378
- } else {
379
- symbol = preErrorSymbol;
380
- preErrorSymbol = null;
381
- }
382
- break;
383
- case 2:
384
- len = this.productions_[action[1]][1];
385
- yyval.$ = vstack[vstack.length - len];
386
- 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};
387
- if (ranges) {
388
- yyval._$.range = [lstack[lstack.length - (len || 1)].range[0], lstack[lstack.length - 1].range[1]];
389
- }
390
- r = this.performAction.call(yyval, yytext, yyleng, yylineno, this.yy, action[1], vstack, lstack);
391
- if (typeof r !== "undefined") {
392
- return r;
393
- }
394
- if (len) {
395
- stack = stack.slice(0, -1 * len * 2);
396
- vstack = vstack.slice(0, -1 * len);
397
- lstack = lstack.slice(0, -1 * len);
398
- }
399
- stack.push(this.productions_[action[1]][0]);
400
- vstack.push(yyval.$);
401
- lstack.push(yyval._$);
402
- newState = table[stack[stack.length - 2]][stack[stack.length - 1]];
403
- stack.push(newState);
404
- break;
405
- case 3:
406
- return true;
407
- }
408
- }
409
- return true;
410
- }
411
- };
412
- /* Jison generated lexer */
413
- var lexer = (function(){
414
- var lexer = ({EOF:1,
415
- parseError:function parseError(str, hash) {
416
- if (this.yy.parser) {
417
- this.yy.parser.parseError(str, hash);
418
- } else {
419
- throw new Error(str);
420
- }
421
- },
422
- setInput:function (input) {
423
- this._input = input;
424
- this._more = this._less = this.done = false;
425
- this.yylineno = this.yyleng = 0;
426
- this.yytext = this.matched = this.match = '';
427
- this.conditionStack = ['INITIAL'];
428
- this.yylloc = {first_line:1,first_column:0,last_line:1,last_column:0};
429
- if (this.options.ranges) this.yylloc.range = [0,0];
430
- this.offset = 0;
431
- return this;
432
- },
433
- input:function () {
434
- var ch = this._input[0];
435
- this.yytext += ch;
436
- this.yyleng++;
437
- this.offset++;
438
- this.match += ch;
439
- this.matched += ch;
440
- var lines = ch.match(/(?:\r\n?|\n).*/g);
441
- if (lines) {
442
- this.yylineno++;
443
- this.yylloc.last_line++;
444
- } else {
445
- this.yylloc.last_column++;
446
- }
447
- if (this.options.ranges) this.yylloc.range[1]++;
448
-
449
- this._input = this._input.slice(1);
450
- return ch;
451
- },
452
- unput:function (ch) {
453
- var len = ch.length;
454
- var lines = ch.split(/(?:\r\n?|\n)/g);
455
-
456
- this._input = ch + this._input;
457
- this.yytext = this.yytext.substr(0, this.yytext.length-len-1);
458
- //this.yyleng -= len;
459
- this.offset -= len;
460
- var oldLines = this.match.split(/(?:\r\n?|\n)/g);
461
- this.match = this.match.substr(0, this.match.length-1);
462
- this.matched = this.matched.substr(0, this.matched.length-1);
463
-
464
- if (lines.length-1) this.yylineno -= lines.length-1;
465
- var r = this.yylloc.range;
466
-
467
- this.yylloc = {first_line: this.yylloc.first_line,
468
- last_line: this.yylineno+1,
469
- first_column: this.yylloc.first_column,
470
- last_column: lines ?
471
- (lines.length === oldLines.length ? this.yylloc.first_column : 0) + oldLines[oldLines.length - lines.length].length - lines[0].length:
472
- this.yylloc.first_column - len
473
- };
474
-
475
- if (this.options.ranges) {
476
- this.yylloc.range = [r[0], r[0] + this.yyleng - len];
477
- }
478
- return this;
479
- },
480
- more:function () {
481
- this._more = true;
482
- return this;
483
- },
484
- less:function (n) {
485
- this.unput(this.match.slice(n));
486
- },
487
- pastInput:function () {
488
- var past = this.matched.substr(0, this.matched.length - this.match.length);
489
- return (past.length > 20 ? '...':'') + past.substr(-20).replace(/\n/g, "");
490
- },
491
- upcomingInput:function () {
492
- var next = this.match;
493
- if (next.length < 20) {
494
- next += this._input.substr(0, 20-next.length);
495
- }
496
- return (next.substr(0,20)+(next.length > 20 ? '...':'')).replace(/\n/g, "");
497
- },
498
- showPosition:function () {
499
- var pre = this.pastInput();
500
- var c = new Array(pre.length + 1).join("-");
501
- return pre + this.upcomingInput() + "\n" + c+"^";
502
- },
503
- next:function () {
504
- if (this.done) {
505
- return this.EOF;
506
- }
507
- if (!this._input) this.done = true;
508
-
509
- var token,
510
- match,
511
- tempMatch,
512
- index,
513
- col,
514
- lines;
515
- if (!this._more) {
516
- this.yytext = '';
517
- this.match = '';
518
- }
519
- var rules = this._currentRules();
520
- for (var i=0;i < rules.length; i++) {
521
- tempMatch = this._input.match(this.rules[rules[i]]);
522
- if (tempMatch && (!match || tempMatch[0].length > match[0].length)) {
523
- match = tempMatch;
524
- index = i;
525
- if (!this.options.flex) break;
526
- }
527
- }
528
- if (match) {
529
- lines = match[0].match(/(?:\r\n?|\n).*/g);
530
- if (lines) this.yylineno += lines.length;
531
- this.yylloc = {first_line: this.yylloc.last_line,
532
- last_line: this.yylineno+1,
533
- first_column: this.yylloc.last_column,
534
- last_column: lines ? lines[lines.length-1].length-lines[lines.length-1].match(/\r?\n?/)[0].length : this.yylloc.last_column + match[0].length};
535
- this.yytext += match[0];
536
- this.match += match[0];
537
- this.matches = match;
538
- this.yyleng = this.yytext.length;
539
- if (this.options.ranges) {
540
- this.yylloc.range = [this.offset, this.offset += this.yyleng];
541
- }
542
- this._more = false;
543
- this._input = this._input.slice(match[0].length);
544
- this.matched += match[0];
545
- token = this.performAction.call(this, this.yy, this, rules[index],this.conditionStack[this.conditionStack.length-1]);
546
- if (this.done && this._input) this.done = false;
547
- if (token) return token;
548
- else return;
549
- }
550
- if (this._input === "") {
551
- return this.EOF;
552
- } else {
553
- return this.parseError('Lexical error on line '+(this.yylineno+1)+'. Unrecognized text.\n'+this.showPosition(),
554
- {text: "", token: null, line: this.yylineno});
555
- }
556
- },
557
- lex:function lex() {
558
- var r = this.next();
559
- if (typeof r !== 'undefined') {
560
- return r;
561
- } else {
562
- return this.lex();
563
- }
564
- },
565
- begin:function begin(condition) {
566
- this.conditionStack.push(condition);
567
- },
568
- popState:function popState() {
569
- return this.conditionStack.pop();
570
- },
571
- _currentRules:function _currentRules() {
572
- return this.conditions[this.conditionStack[this.conditionStack.length-1]].rules;
573
- },
574
- topState:function () {
575
- return this.conditionStack[this.conditionStack.length-2];
576
- },
577
- pushState:function begin(condition) {
578
- this.begin(condition);
579
- }});
580
- lexer.options = {};
581
- lexer.performAction = function anonymous(yy,yy_,$avoiding_name_collisions,YY_START) {
582
-
583
- var YYSTATE=YY_START
584
- switch($avoiding_name_collisions) {
585
- case 0: yy_.yytext = "\\"; return 14;
586
- break;
587
- case 1:
588
- if(yy_.yytext.slice(-1) !== "\\") this.begin("mu");
589
- if(yy_.yytext.slice(-1) === "\\") yy_.yytext = yy_.yytext.substr(0,yy_.yyleng-1), this.begin("emu");
590
- if(yy_.yytext) return 14;
591
-
592
- break;
593
- case 2: return 14;
594
- break;
595
- case 3:
596
- if(yy_.yytext.slice(-1) !== "\\") this.popState();
597
- if(yy_.yytext.slice(-1) === "\\") yy_.yytext = yy_.yytext.substr(0,yy_.yyleng-1);
598
- return 14;
599
-
600
- break;
601
- case 4: yy_.yytext = yy_.yytext.substr(0, yy_.yyleng-4); this.popState(); return 15;
602
- break;
603
- case 5: return 25;
604
- break;
605
- case 6: return 16;
606
- break;
607
- case 7: return 20;
608
- break;
609
- case 8: return 19;
610
- break;
611
- case 9: return 19;
612
- break;
613
- case 10: return 23;
614
- break;
615
- case 11: return 22;
616
- break;
617
- case 12: this.popState(); this.begin('com');
618
- break;
619
- case 13: yy_.yytext = yy_.yytext.substr(3,yy_.yyleng-5); this.popState(); return 15;
620
- break;
621
- case 14: return 22;
622
- break;
623
- case 15: return 37;
624
- break;
625
- case 16: return 36;
626
- break;
627
- case 17: return 36;
628
- break;
629
- case 18: return 40;
630
- break;
631
- case 19: /*ignore whitespace*/
632
- break;
633
- case 20: this.popState(); return 24;
634
- break;
635
- case 21: this.popState(); return 18;
636
- break;
637
- case 22: yy_.yytext = yy_.yytext.substr(1,yy_.yyleng-2).replace(/\\"/g,'"'); return 31;
638
- break;
639
- case 23: yy_.yytext = yy_.yytext.substr(1,yy_.yyleng-2).replace(/\\'/g,"'"); return 31;
640
- break;
641
- case 24: return 38;
642
- break;
643
- case 25: return 33;
644
- break;
645
- case 26: return 33;
646
- break;
647
- case 27: return 32;
648
- break;
649
- case 28: return 36;
650
- break;
651
- case 29: yy_.yytext = yy_.yytext.substr(1, yy_.yyleng-2); return 36;
652
- break;
653
- case 30: return 'INVALID';
654
- break;
655
- case 31: return 5;
656
- break;
657
- }
658
- };
659
- lexer.rules = [/^(?:\\\\(?=(\{\{)))/,/^(?:[^\x00]*?(?=(\{\{)))/,/^(?:[^\x00]+)/,/^(?:[^\x00]{2,}?(?=(\{\{|$)))/,/^(?:[\s\S]*?--\}\})/,/^(?:\{\{>)/,/^(?:\{\{#)/,/^(?:\{\{\/)/,/^(?:\{\{\^)/,/^(?:\{\{\s*else\b)/,/^(?:\{\{\{)/,/^(?:\{\{&)/,/^(?:\{\{!--)/,/^(?:\{\{![\s\S]*?\}\})/,/^(?:\{\{)/,/^(?:=)/,/^(?:\.(?=[}\/ ]))/,/^(?:\.\.)/,/^(?:[\/.])/,/^(?:\s+)/,/^(?:\}\}\})/,/^(?:\}\})/,/^(?:"(\\["]|[^"])*")/,/^(?:'(\\[']|[^'])*')/,/^(?:@)/,/^(?:true(?=[}\s]))/,/^(?:false(?=[}\s]))/,/^(?:-?[0-9]+(?=[}\s]))/,/^(?:[^\s!"#%-,\.\/;->@\[-\^`\{-~]+(?=[=}\s\/.]))/,/^(?:\[[^\]]*\])/,/^(?:.)/,/^(?:$)/];
660
- lexer.conditions = {"mu":{"rules":[5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31],"inclusive":false},"emu":{"rules":[3],"inclusive":false},"com":{"rules":[4],"inclusive":false},"INITIAL":{"rules":[0,1,2,31],"inclusive":true}};
661
- return lexer;})()
662
- parser.lexer = lexer;
663
- function Parser () { this.yy = {}; }Parser.prototype = parser;parser.Parser = Parser;
664
- return new Parser;
665
- })();;
666
- // lib/handlebars/compiler/base.js
667
-
668
- Handlebars.Parser = handlebars;
669
-
670
- Handlebars.parse = function(input) {
671
-
672
- // Just return if an already-compile AST was passed in.
673
- if(input.constructor === Handlebars.AST.ProgramNode) { return input; }
674
-
675
- Handlebars.Parser.yy = Handlebars.AST;
676
- return Handlebars.Parser.parse(input);
677
- };
678
- ;
679
- // lib/handlebars/compiler/ast.js
680
- Handlebars.AST = {};
681
-
682
- Handlebars.AST.ProgramNode = function(statements, inverse) {
683
- this.type = "program";
684
- this.statements = statements;
685
- if(inverse) { this.inverse = new Handlebars.AST.ProgramNode(inverse); }
686
- };
687
-
688
- Handlebars.AST.MustacheNode = function(rawParams, hash, unescaped) {
689
- this.type = "mustache";
690
- this.escaped = !unescaped;
691
- this.hash = hash;
692
-
693
- var id = this.id = rawParams[0];
694
- var params = this.params = rawParams.slice(1);
695
-
696
- // a mustache is an eligible helper if:
697
- // * its id is simple (a single part, not `this` or `..`)
698
- var eligibleHelper = this.eligibleHelper = id.isSimple;
699
-
700
- // a mustache is definitely a helper if:
701
- // * it is an eligible helper, and
702
- // * it has at least one parameter or hash segment
703
- this.isHelper = eligibleHelper && (params.length || hash);
704
-
705
- // if a mustache is an eligible helper but not a definite
706
- // helper, it is ambiguous, and will be resolved in a later
707
- // pass or at runtime.
708
- };
709
-
710
- Handlebars.AST.PartialNode = function(partialName, context) {
711
- this.type = "partial";
712
- this.partialName = partialName;
713
- this.context = context;
714
- };
715
-
716
- Handlebars.AST.BlockNode = function(mustache, program, inverse, close) {
717
- var verifyMatch = function(open, close) {
718
- if(open.original !== close.original) {
719
- throw new Handlebars.Exception(open.original + " doesn't match " + close.original);
720
- }
721
- };
722
-
723
- verifyMatch(mustache.id, close);
724
- this.type = "block";
725
- this.mustache = mustache;
726
- this.program = program;
727
- this.inverse = inverse;
728
-
729
- if (this.inverse && !this.program) {
730
- this.isInverse = true;
731
- }
732
- };
733
-
734
- Handlebars.AST.ContentNode = function(string) {
735
- this.type = "content";
736
- this.string = string;
737
- };
738
-
739
- Handlebars.AST.HashNode = function(pairs) {
740
- this.type = "hash";
741
- this.pairs = pairs;
742
- };
743
-
744
- Handlebars.AST.IdNode = function(parts) {
745
- this.type = "ID";
746
-
747
- var original = "",
748
- dig = [],
749
- depth = 0;
750
-
751
- for(var i=0,l=parts.length; i<l; i++) {
752
- var part = parts[i].part;
753
- original += (parts[i].separator || '') + part;
754
-
755
- if (part === ".." || part === "." || part === "this") {
756
- if (dig.length > 0) { throw new Handlebars.Exception("Invalid path: " + original); }
757
- else if (part === "..") { depth++; }
758
- else { this.isScoped = true; }
759
- }
760
- else { dig.push(part); }
761
- }
762
-
763
- this.original = original;
764
- this.parts = dig;
765
- this.string = dig.join('.');
766
- this.depth = depth;
767
-
768
- // an ID is simple if it only has one part, and that part is not
769
- // `..` or `this`.
770
- this.isSimple = parts.length === 1 && !this.isScoped && depth === 0;
771
-
772
- this.stringModeValue = this.string;
773
- };
774
-
775
- Handlebars.AST.PartialNameNode = function(name) {
776
- this.type = "PARTIAL_NAME";
777
- this.name = name.original;
778
- };
779
-
780
- Handlebars.AST.DataNode = function(id) {
781
- this.type = "DATA";
782
- this.id = id;
783
- };
784
-
785
- Handlebars.AST.StringNode = function(string) {
786
- this.type = "STRING";
787
- this.original =
788
- this.string =
789
- this.stringModeValue = string;
790
- };
791
-
792
- Handlebars.AST.IntegerNode = function(integer) {
793
- this.type = "INTEGER";
794
- this.original =
795
- this.integer = integer;
796
- this.stringModeValue = Number(integer);
797
- };
798
-
799
- Handlebars.AST.BooleanNode = function(bool) {
800
- this.type = "BOOLEAN";
801
- this.bool = bool;
802
- this.stringModeValue = bool === "true";
803
- };
804
-
805
- Handlebars.AST.CommentNode = function(comment) {
806
- this.type = "comment";
807
- this.comment = comment;
808
- };
809
- ;
810
- // lib/handlebars/utils.js
811
-
812
- var errorProps = ['description', 'fileName', 'lineNumber', 'message', 'name', 'number', 'stack'];
813
-
814
- Handlebars.Exception = function(message) {
815
- var tmp = Error.prototype.constructor.apply(this, arguments);
816
-
817
- // Unfortunately errors are not enumerable in Chrome (at least), so `for prop in tmp` doesn't work.
818
- for (var idx = 0; idx < errorProps.length; idx++) {
819
- this[errorProps[idx]] = tmp[errorProps[idx]];
820
- }
821
- };
822
- Handlebars.Exception.prototype = new Error();
823
-
824
- // Build out our basic SafeString type
825
- Handlebars.SafeString = function(string) {
826
- this.string = string;
827
- };
828
- Handlebars.SafeString.prototype.toString = function() {
829
- return this.string.toString();
830
- };
831
-
832
- var escape = {
833
- "&": "&amp;",
834
- "<": "&lt;",
835
- ">": "&gt;",
836
- '"': "&quot;",
837
- "'": "&#x27;",
838
- "`": "&#x60;"
839
- };
840
-
841
- var badChars = /[&<>"'`]/g;
842
- var possible = /[&<>"'`]/;
843
-
844
- var escapeChar = function(chr) {
845
- return escape[chr] || "&amp;";
846
- };
847
-
848
- Handlebars.Utils = {
849
- extend: function(obj, value) {
850
- for(var key in value) {
851
- if(value.hasOwnProperty(key)) {
852
- obj[key] = value[key];
853
- }
854
- }
855
- },
856
-
857
- escapeExpression: function(string) {
858
- // don't escape SafeStrings, since they're already safe
859
- if (string instanceof Handlebars.SafeString) {
860
- return string.toString();
861
- } else if (string == null || string === false) {
862
- return "";
863
- }
864
-
865
- // Force a string conversion as this will be done by the append regardless and
866
- // the regex test will do this transparently behind the scenes, causing issues if
867
- // an object's to string has escaped characters in it.
868
- string = string.toString();
869
-
870
- if(!possible.test(string)) { return string; }
871
- return string.replace(badChars, escapeChar);
872
- },
873
-
874
- isEmpty: function(value) {
875
- if (!value && value !== 0) {
876
- return true;
877
- } else if(toString.call(value) === "[object Array]" && value.length === 0) {
878
- return true;
879
- } else {
880
- return false;
881
- }
882
- }
883
- };
884
- ;
885
- // lib/handlebars/compiler/compiler.js
886
-
887
- /*jshint eqnull:true*/
888
- var Compiler = Handlebars.Compiler = function() {};
889
- var JavaScriptCompiler = Handlebars.JavaScriptCompiler = function() {};
890
-
891
- // the foundHelper register will disambiguate helper lookup from finding a
892
- // function in a context. This is necessary for mustache compatibility, which
893
- // requires that context functions in blocks are evaluated by blockHelperMissing,
894
- // and then proceed as if the resulting value was provided to blockHelperMissing.
895
-
896
- Compiler.prototype = {
897
- compiler: Compiler,
898
-
899
- disassemble: function() {
900
- var opcodes = this.opcodes, opcode, out = [], params, param;
901
-
902
- for (var i=0, l=opcodes.length; i<l; i++) {
903
- opcode = opcodes[i];
904
-
905
- if (opcode.opcode === 'DECLARE') {
906
- out.push("DECLARE " + opcode.name + "=" + opcode.value);
907
- } else {
908
- params = [];
909
- for (var j=0; j<opcode.args.length; j++) {
910
- param = opcode.args[j];
911
- if (typeof param === "string") {
912
- param = "\"" + param.replace("\n", "\\n") + "\"";
913
- }
914
- params.push(param);
915
- }
916
- out.push(opcode.opcode + " " + params.join(" "));
917
- }
918
- }
919
-
920
- return out.join("\n");
921
- },
922
- equals: function(other) {
923
- var len = this.opcodes.length;
924
- if (other.opcodes.length !== len) {
925
- return false;
926
- }
927
-
928
- for (var i = 0; i < len; i++) {
929
- var opcode = this.opcodes[i],
930
- otherOpcode = other.opcodes[i];
931
- if (opcode.opcode !== otherOpcode.opcode || opcode.args.length !== otherOpcode.args.length) {
932
- return false;
933
- }
934
- for (var j = 0; j < opcode.args.length; j++) {
935
- if (opcode.args[j] !== otherOpcode.args[j]) {
936
- return false;
937
- }
938
- }
939
- }
940
-
941
- len = this.children.length;
942
- if (other.children.length !== len) {
943
- return false;
944
- }
945
- for (i = 0; i < len; i++) {
946
- if (!this.children[i].equals(other.children[i])) {
947
- return false;
948
- }
949
- }
950
-
951
- return true;
952
- },
953
-
954
- guid: 0,
955
-
956
- compile: function(program, options) {
957
- this.children = [];
958
- this.depths = {list: []};
959
- this.options = options;
960
-
961
- // These changes will propagate to the other compiler components
962
- var knownHelpers = this.options.knownHelpers;
963
- this.options.knownHelpers = {
964
- 'helperMissing': true,
965
- 'blockHelperMissing': true,
966
- 'each': true,
967
- 'if': true,
968
- 'unless': true,
969
- 'with': true,
970
- 'log': true
971
- };
972
- if (knownHelpers) {
973
- for (var name in knownHelpers) {
974
- this.options.knownHelpers[name] = knownHelpers[name];
975
- }
976
- }
977
-
978
- return this.program(program);
979
- },
980
-
981
- accept: function(node) {
982
- return this[node.type](node);
983
- },
984
-
985
- program: function(program) {
986
- var statements = program.statements, statement;
987
- this.opcodes = [];
988
-
989
- for(var i=0, l=statements.length; i<l; i++) {
990
- statement = statements[i];
991
- this[statement.type](statement);
992
- }
993
- this.isSimple = l === 1;
994
-
995
- this.depths.list = this.depths.list.sort(function(a, b) {
996
- return a - b;
997
- });
998
-
999
- return this;
1000
- },
1001
-
1002
- compileProgram: function(program) {
1003
- var result = new this.compiler().compile(program, this.options);
1004
- var guid = this.guid++, depth;
1005
-
1006
- this.usePartial = this.usePartial || result.usePartial;
1007
-
1008
- this.children[guid] = result;
1009
-
1010
- for(var i=0, l=result.depths.list.length; i<l; i++) {
1011
- depth = result.depths.list[i];
1012
-
1013
- if(depth < 2) { continue; }
1014
- else { this.addDepth(depth - 1); }
1015
- }
1016
-
1017
- return guid;
1018
- },
1019
-
1020
- block: function(block) {
1021
- var mustache = block.mustache,
1022
- program = block.program,
1023
- inverse = block.inverse;
1024
-
1025
- if (program) {
1026
- program = this.compileProgram(program);
1027
- }
1028
-
1029
- if (inverse) {
1030
- inverse = this.compileProgram(inverse);
1031
- }
1032
-
1033
- var type = this.classifyMustache(mustache);
1034
-
1035
- if (type === "helper") {
1036
- this.helperMustache(mustache, program, inverse);
1037
- } else if (type === "simple") {
1038
- this.simpleMustache(mustache);
1039
-
1040
- // now that the simple mustache is resolved, we need to
1041
- // evaluate it by executing `blockHelperMissing`
1042
- this.opcode('pushProgram', program);
1043
- this.opcode('pushProgram', inverse);
1044
- this.opcode('emptyHash');
1045
- this.opcode('blockValue');
1046
- } else {
1047
- this.ambiguousMustache(mustache, program, inverse);
1048
-
1049
- // now that the simple mustache is resolved, we need to
1050
- // evaluate it by executing `blockHelperMissing`
1051
- this.opcode('pushProgram', program);
1052
- this.opcode('pushProgram', inverse);
1053
- this.opcode('emptyHash');
1054
- this.opcode('ambiguousBlockValue');
1055
- }
1056
-
1057
- this.opcode('append');
1058
- },
1059
-
1060
- hash: function(hash) {
1061
- var pairs = hash.pairs, pair, val;
1062
-
1063
- this.opcode('pushHash');
1064
-
1065
- for(var i=0, l=pairs.length; i<l; i++) {
1066
- pair = pairs[i];
1067
- val = pair[1];
1068
-
1069
- if (this.options.stringParams) {
1070
- if(val.depth) {
1071
- this.addDepth(val.depth);
1072
- }
1073
- this.opcode('getContext', val.depth || 0);
1074
- this.opcode('pushStringParam', val.stringModeValue, val.type);
1075
- } else {
1076
- this.accept(val);
1077
- }
1078
-
1079
- this.opcode('assignToHash', pair[0]);
1080
- }
1081
- this.opcode('popHash');
1082
- },
1083
-
1084
- partial: function(partial) {
1085
- var partialName = partial.partialName;
1086
- this.usePartial = true;
1087
-
1088
- if(partial.context) {
1089
- this.ID(partial.context);
1090
- } else {
1091
- this.opcode('push', 'depth0');
1092
- }
1093
-
1094
- this.opcode('invokePartial', partialName.name);
1095
- this.opcode('append');
1096
- },
1097
-
1098
- content: function(content) {
1099
- this.opcode('appendContent', content.string);
1100
- },
1101
-
1102
- mustache: function(mustache) {
1103
- var options = this.options;
1104
- var type = this.classifyMustache(mustache);
1105
-
1106
- if (type === "simple") {
1107
- this.simpleMustache(mustache);
1108
- } else if (type === "helper") {
1109
- this.helperMustache(mustache);
1110
- } else {
1111
- this.ambiguousMustache(mustache);
1112
- }
1113
-
1114
- if(mustache.escaped && !options.noEscape) {
1115
- this.opcode('appendEscaped');
1116
- } else {
1117
- this.opcode('append');
1118
- }
1119
- },
1120
-
1121
- ambiguousMustache: function(mustache, program, inverse) {
1122
- var id = mustache.id,
1123
- name = id.parts[0],
1124
- isBlock = program != null || inverse != null;
1125
-
1126
- this.opcode('getContext', id.depth);
1127
-
1128
- this.opcode('pushProgram', program);
1129
- this.opcode('pushProgram', inverse);
1130
-
1131
- this.opcode('invokeAmbiguous', name, isBlock);
1132
- },
1133
-
1134
- simpleMustache: function(mustache) {
1135
- var id = mustache.id;
1136
-
1137
- if (id.type === 'DATA') {
1138
- this.DATA(id);
1139
- } else if (id.parts.length) {
1140
- this.ID(id);
1141
- } else {
1142
- // Simplified ID for `this`
1143
- this.addDepth(id.depth);
1144
- this.opcode('getContext', id.depth);
1145
- this.opcode('pushContext');
1146
- }
1147
-
1148
- this.opcode('resolvePossibleLambda');
1149
- },
1150
-
1151
- helperMustache: function(mustache, program, inverse) {
1152
- var params = this.setupFullMustacheParams(mustache, program, inverse),
1153
- name = mustache.id.parts[0];
1154
-
1155
- if (this.options.knownHelpers[name]) {
1156
- this.opcode('invokeKnownHelper', params.length, name);
1157
- } else if (this.options.knownHelpersOnly) {
1158
- throw new Error("You specified knownHelpersOnly, but used the unknown helper " + name);
1159
- } else {
1160
- this.opcode('invokeHelper', params.length, name);
1161
- }
1162
- },
1163
-
1164
- ID: function(id) {
1165
- this.addDepth(id.depth);
1166
- this.opcode('getContext', id.depth);
1167
-
1168
- var name = id.parts[0];
1169
- if (!name) {
1170
- this.opcode('pushContext');
1171
- } else {
1172
- this.opcode('lookupOnContext', id.parts[0]);
1173
- }
1174
-
1175
- for(var i=1, l=id.parts.length; i<l; i++) {
1176
- this.opcode('lookup', id.parts[i]);
1177
- }
1178
- },
1179
-
1180
- DATA: function(data) {
1181
- this.options.data = true;
1182
- if (data.id.isScoped || data.id.depth) {
1183
- throw new Handlebars.Exception('Scoped data references are not supported: ' + data.original);
1184
- }
1185
-
1186
- this.opcode('lookupData');
1187
- var parts = data.id.parts;
1188
- for(var i=0, l=parts.length; i<l; i++) {
1189
- this.opcode('lookup', parts[i]);
1190
- }
1191
- },
1192
-
1193
- STRING: function(string) {
1194
- this.opcode('pushString', string.string);
1195
- },
1196
-
1197
- INTEGER: function(integer) {
1198
- this.opcode('pushLiteral', integer.integer);
1199
- },
1200
-
1201
- BOOLEAN: function(bool) {
1202
- this.opcode('pushLiteral', bool.bool);
1203
- },
1204
-
1205
- comment: function() {},
1206
-
1207
- // HELPERS
1208
- opcode: function(name) {
1209
- this.opcodes.push({ opcode: name, args: [].slice.call(arguments, 1) });
1210
- },
1211
-
1212
- declare: function(name, value) {
1213
- this.opcodes.push({ opcode: 'DECLARE', name: name, value: value });
1214
- },
1215
-
1216
- addDepth: function(depth) {
1217
- if(isNaN(depth)) { throw new Error("EWOT"); }
1218
- if(depth === 0) { return; }
1219
-
1220
- if(!this.depths[depth]) {
1221
- this.depths[depth] = true;
1222
- this.depths.list.push(depth);
1223
- }
1224
- },
1225
-
1226
- classifyMustache: function(mustache) {
1227
- var isHelper = mustache.isHelper;
1228
- var isEligible = mustache.eligibleHelper;
1229
- var options = this.options;
1230
-
1231
- // if ambiguous, we can possibly resolve the ambiguity now
1232
- if (isEligible && !isHelper) {
1233
- var name = mustache.id.parts[0];
1234
-
1235
- if (options.knownHelpers[name]) {
1236
- isHelper = true;
1237
- } else if (options.knownHelpersOnly) {
1238
- isEligible = false;
1239
- }
1240
- }
1241
-
1242
- if (isHelper) { return "helper"; }
1243
- else if (isEligible) { return "ambiguous"; }
1244
- else { return "simple"; }
1245
- },
1246
-
1247
- pushParams: function(params) {
1248
- var i = params.length, param;
1249
-
1250
- while(i--) {
1251
- param = params[i];
1252
-
1253
- if(this.options.stringParams) {
1254
- if(param.depth) {
1255
- this.addDepth(param.depth);
1256
- }
1257
-
1258
- this.opcode('getContext', param.depth || 0);
1259
- this.opcode('pushStringParam', param.stringModeValue, param.type);
1260
- } else {
1261
- this[param.type](param);
1262
- }
1263
- }
1264
- },
1265
-
1266
- setupMustacheParams: function(mustache) {
1267
- var params = mustache.params;
1268
- this.pushParams(params);
1269
-
1270
- if(mustache.hash) {
1271
- this.hash(mustache.hash);
1272
- } else {
1273
- this.opcode('emptyHash');
1274
- }
1275
-
1276
- return params;
1277
- },
1278
-
1279
- // this will replace setupMustacheParams when we're done
1280
- setupFullMustacheParams: function(mustache, program, inverse) {
1281
- var params = mustache.params;
1282
- this.pushParams(params);
1283
-
1284
- this.opcode('pushProgram', program);
1285
- this.opcode('pushProgram', inverse);
1286
-
1287
- if(mustache.hash) {
1288
- this.hash(mustache.hash);
1289
- } else {
1290
- this.opcode('emptyHash');
1291
- }
1292
-
1293
- return params;
1294
- }
1295
- };
1296
-
1297
- var Literal = function(value) {
1298
- this.value = value;
1299
- };
1300
-
1301
- JavaScriptCompiler.prototype = {
1302
- // PUBLIC API: You can override these methods in a subclass to provide
1303
- // alternative compiled forms for name lookup and buffering semantics
1304
- nameLookup: function(parent, name /* , type*/) {
1305
- if (/^[0-9]+$/.test(name)) {
1306
- return parent + "[" + name + "]";
1307
- } else if (JavaScriptCompiler.isValidJavaScriptVariableName(name)) {
1308
- return parent + "." + name;
1309
- }
1310
- else {
1311
- return parent + "['" + name + "']";
1312
- }
1313
- },
1314
-
1315
- appendToBuffer: function(string) {
1316
- if (this.environment.isSimple) {
1317
- return "return " + string + ";";
1318
- } else {
1319
- return {
1320
- appendToBuffer: true,
1321
- content: string,
1322
- toString: function() { return "buffer += " + string + ";"; }
1323
- };
1324
- }
1325
- },
1326
-
1327
- initializeBuffer: function() {
1328
- return this.quotedString("");
1329
- },
1330
-
1331
- namespace: "Handlebars",
1332
- // END PUBLIC API
1333
-
1334
- compile: function(environment, options, context, asObject) {
1335
- this.environment = environment;
1336
- this.options = options || {};
1337
-
1338
- Handlebars.log(Handlebars.logger.DEBUG, this.environment.disassemble() + "\n\n");
1339
-
1340
- this.name = this.environment.name;
1341
- this.isChild = !!context;
1342
- this.context = context || {
1343
- programs: [],
1344
- environments: [],
1345
- aliases: { }
1346
- };
1347
-
1348
- this.preamble();
1349
-
1350
- this.stackSlot = 0;
1351
- this.stackVars = [];
1352
- this.registers = { list: [] };
1353
- this.compileStack = [];
1354
- this.inlineStack = [];
1355
-
1356
- this.compileChildren(environment, options);
1357
-
1358
- var opcodes = environment.opcodes, opcode;
1359
-
1360
- this.i = 0;
1361
-
1362
- for(l=opcodes.length; this.i<l; this.i++) {
1363
- opcode = opcodes[this.i];
1364
-
1365
- if(opcode.opcode === 'DECLARE') {
1366
- this[opcode.name] = opcode.value;
1367
- } else {
1368
- this[opcode.opcode].apply(this, opcode.args);
1369
- }
1370
- }
1371
-
1372
- return this.createFunctionContext(asObject);
1373
- },
1374
-
1375
- nextOpcode: function() {
1376
- var opcodes = this.environment.opcodes;
1377
- return opcodes[this.i + 1];
1378
- },
1379
-
1380
- eat: function() {
1381
- this.i = this.i + 1;
1382
- },
1383
-
1384
- preamble: function() {
1385
- var out = [];
1386
-
1387
- if (!this.isChild) {
1388
- var namespace = this.namespace;
1389
-
1390
- var copies = "helpers = this.merge(helpers, " + namespace + ".helpers);";
1391
- if (this.environment.usePartial) { copies = copies + " partials = this.merge(partials, " + namespace + ".partials);"; }
1392
- if (this.options.data) { copies = copies + " data = data || {};"; }
1393
- out.push(copies);
1394
- } else {
1395
- out.push('');
1396
- }
1397
-
1398
- if (!this.environment.isSimple) {
1399
- out.push(", buffer = " + this.initializeBuffer());
1400
- } else {
1401
- out.push("");
1402
- }
1403
-
1404
- // track the last context pushed into place to allow skipping the
1405
- // getContext opcode when it would be a noop
1406
- this.lastContext = 0;
1407
- this.source = out;
1408
- },
1409
-
1410
- createFunctionContext: function(asObject) {
1411
- var locals = this.stackVars.concat(this.registers.list);
1412
-
1413
- if(locals.length > 0) {
1414
- this.source[1] = this.source[1] + ", " + locals.join(", ");
1415
- }
1416
-
1417
- // Generate minimizer alias mappings
1418
- if (!this.isChild) {
1419
- for (var alias in this.context.aliases) {
1420
- if (this.context.aliases.hasOwnProperty(alias)) {
1421
- this.source[1] = this.source[1] + ', ' + alias + '=' + this.context.aliases[alias];
1422
- }
1423
- }
1424
- }
1425
-
1426
- if (this.source[1]) {
1427
- this.source[1] = "var " + this.source[1].substring(2) + ";";
1428
- }
1429
-
1430
- // Merge children
1431
- if (!this.isChild) {
1432
- this.source[1] += '\n' + this.context.programs.join('\n') + '\n';
1433
- }
1434
-
1435
- if (!this.environment.isSimple) {
1436
- this.source.push("return buffer;");
1437
- }
1438
-
1439
- var params = this.isChild ? ["depth0", "data"] : ["Handlebars", "depth0", "helpers", "partials", "data"];
1440
-
1441
- for(var i=0, l=this.environment.depths.list.length; i<l; i++) {
1442
- params.push("depth" + this.environment.depths.list[i]);
1443
- }
1444
-
1445
- // Perform a second pass over the output to merge content when possible
1446
- var source = this.mergeSource();
1447
-
1448
- if (!this.isChild) {
1449
- var revision = Handlebars.COMPILER_REVISION,
1450
- versions = Handlebars.REVISION_CHANGES[revision];
1451
- source = "this.compilerInfo = ["+revision+",'"+versions+"'];\n"+source;
1452
- }
1453
-
1454
- if (asObject) {
1455
- params.push(source);
1456
-
1457
- return Function.apply(this, params);
1458
- } else {
1459
- var functionSource = 'function ' + (this.name || '') + '(' + params.join(',') + ') {\n ' + source + '}';
1460
- Handlebars.log(Handlebars.logger.DEBUG, functionSource + "\n\n");
1461
- return functionSource;
1462
- }
1463
- },
1464
- mergeSource: function() {
1465
- // WARN: We are not handling the case where buffer is still populated as the source should
1466
- // not have buffer append operations as their final action.
1467
- var source = '',
1468
- buffer;
1469
- for (var i = 0, len = this.source.length; i < len; i++) {
1470
- var line = this.source[i];
1471
- if (line.appendToBuffer) {
1472
- if (buffer) {
1473
- buffer = buffer + '\n + ' + line.content;
1474
- } else {
1475
- buffer = line.content;
1476
- }
1477
- } else {
1478
- if (buffer) {
1479
- source += 'buffer += ' + buffer + ';\n ';
1480
- buffer = undefined;
1481
- }
1482
- source += line + '\n ';
1483
- }
1484
- }
1485
- return source;
1486
- },
1487
-
1488
- // [blockValue]
1489
- //
1490
- // On stack, before: hash, inverse, program, value
1491
- // On stack, after: return value of blockHelperMissing
1492
- //
1493
- // The purpose of this opcode is to take a block of the form
1494
- // `{{#foo}}...{{/foo}}`, resolve the value of `foo`, and
1495
- // replace it on the stack with the result of properly
1496
- // invoking blockHelperMissing.
1497
- blockValue: function() {
1498
- this.context.aliases.blockHelperMissing = 'helpers.blockHelperMissing';
1499
-
1500
- var params = ["depth0"];
1501
- this.setupParams(0, params);
1502
-
1503
- this.replaceStack(function(current) {
1504
- params.splice(1, 0, current);
1505
- return "blockHelperMissing.call(" + params.join(", ") + ")";
1506
- });
1507
- },
1508
-
1509
- // [ambiguousBlockValue]
1510
- //
1511
- // On stack, before: hash, inverse, program, value
1512
- // Compiler value, before: lastHelper=value of last found helper, if any
1513
- // On stack, after, if no lastHelper: same as [blockValue]
1514
- // On stack, after, if lastHelper: value
1515
- ambiguousBlockValue: function() {
1516
- this.context.aliases.blockHelperMissing = 'helpers.blockHelperMissing';
1517
-
1518
- var params = ["depth0"];
1519
- this.setupParams(0, params);
1520
-
1521
- var current = this.topStack();
1522
- params.splice(1, 0, current);
1523
-
1524
- // Use the options value generated from the invocation
1525
- params[params.length-1] = 'options';
1526
-
1527
- this.source.push("if (!" + this.lastHelper + ") { " + current + " = blockHelperMissing.call(" + params.join(", ") + "); }");
1528
- },
1529
-
1530
- // [appendContent]
1531
- //
1532
- // On stack, before: ...
1533
- // On stack, after: ...
1534
- //
1535
- // Appends the string value of `content` to the current buffer
1536
- appendContent: function(content) {
1537
- this.source.push(this.appendToBuffer(this.quotedString(content)));
1538
- },
1539
-
1540
- // [append]
1541
- //
1542
- // On stack, before: value, ...
1543
- // On stack, after: ...
1544
- //
1545
- // Coerces `value` to a String and appends it to the current buffer.
1546
- //
1547
- // If `value` is truthy, or 0, it is coerced into a string and appended
1548
- // Otherwise, the empty string is appended
1549
- append: function() {
1550
- // Force anything that is inlined onto the stack so we don't have duplication
1551
- // when we examine local
1552
- this.flushInline();
1553
- var local = this.popStack();
1554
- this.source.push("if(" + local + " || " + local + " === 0) { " + this.appendToBuffer(local) + " }");
1555
- if (this.environment.isSimple) {
1556
- this.source.push("else { " + this.appendToBuffer("''") + " }");
1557
- }
1558
- },
1559
-
1560
- // [appendEscaped]
1561
- //
1562
- // On stack, before: value, ...
1563
- // On stack, after: ...
1564
- //
1565
- // Escape `value` and append it to the buffer
1566
- appendEscaped: function() {
1567
- this.context.aliases.escapeExpression = 'this.escapeExpression';
1568
-
1569
- this.source.push(this.appendToBuffer("escapeExpression(" + this.popStack() + ")"));
1570
- },
1571
-
1572
- // [getContext]
1573
- //
1574
- // On stack, before: ...
1575
- // On stack, after: ...
1576
- // Compiler value, after: lastContext=depth
1577
- //
1578
- // Set the value of the `lastContext` compiler value to the depth
1579
- getContext: function(depth) {
1580
- if(this.lastContext !== depth) {
1581
- this.lastContext = depth;
1582
- }
1583
- },
1584
-
1585
- // [lookupOnContext]
1586
- //
1587
- // On stack, before: ...
1588
- // On stack, after: currentContext[name], ...
1589
- //
1590
- // Looks up the value of `name` on the current context and pushes
1591
- // it onto the stack.
1592
- lookupOnContext: function(name) {
1593
- this.push(this.nameLookup('depth' + this.lastContext, name, 'context'));
1594
- },
1595
-
1596
- // [pushContext]
1597
- //
1598
- // On stack, before: ...
1599
- // On stack, after: currentContext, ...
1600
- //
1601
- // Pushes the value of the current context onto the stack.
1602
- pushContext: function() {
1603
- this.pushStackLiteral('depth' + this.lastContext);
1604
- },
1605
-
1606
- // [resolvePossibleLambda]
1607
- //
1608
- // On stack, before: value, ...
1609
- // On stack, after: resolved value, ...
1610
- //
1611
- // If the `value` is a lambda, replace it on the stack by
1612
- // the return value of the lambda
1613
- resolvePossibleLambda: function() {
1614
- this.context.aliases.functionType = '"function"';
1615
-
1616
- this.replaceStack(function(current) {
1617
- return "typeof " + current + " === functionType ? " + current + ".apply(depth0) : " + current;
1618
- });
1619
- },
1620
-
1621
- // [lookup]
1622
- //
1623
- // On stack, before: value, ...
1624
- // On stack, after: value[name], ...
1625
- //
1626
- // Replace the value on the stack with the result of looking
1627
- // up `name` on `value`
1628
- lookup: function(name) {
1629
- this.replaceStack(function(current) {
1630
- return current + " == null || " + current + " === false ? " + current + " : " + this.nameLookup(current, name, 'context');
1631
- });
1632
- },
1633
-
1634
- // [lookupData]
1635
- //
1636
- // On stack, before: ...
1637
- // On stack, after: data[id], ...
1638
- //
1639
- // Push the result of looking up `id` on the current data
1640
- lookupData: function(id) {
1641
- this.push('data');
1642
- },
1643
-
1644
- // [pushStringParam]
1645
- //
1646
- // On stack, before: ...
1647
- // On stack, after: string, currentContext, ...
1648
- //
1649
- // This opcode is designed for use in string mode, which
1650
- // provides the string value of a parameter along with its
1651
- // depth rather than resolving it immediately.
1652
- pushStringParam: function(string, type) {
1653
- this.pushStackLiteral('depth' + this.lastContext);
1654
-
1655
- this.pushString(type);
1656
-
1657
- if (typeof string === 'string') {
1658
- this.pushString(string);
1659
- } else {
1660
- this.pushStackLiteral(string);
1661
- }
1662
- },
1663
-
1664
- emptyHash: function() {
1665
- this.pushStackLiteral('{}');
1666
-
1667
- if (this.options.stringParams) {
1668
- this.register('hashTypes', '{}');
1669
- this.register('hashContexts', '{}');
1670
- }
1671
- },
1672
- pushHash: function() {
1673
- this.hash = {values: [], types: [], contexts: []};
1674
- },
1675
- popHash: function() {
1676
- var hash = this.hash;
1677
- this.hash = undefined;
1678
-
1679
- if (this.options.stringParams) {
1680
- this.register('hashContexts', '{' + hash.contexts.join(',') + '}');
1681
- this.register('hashTypes', '{' + hash.types.join(',') + '}');
1682
- }
1683
- this.push('{\n ' + hash.values.join(',\n ') + '\n }');
1684
- },
1685
-
1686
- // [pushString]
1687
- //
1688
- // On stack, before: ...
1689
- // On stack, after: quotedString(string), ...
1690
- //
1691
- // Push a quoted version of `string` onto the stack
1692
- pushString: function(string) {
1693
- this.pushStackLiteral(this.quotedString(string));
1694
- },
1695
-
1696
- // [push]
1697
- //
1698
- // On stack, before: ...
1699
- // On stack, after: expr, ...
1700
- //
1701
- // Push an expression onto the stack
1702
- push: function(expr) {
1703
- this.inlineStack.push(expr);
1704
- return expr;
1705
- },
1706
-
1707
- // [pushLiteral]
1708
- //
1709
- // On stack, before: ...
1710
- // On stack, after: value, ...
1711
- //
1712
- // Pushes a value onto the stack. This operation prevents
1713
- // the compiler from creating a temporary variable to hold
1714
- // it.
1715
- pushLiteral: function(value) {
1716
- this.pushStackLiteral(value);
1717
- },
1718
-
1719
- // [pushProgram]
1720
- //
1721
- // On stack, before: ...
1722
- // On stack, after: program(guid), ...
1723
- //
1724
- // Push a program expression onto the stack. This takes
1725
- // a compile-time guid and converts it into a runtime-accessible
1726
- // expression.
1727
- pushProgram: function(guid) {
1728
- if (guid != null) {
1729
- this.pushStackLiteral(this.programExpression(guid));
1730
- } else {
1731
- this.pushStackLiteral(null);
1732
- }
1733
- },
1734
-
1735
- // [invokeHelper]
1736
- //
1737
- // On stack, before: hash, inverse, program, params..., ...
1738
- // On stack, after: result of helper invocation
1739
- //
1740
- // Pops off the helper's parameters, invokes the helper,
1741
- // and pushes the helper's return value onto the stack.
1742
- //
1743
- // If the helper is not found, `helperMissing` is called.
1744
- invokeHelper: function(paramSize, name) {
1745
- this.context.aliases.helperMissing = 'helpers.helperMissing';
1746
-
1747
- var helper = this.lastHelper = this.setupHelper(paramSize, name, true);
1748
- var nonHelper = this.nameLookup('depth' + this.lastContext, name, 'context');
1749
-
1750
- this.push(helper.name + ' || ' + nonHelper);
1751
- this.replaceStack(function(name) {
1752
- return name + ' ? ' + name + '.call(' +
1753
- helper.callParams + ") " + ": helperMissing.call(" +
1754
- helper.helperMissingParams + ")";
1755
- });
1756
- },
1757
-
1758
- // [invokeKnownHelper]
1759
- //
1760
- // On stack, before: hash, inverse, program, params..., ...
1761
- // On stack, after: result of helper invocation
1762
- //
1763
- // This operation is used when the helper is known to exist,
1764
- // so a `helperMissing` fallback is not required.
1765
- invokeKnownHelper: function(paramSize, name) {
1766
- var helper = this.setupHelper(paramSize, name);
1767
- this.push(helper.name + ".call(" + helper.callParams + ")");
1768
- },
1769
-
1770
- // [invokeAmbiguous]
1771
- //
1772
- // On stack, before: hash, inverse, program, params..., ...
1773
- // On stack, after: result of disambiguation
1774
- //
1775
- // This operation is used when an expression like `{{foo}}`
1776
- // is provided, but we don't know at compile-time whether it
1777
- // is a helper or a path.
1778
- //
1779
- // This operation emits more code than the other options,
1780
- // and can be avoided by passing the `knownHelpers` and
1781
- // `knownHelpersOnly` flags at compile-time.
1782
- invokeAmbiguous: function(name, helperCall) {
1783
- this.context.aliases.functionType = '"function"';
1784
-
1785
- this.pushStackLiteral('{}'); // Hash value
1786
- var helper = this.setupHelper(0, name, helperCall);
1787
-
1788
- var helperName = this.lastHelper = this.nameLookup('helpers', name, 'helper');
1789
-
1790
- var nonHelper = this.nameLookup('depth' + this.lastContext, name, 'context');
1791
- var nextStack = this.nextStack();
1792
-
1793
- this.source.push('if (' + nextStack + ' = ' + helperName + ') { ' + nextStack + ' = ' + nextStack + '.call(' + helper.callParams + '); }');
1794
- this.source.push('else { ' + nextStack + ' = ' + nonHelper + '; ' + nextStack + ' = typeof ' + nextStack + ' === functionType ? ' + nextStack + '.apply(depth0) : ' + nextStack + '; }');
1795
- },
1796
-
1797
- // [invokePartial]
1798
- //
1799
- // On stack, before: context, ...
1800
- // On stack after: result of partial invocation
1801
- //
1802
- // This operation pops off a context, invokes a partial with that context,
1803
- // and pushes the result of the invocation back.
1804
- invokePartial: function(name) {
1805
- var params = [this.nameLookup('partials', name, 'partial'), "'" + name + "'", this.popStack(), "helpers", "partials"];
1806
-
1807
- if (this.options.data) {
1808
- params.push("data");
1809
- }
1810
-
1811
- this.context.aliases.self = "this";
1812
- this.push("self.invokePartial(" + params.join(", ") + ")");
1813
- },
1814
-
1815
- // [assignToHash]
1816
- //
1817
- // On stack, before: value, hash, ...
1818
- // On stack, after: hash, ...
1819
- //
1820
- // Pops a value and hash off the stack, assigns `hash[key] = value`
1821
- // and pushes the hash back onto the stack.
1822
- assignToHash: function(key) {
1823
- var value = this.popStack(),
1824
- context,
1825
- type;
1826
-
1827
- if (this.options.stringParams) {
1828
- type = this.popStack();
1829
- context = this.popStack();
1830
- }
1831
-
1832
- var hash = this.hash;
1833
- if (context) {
1834
- hash.contexts.push("'" + key + "': " + context);
1835
- }
1836
- if (type) {
1837
- hash.types.push("'" + key + "': " + type);
1838
- }
1839
- hash.values.push("'" + key + "': (" + value + ")");
1840
- },
1841
-
1842
- // HELPERS
1843
-
1844
- compiler: JavaScriptCompiler,
1845
-
1846
- compileChildren: function(environment, options) {
1847
- var children = environment.children, child, compiler;
1848
-
1849
- for(var i=0, l=children.length; i<l; i++) {
1850
- child = children[i];
1851
- compiler = new this.compiler();
1852
-
1853
- var index = this.matchExistingProgram(child);
1854
-
1855
- if (index == null) {
1856
- this.context.programs.push(''); // Placeholder to prevent name conflicts for nested children
1857
- index = this.context.programs.length;
1858
- child.index = index;
1859
- child.name = 'program' + index;
1860
- this.context.programs[index] = compiler.compile(child, options, this.context);
1861
- this.context.environments[index] = child;
1862
- } else {
1863
- child.index = index;
1864
- child.name = 'program' + index;
1865
- }
1866
- }
1867
- },
1868
- matchExistingProgram: function(child) {
1869
- for (var i = 0, len = this.context.environments.length; i < len; i++) {
1870
- var environment = this.context.environments[i];
1871
- if (environment && environment.equals(child)) {
1872
- return i;
1873
- }
1874
- }
1875
- },
1876
-
1877
- programExpression: function(guid) {
1878
- this.context.aliases.self = "this";
1879
-
1880
- if(guid == null) {
1881
- return "self.noop";
1882
- }
1883
-
1884
- var child = this.environment.children[guid],
1885
- depths = child.depths.list, depth;
1886
-
1887
- var programParams = [child.index, child.name, "data"];
1888
-
1889
- for(var i=0, l = depths.length; i<l; i++) {
1890
- depth = depths[i];
1891
-
1892
- if(depth === 1) { programParams.push("depth0"); }
1893
- else { programParams.push("depth" + (depth - 1)); }
1894
- }
1895
-
1896
- return (depths.length === 0 ? "self.program(" : "self.programWithDepth(") + programParams.join(", ") + ")";
1897
- },
1898
-
1899
- register: function(name, val) {
1900
- this.useRegister(name);
1901
- this.source.push(name + " = " + val + ";");
1902
- },
1903
-
1904
- useRegister: function(name) {
1905
- if(!this.registers[name]) {
1906
- this.registers[name] = true;
1907
- this.registers.list.push(name);
1908
- }
1909
- },
1910
-
1911
- pushStackLiteral: function(item) {
1912
- return this.push(new Literal(item));
1913
- },
1914
-
1915
- pushStack: function(item) {
1916
- this.flushInline();
1917
-
1918
- var stack = this.incrStack();
1919
- if (item) {
1920
- this.source.push(stack + " = " + item + ";");
1921
- }
1922
- this.compileStack.push(stack);
1923
- return stack;
1924
- },
1925
-
1926
- replaceStack: function(callback) {
1927
- var prefix = '',
1928
- inline = this.isInline(),
1929
- stack;
1930
-
1931
- // If we are currently inline then we want to merge the inline statement into the
1932
- // replacement statement via ','
1933
- if (inline) {
1934
- var top = this.popStack(true);
1935
-
1936
- if (top instanceof Literal) {
1937
- // Literals do not need to be inlined
1938
- stack = top.value;
1939
- } else {
1940
- // Get or create the current stack name for use by the inline
1941
- var name = this.stackSlot ? this.topStackName() : this.incrStack();
1942
-
1943
- prefix = '(' + this.push(name) + ' = ' + top + '),';
1944
- stack = this.topStack();
1945
- }
1946
- } else {
1947
- stack = this.topStack();
1948
- }
1949
-
1950
- var item = callback.call(this, stack);
1951
-
1952
- if (inline) {
1953
- if (this.inlineStack.length || this.compileStack.length) {
1954
- this.popStack();
1955
- }
1956
- this.push('(' + prefix + item + ')');
1957
- } else {
1958
- // Prevent modification of the context depth variable. Through replaceStack
1959
- if (!/^stack/.test(stack)) {
1960
- stack = this.nextStack();
1961
- }
1962
-
1963
- this.source.push(stack + " = (" + prefix + item + ");");
1964
- }
1965
- return stack;
1966
- },
1967
-
1968
- nextStack: function() {
1969
- return this.pushStack();
1970
- },
1971
-
1972
- incrStack: function() {
1973
- this.stackSlot++;
1974
- if(this.stackSlot > this.stackVars.length) { this.stackVars.push("stack" + this.stackSlot); }
1975
- return this.topStackName();
1976
- },
1977
- topStackName: function() {
1978
- return "stack" + this.stackSlot;
1979
- },
1980
- flushInline: function() {
1981
- var inlineStack = this.inlineStack;
1982
- if (inlineStack.length) {
1983
- this.inlineStack = [];
1984
- for (var i = 0, len = inlineStack.length; i < len; i++) {
1985
- var entry = inlineStack[i];
1986
- if (entry instanceof Literal) {
1987
- this.compileStack.push(entry);
1988
- } else {
1989
- this.pushStack(entry);
1990
- }
1991
- }
1992
- }
1993
- },
1994
- isInline: function() {
1995
- return this.inlineStack.length;
1996
- },
1997
-
1998
- popStack: function(wrapped) {
1999
- var inline = this.isInline(),
2000
- item = (inline ? this.inlineStack : this.compileStack).pop();
2001
-
2002
- if (!wrapped && (item instanceof Literal)) {
2003
- return item.value;
2004
- } else {
2005
- if (!inline) {
2006
- this.stackSlot--;
2007
- }
2008
- return item;
2009
- }
2010
- },
2011
-
2012
- topStack: function(wrapped) {
2013
- var stack = (this.isInline() ? this.inlineStack : this.compileStack),
2014
- item = stack[stack.length - 1];
2015
-
2016
- if (!wrapped && (item instanceof Literal)) {
2017
- return item.value;
2018
- } else {
2019
- return item;
2020
- }
2021
- },
2022
-
2023
- quotedString: function(str) {
2024
- return '"' + str
2025
- .replace(/\\/g, '\\\\')
2026
- .replace(/"/g, '\\"')
2027
- .replace(/\n/g, '\\n')
2028
- .replace(/\r/g, '\\r')
2029
- .replace(/\u2028/g, '\\u2028') // Per Ecma-262 7.3 + 7.8.4
2030
- .replace(/\u2029/g, '\\u2029') + '"';
2031
- },
2032
-
2033
- setupHelper: function(paramSize, name, missingParams) {
2034
- var params = [];
2035
- this.setupParams(paramSize, params, missingParams);
2036
- var foundHelper = this.nameLookup('helpers', name, 'helper');
2037
-
2038
- return {
2039
- params: params,
2040
- name: foundHelper,
2041
- callParams: ["depth0"].concat(params).join(", "),
2042
- helperMissingParams: missingParams && ["depth0", this.quotedString(name)].concat(params).join(", ")
2043
- };
2044
- },
2045
-
2046
- // the params and contexts arguments are passed in arrays
2047
- // to fill in
2048
- setupParams: function(paramSize, params, useRegister) {
2049
- var options = [], contexts = [], types = [], param, inverse, program;
2050
-
2051
- options.push("hash:" + this.popStack());
2052
-
2053
- inverse = this.popStack();
2054
- program = this.popStack();
2055
-
2056
- // Avoid setting fn and inverse if neither are set. This allows
2057
- // helpers to do a check for `if (options.fn)`
2058
- if (program || inverse) {
2059
- if (!program) {
2060
- this.context.aliases.self = "this";
2061
- program = "self.noop";
2062
- }
2063
-
2064
- if (!inverse) {
2065
- this.context.aliases.self = "this";
2066
- inverse = "self.noop";
2067
- }
2068
-
2069
- options.push("inverse:" + inverse);
2070
- options.push("fn:" + program);
2071
- }
2072
-
2073
- for(var i=0; i<paramSize; i++) {
2074
- param = this.popStack();
2075
- params.push(param);
2076
-
2077
- if(this.options.stringParams) {
2078
- types.push(this.popStack());
2079
- contexts.push(this.popStack());
2080
- }
2081
- }
2082
-
2083
- if (this.options.stringParams) {
2084
- options.push("contexts:[" + contexts.join(",") + "]");
2085
- options.push("types:[" + types.join(",") + "]");
2086
- options.push("hashContexts:hashContexts");
2087
- options.push("hashTypes:hashTypes");
2088
- }
2089
-
2090
- if(this.options.data) {
2091
- options.push("data:data");
2092
- }
2093
-
2094
- options = "{" + options.join(",") + "}";
2095
- if (useRegister) {
2096
- this.register('options', options);
2097
- params.push('options');
2098
- } else {
2099
- params.push(options);
2100
- }
2101
- return params.join(", ");
2102
- }
2103
- };
2104
-
2105
- var reservedWords = (
2106
- "break else new var" +
2107
- " case finally return void" +
2108
- " catch for switch while" +
2109
- " continue function this with" +
2110
- " default if throw" +
2111
- " delete in try" +
2112
- " do instanceof typeof" +
2113
- " abstract enum int short" +
2114
- " boolean export interface static" +
2115
- " byte extends long super" +
2116
- " char final native synchronized" +
2117
- " class float package throws" +
2118
- " const goto private transient" +
2119
- " debugger implements protected volatile" +
2120
- " double import public let yield"
2121
- ).split(" ");
2122
-
2123
- var compilerWords = JavaScriptCompiler.RESERVED_WORDS = {};
2124
-
2125
- for(var i=0, l=reservedWords.length; i<l; i++) {
2126
- compilerWords[reservedWords[i]] = true;
2127
- }
2128
-
2129
- JavaScriptCompiler.isValidJavaScriptVariableName = function(name) {
2130
- if(!JavaScriptCompiler.RESERVED_WORDS[name] && /^[a-zA-Z_$][0-9a-zA-Z_$]+$/.test(name)) {
2131
- return true;
2132
- }
2133
- return false;
2134
- };
2135
-
2136
- Handlebars.precompile = function(input, options) {
2137
- if (input == null || (typeof input !== 'string' && input.constructor !== Handlebars.AST.ProgramNode)) {
2138
- throw new Handlebars.Exception("You must pass a string or Handlebars AST to Handlebars.precompile. You passed " + input);
2139
- }
2140
-
2141
- options = options || {};
2142
- if (!('data' in options)) {
2143
- options.data = true;
2144
- }
2145
- var ast = Handlebars.parse(input);
2146
- var environment = new Compiler().compile(ast, options);
2147
- return new JavaScriptCompiler().compile(environment, options);
2148
- };
2149
-
2150
- Handlebars.compile = function(input, options) {
2151
- if (input == null || (typeof input !== 'string' && input.constructor !== Handlebars.AST.ProgramNode)) {
2152
- throw new Handlebars.Exception("You must pass a string or Handlebars AST to Handlebars.compile. You passed " + input);
2153
- }
2154
-
2155
- options = options || {};
2156
- if (!('data' in options)) {
2157
- options.data = true;
2158
- }
2159
- var compiled;
2160
- function compile() {
2161
- var ast = Handlebars.parse(input);
2162
- var environment = new Compiler().compile(ast, options);
2163
- var templateSpec = new JavaScriptCompiler().compile(environment, options, undefined, true);
2164
- return Handlebars.template(templateSpec);
2165
- }
2166
-
2167
- // Template is only compiled on first use and cached after that point.
2168
- return function(context, options) {
2169
- if (!compiled) {
2170
- compiled = compile();
2171
- }
2172
- return compiled.call(this, context, options);
2173
- };
2174
- };
2175
-
2176
- ;
2177
- // lib/handlebars/runtime.js
2178
-
2179
- Handlebars.VM = {
2180
- template: function(templateSpec) {
2181
- // Just add water
2182
- var container = {
2183
- escapeExpression: Handlebars.Utils.escapeExpression,
2184
- invokePartial: Handlebars.VM.invokePartial,
2185
- programs: [],
2186
- program: function(i, fn, data) {
2187
- var programWrapper = this.programs[i];
2188
- if(data) {
2189
- programWrapper = Handlebars.VM.program(i, fn, data);
2190
- } else if (!programWrapper) {
2191
- programWrapper = this.programs[i] = Handlebars.VM.program(i, fn);
2192
- }
2193
- return programWrapper;
2194
- },
2195
- merge: function(param, common) {
2196
- var ret = param || common;
2197
-
2198
- if (param && common) {
2199
- ret = {};
2200
- Handlebars.Utils.extend(ret, common);
2201
- Handlebars.Utils.extend(ret, param);
2202
- }
2203
- return ret;
2204
- },
2205
- programWithDepth: Handlebars.VM.programWithDepth,
2206
- noop: Handlebars.VM.noop,
2207
- compilerInfo: null
2208
- };
2209
-
2210
- return function(context, options) {
2211
- options = options || {};
2212
- var result = templateSpec.call(container, Handlebars, context, options.helpers, options.partials, options.data);
2213
-
2214
- var compilerInfo = container.compilerInfo || [],
2215
- compilerRevision = compilerInfo[0] || 1,
2216
- currentRevision = Handlebars.COMPILER_REVISION;
2217
-
2218
- if (compilerRevision !== currentRevision) {
2219
- if (compilerRevision < currentRevision) {
2220
- var runtimeVersions = Handlebars.REVISION_CHANGES[currentRevision],
2221
- compilerVersions = Handlebars.REVISION_CHANGES[compilerRevision];
2222
- throw "Template was precompiled with an older version of Handlebars than the current runtime. "+
2223
- "Please update your precompiler to a newer version ("+runtimeVersions+") or downgrade your runtime to an older version ("+compilerVersions+").";
2224
- } else {
2225
- // Use the embedded version info since the runtime doesn't know about this revision yet
2226
- throw "Template was precompiled with a newer version of Handlebars than the current runtime. "+
2227
- "Please update your runtime to a newer version ("+compilerInfo[1]+").";
2228
- }
2229
- }
2230
-
2231
- return result;
2232
- };
2233
- },
2234
-
2235
- programWithDepth: function(i, fn, data /*, $depth */) {
2236
- var args = Array.prototype.slice.call(arguments, 3);
2237
-
2238
- var program = function(context, options) {
2239
- options = options || {};
2240
-
2241
- return fn.apply(this, [context, options.data || data].concat(args));
2242
- };
2243
- program.program = i;
2244
- program.depth = args.length;
2245
- return program;
2246
- },
2247
- program: function(i, fn, data) {
2248
- var program = function(context, options) {
2249
- options = options || {};
2250
-
2251
- return fn(context, options.data || data);
2252
- };
2253
- program.program = i;
2254
- program.depth = 0;
2255
- return program;
2256
- },
2257
- noop: function() { return ""; },
2258
- invokePartial: function(partial, name, context, helpers, partials, data) {
2259
- var options = { helpers: helpers, partials: partials, data: data };
2260
-
2261
- if(partial === undefined) {
2262
- throw new Handlebars.Exception("The partial " + name + " could not be found");
2263
- } else if(partial instanceof Function) {
2264
- return partial(context, options);
2265
- } else if (!Handlebars.compile) {
2266
- throw new Handlebars.Exception("The partial " + name + " could not be compiled when running in runtime-only mode");
2267
- } else {
2268
- partials[name] = Handlebars.compile(partial, {data: data !== undefined});
2269
- return partials[name](context, options);
2270
- }
2271
- }
2272
- };
2273
-
2274
- Handlebars.template = Handlebars.VM.template;
2275
- ;
2276
- // lib/handlebars/browser-suffix.js
2277
- })(Handlebars);
2278
- ;