hogan_assets 1.1.0 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- hogan_assets (1.1.0)
4
+ hogan_assets (1.2.0)
5
5
  execjs (>= 1.2.9)
6
6
  sprockets (>= 2.0.3)
7
7
  tilt (>= 1.3.3)
data/README.md CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  **hogan.js** is a templating engine developed at [Twitter](http://twitter.com) that follows the **mustache** spec and compiles the templates to JavaScript. The first bit is *cool*, since **mustache** is *cool*. The second bit is **awesome and full of win** because we can now compile our **mustache** templates on the server using the asset pipeline/sprockets.
6
6
 
7
- This gem contains **hogan.js v1.0.5**
7
+ This gem contains **hogan.js v3.0.0**
8
8
 
9
9
  ## Installation
10
10
 
@@ -47,12 +47,12 @@ Require `hogan.js` somewhere in your JavaScript.
47
47
 
48
48
  ## Hamstache!
49
49
 
50
- _hamstache_ is the quite popular combination of `haml` and `mustache`, a more robust solution exists using [haml_assets](https://github.com/infbio/haml_assets), but if all you want is nicer markup, you need to take these two steps:
50
+ _hamstache_ is the quite popular combination of `haml` and `mustache`, a more robust solution exists using [haml_assets](https://github.com/infbio/haml_assets), but if all you want is nicer markup, you need to take these two additional steps:
51
51
 
52
52
  Add this line to your `Gemfile`:
53
53
 
54
54
  group :assets do
55
- gem 'hogan_assets'
55
+ gem 'haml'
56
56
  end
57
57
 
58
58
  And then execute:
@@ -63,7 +63,7 @@ And then execute:
63
63
 
64
64
  Templates are compiled to a global JavaScript object named `HoganTemplates`. To render `pages/person`:
65
65
 
66
- HoganTemplates['pages/person'].render(context, partials);
66
+ HoganTemplates['templates/pages/person'].render(context, partials);
67
67
 
68
68
  # Author
69
69
 
@@ -16,8 +16,6 @@ module HoganAssets
16
16
  yield self
17
17
  end
18
18
 
19
- attr_accessor :allow_hamstache
20
-
21
19
  attr_writer :template_extensions
22
20
 
23
21
  def template_extensions
@@ -1,3 +1,3 @@
1
1
  module HoganAssets
2
- VERSION = "1.1.0"
2
+ VERSION = "1.2.0"
3
3
  end
@@ -16,7 +16,7 @@ module HoganAssets
16
16
  template = HoganAssets::Tilt.new('/myapp/app/assets/templates/path/to/template.mustache') { "This is {{mustache}}" }
17
17
  assert_equal <<-END_EXPECTED, template.render(scope, {})
18
18
  this.HoganTemplates || (this.HoganTemplates = {});
19
- this.HoganTemplates[\"path/to/template\"] = new Hogan.Template(function(c,p,i){var _=this;_.b(i=i||\"\");_.b(\"This is \");_.b(_.v(_.f(\"mustache\",c,p,0)));return _.fl();;});
19
+ this.HoganTemplates[\"path/to/template\"] = new Hogan.Template({code: function (c,p,i) { var t=this;t.b(i=i||\"\");t.b(\"This is \");t.b(t.v(t.f(\"mustache\",c,p,0)));return t.fl(); },partials: {}, subs: { }});
20
20
  END_EXPECTED
21
21
  end
22
22
  end
@@ -18,12 +18,15 @@
18
18
  var Hogan = {};
19
19
 
20
20
  (function (Hogan, useArrayBuffer) {
21
- Hogan.Template = function (renderFunc, text, compiler, options) {
22
- this.r = renderFunc || this.r;
21
+ Hogan.Template = function (codeObj, text, compiler, options) {
22
+ codeObj = codeObj || {};
23
+ this.r = codeObj.code || this.r;
23
24
  this.c = compiler;
24
25
  this.options = options;
25
26
  this.text = text || '';
26
- this.buf = (useArrayBuffer) ? [] : '';
27
+ this.partials = codeObj.partials || {};
28
+ this.subs = codeObj.subs || {};
29
+ this.ib();
27
30
  }
28
31
 
29
32
  Hogan.Template.prototype = {
@@ -45,16 +48,43 @@ var Hogan = {};
45
48
  return this.r(context, partials, indent);
46
49
  },
47
50
 
48
- // tries to find a partial in the curent scope and render it
49
- rp: function(name, context, partials, indent) {
50
- var partial = partials[name];
51
+ // ensurePartial
52
+ ep: function(symbol, partials) {
53
+ var partial = this.partials[symbol];
51
54
 
52
- if (!partial) {
53
- return '';
55
+ // check to see that if we've instantiated this partial before
56
+ var template = partials[partial.name];
57
+ if (partial.instance && partial.base == template) {
58
+ return partial.instance;
59
+ }
60
+
61
+ if (typeof template == 'string') {
62
+ if (!this.c) {
63
+ throw new Error("No compiler available.");
64
+ }
65
+ template = this.c.compile(template, this.options);
54
66
  }
55
67
 
56
- if (this.c && typeof partial == 'string') {
57
- partial = this.c.compile(partial, this.options);
68
+ if (!template) {
69
+ return null;
70
+ }
71
+
72
+ // We use this to check whether the partials dictionary has changed
73
+ this.partials[symbol].base = template;
74
+
75
+ if (partial.subs) {
76
+ template = createSpecializedPartial(template, partial.subs, partial.partials);
77
+ }
78
+
79
+ this.partials[symbol].instance = template;
80
+ return template;
81
+ },
82
+
83
+ // tries to find a partial in the curent scope and render it
84
+ rp: function(symbol, context, partials, indent) {
85
+ var partial = this.ep(symbol, partials);
86
+ if (!partial) {
87
+ return '';
58
88
  }
59
89
 
60
90
  return partial.ri(context, partials, indent);
@@ -85,7 +115,7 @@ var Hogan = {};
85
115
  }
86
116
 
87
117
  if (typeof val == 'function') {
88
- val = this.ls(val, ctx, partials, inverted, start, end, tags);
118
+ val = this.ms(val, ctx, partials, inverted, start, end, tags);
89
119
  }
90
120
 
91
121
  pass = (val === '') || !!val;
@@ -108,7 +138,7 @@ var Hogan = {};
108
138
  }
109
139
 
110
140
  for (var i = 1; i < names.length; i++) {
111
- if (val && typeof val == 'object' && names[i] in val) {
141
+ if (val && typeof val == 'object' && val[names[i]] != null) {
112
142
  cx = val;
113
143
  val = val[names[i]];
114
144
  } else {
@@ -122,7 +152,7 @@ var Hogan = {};
122
152
 
123
153
  if (!returnFound && typeof val == 'function') {
124
154
  ctx.push(cx);
125
- val = this.lv(val, ctx, partials);
155
+ val = this.mv(val, ctx, partials);
126
156
  ctx.pop();
127
157
  }
128
158
 
@@ -137,7 +167,7 @@ var Hogan = {};
137
167
 
138
168
  for (var i = ctx.length - 1; i >= 0; i--) {
139
169
  v = ctx[i];
140
- if (v && typeof v == 'object' && key in v) {
170
+ if (v && typeof v == 'object' && v[key] != null) {
141
171
  val = v[key];
142
172
  found = true;
143
173
  break;
@@ -149,70 +179,100 @@ var Hogan = {};
149
179
  }
150
180
 
151
181
  if (!returnFound && typeof val == 'function') {
152
- val = this.lv(val, ctx, partials);
182
+ val = this.mv(val, ctx, partials);
153
183
  }
154
184
 
155
185
  return val;
156
186
  },
157
187
 
158
188
  // higher order templates
159
- ho: function(val, cx, partials, text, tags) {
160
- var compiler = this.c;
161
- var options = this.options;
162
- options.delimiters = tags;
163
- var t = val.call(cx, text, function(t) {
164
- return compiler.compile(t, options).render(cx, partials);
165
- });
166
- this.b(compiler.compile(t.toString(), options).render(cx, partials));
189
+ ls: function(func, cx, partials, text, tags) {
190
+ var oldTags = this.options.delimiters;
191
+
192
+ this.options.delimiters = tags;
193
+ this.b(this.ct(coerceToString(func.call(cx, text)), cx, partials));
194
+ this.options.delimiters = oldTags;
195
+
167
196
  return false;
168
197
  },
169
198
 
199
+ // compile text
200
+ ct: function(text, cx, partials) {
201
+ if (this.options.disableLambda) {
202
+ throw new Error('Lambda features disabled.');
203
+ }
204
+ return this.c.compile(text, this.options).render(cx, partials);
205
+ },
206
+
170
207
  // template result buffering
171
208
  b: (useArrayBuffer) ? function(s) { this.buf.push(s); } :
172
209
  function(s) { this.buf += s; },
210
+
173
211
  fl: (useArrayBuffer) ? function() { var r = this.buf.join(''); this.buf = []; return r; } :
174
212
  function() { var r = this.buf; this.buf = ''; return r; },
213
+ // init the buffer
214
+ ib: function () {
215
+ this.buf = (useArrayBuffer) ? [] : '';
216
+ },
175
217
 
176
- // lambda replace section
177
- ls: function(val, ctx, partials, inverted, start, end, tags) {
218
+ // method replace section
219
+ ms: function(func, ctx, partials, inverted, start, end, tags) {
178
220
  var cx = ctx[ctx.length - 1],
179
- t = null;
221
+ result = func.call(cx);
180
222
 
181
- if (!inverted && this.c && val.length > 0) {
182
- return this.ho(val, cx, partials, this.text.substring(start, end), tags);
183
- }
184
-
185
- t = val.call(cx);
186
-
187
- if (typeof t == 'function') {
223
+ if (typeof result == 'function') {
188
224
  if (inverted) {
189
225
  return true;
190
- } else if (this.c) {
191
- return this.ho(t, cx, partials, this.text.substring(start, end), tags);
226
+ } else {
227
+ return this.ls(result, cx, partials, this.text.substring(start, end), tags);
192
228
  }
193
229
  }
194
230
 
195
- return t;
231
+ return result;
196
232
  },
197
233
 
198
- // lambda replace variable
199
- lv: function(val, ctx, partials) {
234
+ // method replace variable
235
+ mv: function(func, ctx, partials) {
200
236
  var cx = ctx[ctx.length - 1];
201
- var result = val.call(cx);
202
- if (typeof result == 'function') {
203
- result = result.call(cx);
204
- }
205
- result = coerceToString(result);
237
+ var result = func.call(cx);
206
238
 
207
- if (this.c && ~result.indexOf("{\u007B")) {
208
- return this.c.compile(result, this.options).render(cx, partials);
239
+ if (typeof result == 'function') {
240
+ return this.ct(coerceToString(result.call(cx)), cx, partials);
209
241
  }
210
242
 
211
243
  return result;
244
+ },
245
+
246
+ sub: function(name, context, partials, indent) {
247
+ var f = this.subs[name];
248
+ if (f) {
249
+ f(context, partials, this, indent);
250
+ }
212
251
  }
213
252
 
214
253
  };
215
254
 
255
+ function createSpecializedPartial(instance, subs, partials) {
256
+ function PartialTemplate() {};
257
+ PartialTemplate.prototype = instance;
258
+ function Substitutions() {};
259
+ Substitutions.prototype = instance.subs;
260
+ var key;
261
+ var partial = new PartialTemplate();
262
+ partial.subs = new Substitutions();
263
+ partial.ib();
264
+
265
+ for (key in subs) {
266
+ partial.subs[key] = subs[key];
267
+ }
268
+
269
+ for (key in partials) {
270
+ partial.partials[key] = partials[key];
271
+ }
272
+
273
+ return partial;
274
+ }
275
+
216
276
  var rAmp = /&/g,
217
277
  rLt = /</g,
218
278
  rGt = />/g,
@@ -220,7 +280,6 @@ var Hogan = {};
220
280
  rQuot = /\"/g,
221
281
  hChars =/[&<>\"\']/;
222
282
 
223
-
224
283
  function coerceToString(val) {
225
284
  return String((val === null || val === undefined) ? '' : val);
226
285
  }
@@ -245,7 +304,6 @@ var Hogan = {};
245
304
 
246
305
 
247
306
 
248
-
249
307
  (function (Hogan) {
250
308
  // Setup regex assignments
251
309
  // remove whitespace according to Mustache spec
@@ -253,11 +311,13 @@ var Hogan = {};
253
311
  rQuot = /\"/g,
254
312
  rNewline = /\n/g,
255
313
  rCr = /\r/g,
256
- rSlash = /\\/g,
257
- tagTypes = {
258
- '#': 1, '^': 2, '/': 3, '!': 4, '>': 5,
259
- '<': 6, '=': 7, '_v': 8, '{': 9, '&': 10
260
- };
314
+ rSlash = /\\/g;
315
+
316
+ Hogan.tags = {
317
+ '#': 1, '^': 2, '<': 3, '$': 4,
318
+ '/': 5, '!': 6, '>': 7, '=': 8, '_v': 9,
319
+ '{': 10, '&': 11, '_t': 12
320
+ };
261
321
 
262
322
  Hogan.scan = function scan(text, delimiters) {
263
323
  var len = text.length,
@@ -277,7 +337,7 @@ var Hogan = {};
277
337
 
278
338
  function addBuf() {
279
339
  if (buf.length > 0) {
280
- tokens.push(new String(buf));
340
+ tokens.push({tag: '_t', text: new String(buf)});
281
341
  buf = '';
282
342
  }
283
343
  }
@@ -286,8 +346,8 @@ var Hogan = {};
286
346
  var isAllWhitespace = true;
287
347
  for (var j = lineStart; j < tokens.length; j++) {
288
348
  isAllWhitespace =
289
- (tokens[j].tag && tagTypes[tokens[j].tag] < tagTypes['_v']) ||
290
- (!tokens[j].tag && tokens[j].match(rIsWhitespace) === null);
349
+ (Hogan.tags[tokens[j].tag] < Hogan.tags['_v']) ||
350
+ (tokens[j].tag == '_t' && tokens[j].text.match(rIsWhitespace) === null);
291
351
  if (!isAllWhitespace) {
292
352
  return false;
293
353
  }
@@ -301,10 +361,10 @@ var Hogan = {};
301
361
 
302
362
  if (haveSeenTag && lineIsWhitespace()) {
303
363
  for (var j = lineStart, next; j < tokens.length; j++) {
304
- if (!tokens[j].tag) {
364
+ if (tokens[j].text) {
305
365
  if ((next = tokens[j+1]) && next.tag == '>') {
306
366
  // set indent to token value
307
- next.indent = tokens[j].toString()
367
+ next.indent = tokens[j].text.toString()
308
368
  }
309
369
  tokens.splice(j, 1);
310
370
  }
@@ -351,7 +411,7 @@ var Hogan = {};
351
411
  }
352
412
  } else if (state == IN_TAG_TYPE) {
353
413
  i += otag.length - 1;
354
- tag = tagTypes[text.charAt(i + 1)];
414
+ tag = Hogan.tags[text.charAt(i + 1)];
355
415
  tagType = tag ? text.charAt(i + 1) : '_v';
356
416
  if (tagType == '=') {
357
417
  i = changeDelimiters(text, i);
@@ -366,7 +426,7 @@ var Hogan = {};
366
426
  } else {
367
427
  if (tagChange(ctag, text, i)) {
368
428
  tokens.push({tag: tagType, n: trim(buf), otag: otag, ctag: ctag,
369
- i: (tagType == '/') ? seenTag - ctag.length : i + otag.length});
429
+ i: (tagType == '/') ? seenTag - otag.length : i + ctag.length});
370
430
  buf = '';
371
431
  i += ctag.length - 1;
372
432
  state = IN_TEXT;
@@ -416,17 +476,27 @@ var Hogan = {};
416
476
  return true;
417
477
  }
418
478
 
479
+ // the tags allowed inside super templates
480
+ var allowedInSuper = {'_t': true, '\n': true, '$': true, '/': true};
481
+
419
482
  function buildTree(tokens, kind, stack, customTags) {
420
483
  var instructions = [],
421
484
  opener = null,
485
+ tail = null,
422
486
  token = null;
423
487
 
488
+ tail = stack[stack.length - 1];
489
+
424
490
  while (tokens.length > 0) {
425
491
  token = tokens.shift();
426
- if (token.tag == '#' || token.tag == '^' || isOpener(token, customTags)) {
492
+
493
+ if (tail && tail.tag == '<' && !(token.tag in allowedInSuper)) {
494
+ throw new Error('Illegal content in < super tag.');
495
+ }
496
+
497
+ if (Hogan.tags[token.tag] <= Hogan.tags['$'] || isOpener(token, customTags)) {
427
498
  stack.push(token);
428
499
  token.nodes = buildTree(tokens, token.tag, stack, customTags);
429
- instructions.push(token);
430
500
  } else if (token.tag == '/') {
431
501
  if (stack.length === 0) {
432
502
  throw new Error('Closing tag without opener: /' + token.n);
@@ -437,9 +507,11 @@ var Hogan = {};
437
507
  }
438
508
  opener.end = token.i;
439
509
  return instructions;
440
- } else {
441
- instructions.push(token);
510
+ } else if (token.tag == '\n') {
511
+ token.last = (tokens.length == 0) || (tokens[0].tag == '\n');
442
512
  }
513
+
514
+ instructions.push(token);
443
515
  }
444
516
 
445
517
  if (stack.length > 0) {
@@ -466,16 +538,60 @@ var Hogan = {};
466
538
  }
467
539
  }
468
540
 
469
- function writeCode(tree) {
470
- return 'var _=this;_.b(i=i||"");' + walk(tree) + 'return _.fl();';
541
+ function stringifySubstitutions(obj) {
542
+ var items = [];
543
+ for (var key in obj) {
544
+ items.push('"' + esc(key) + '": function(c,p,t,i) {' + obj[key] + '}');
545
+ }
546
+ return "{ " + items.join(",") + " }";
547
+ }
548
+
549
+ function stringifyPartials(codeObj) {
550
+ var partials = [];
551
+ for (var key in codeObj.partials) {
552
+ partials.push('"' + esc(key) + '":{name:"' + esc(codeObj.partials[key].name) + '", ' + stringifyPartials(codeObj.partials[key]) + "}");
553
+ }
554
+ return "partials: {" + partials.join(",") + "}, subs: " + stringifySubstitutions(codeObj.subs);
555
+ }
556
+
557
+ Hogan.stringify = function(codeObj, text, options) {
558
+ return "{code: function (c,p,i) { " + Hogan.wrapMain(codeObj.code) + " }," + stringifyPartials(codeObj) + "}";
471
559
  }
472
560
 
473
- Hogan.generate = function (code, text, options) {
561
+ var serialNo = 0;
562
+ Hogan.generate = function(tree, text, options) {
563
+ serialNo = 0;
564
+ var context = { code: '', subs: {}, partials: {} };
565
+ Hogan.walk(tree, context);
566
+
474
567
  if (options.asString) {
475
- return 'function(c,p,i){' + code + ';}';
568
+ return this.stringify(context, text, options);
476
569
  }
477
570
 
478
- return new Hogan.Template(new Function('c', 'p', 'i', code), text, Hogan, options);
571
+ return this.makeTemplate(context, text, options);
572
+ }
573
+
574
+ Hogan.wrapMain = function(code) {
575
+ return 'var t=this;t.b(i=i||"");' + code + 'return t.fl();';
576
+ }
577
+
578
+ Hogan.template = Hogan.Template;
579
+
580
+ Hogan.makeTemplate = function(codeObj, text, options) {
581
+ var template = this.makePartials(codeObj);
582
+ template.code = new Function('c', 'p', 'i', this.wrapMain(codeObj.code));
583
+ return new this.template(template, text, this, options);
584
+ }
585
+
586
+ Hogan.makePartials = function(codeObj) {
587
+ var key, template = {subs: {}, partials: codeObj.partials, name: codeObj.name};
588
+ for (key in template.partials) {
589
+ template.partials[key] = this.makePartials(template.partials[key]);
590
+ }
591
+ for (key in codeObj.subs) {
592
+ template.subs[key] = new Function('c', 'p', 't', 'i', codeObj.subs[key]);
593
+ }
594
+ return template;
479
595
  }
480
596
 
481
597
  function esc(s) {
@@ -489,60 +605,79 @@ var Hogan = {};
489
605
  return (~s.indexOf('.')) ? 'd' : 'f';
490
606
  }
491
607
 
492
- function walk(tree) {
493
- var code = '';
494
- for (var i = 0, l = tree.length; i < l; i++) {
495
- var tag = tree[i].tag;
496
- if (tag == '#') {
497
- code += section(tree[i].nodes, tree[i].n, chooseMethod(tree[i].n),
498
- tree[i].i, tree[i].end, tree[i].otag + " " + tree[i].ctag);
499
- } else if (tag == '^') {
500
- code += invertedSection(tree[i].nodes, tree[i].n,
501
- chooseMethod(tree[i].n));
502
- } else if (tag == '<' || tag == '>') {
503
- code += partial(tree[i]);
504
- } else if (tag == '{' || tag == '&') {
505
- code += tripleStache(tree[i].n, chooseMethod(tree[i].n));
506
- } else if (tag == '\n') {
507
- code += text('"\\n"' + (tree.length-1 == i ? '' : ' + i'));
508
- } else if (tag == '_v') {
509
- code += variable(tree[i].n, chooseMethod(tree[i].n));
510
- } else if (tag === undefined) {
511
- code += text('"' + esc(tree[i]) + '"');
512
- }
513
- }
514
- return code;
608
+ function createPartial(node, context) {
609
+ var prefix = "<" + (context.prefix || "");
610
+ var sym = prefix + node.n + serialNo++;
611
+ context.partials[sym] = {name: node.n, partials: {}};
612
+ context.code += 't.b(t.rp("' + esc(sym) + '",c,p,"' + (node.indent || '') + '"));';
613
+ return sym;
515
614
  }
516
615
 
517
- function section(nodes, id, method, start, end, tags) {
518
- return 'if(_.s(_.' + method + '("' + esc(id) + '",c,p,1),' +
519
- 'c,p,0,' + start + ',' + end + ',"' + tags + '")){' +
520
- '_.rs(c,p,' +
521
- 'function(c,p,_){' +
522
- walk(nodes) +
523
- '});c.pop();}';
524
- }
616
+ Hogan.codegen = {
617
+ '#': function(node, context) {
618
+ context.code += 'if(t.s(t.' + chooseMethod(node.n) + '("' + esc(node.n) + '",c,p,1),' +
619
+ 'c,p,0,' + node.i + ',' + node.end + ',"' + node.otag + " " + node.ctag + '")){' +
620
+ 't.rs(c,p,' + 'function(c,p,t){';
621
+ Hogan.walk(node.nodes, context);
622
+ context.code += '});c.pop();}';
623
+ },
525
624
 
526
- function invertedSection(nodes, id, method) {
527
- return 'if(!_.s(_.' + method + '("' + esc(id) + '",c,p,1),c,p,1,0,0,"")){' +
528
- walk(nodes) +
529
- '};';
530
- }
625
+ '^': function(node, context) {
626
+ context.code += 'if(!t.s(t.' + chooseMethod(node.n) + '("' + esc(node.n) + '",c,p,1),c,p,1,0,0,"")){';
627
+ Hogan.walk(node.nodes, context);
628
+ context.code += '};';
629
+ },
630
+
631
+ '>': createPartial,
632
+ '<': function(node, context) {
633
+ var ctx = {partials: {}, code: '', subs: {}, inPartial: true};
634
+ Hogan.walk(node.nodes, ctx);
635
+ var template = context.partials[createPartial(node, context)];
636
+ template.subs = ctx.subs;
637
+ template.partials = ctx.partials;
638
+ },
639
+
640
+ '$': function(node, context) {
641
+ var ctx = {subs: {}, code: '', partials: context.partials, prefix: node.n};
642
+ Hogan.walk(node.nodes, ctx);
643
+ context.subs[node.n] = ctx.code;
644
+ if (!context.inPartial) {
645
+ context.code += 't.sub("' + esc(node.n) + '",c,p,i);';
646
+ }
647
+ },
648
+
649
+ '\n': function(node, context) {
650
+ context.code += write('"\\n"' + (node.last ? '' : ' + i'));
651
+ },
652
+
653
+ '_v': function(node, context) {
654
+ context.code += 't.b(t.v(t.' + chooseMethod(node.n) + '("' + esc(node.n) + '",c,p,0)));';
655
+ },
656
+
657
+ '_t': function(node, context) {
658
+ context.code += write('"' + esc(node.text) + '"');
659
+ },
660
+
661
+ '{': tripleStache,
531
662
 
532
- function partial(tok) {
533
- return '_.b(_.rp("' + esc(tok.n) + '",c,p,"' + (tok.indent || '') + '"));';
663
+ '&': tripleStache
534
664
  }
535
665
 
536
- function tripleStache(id, method) {
537
- return '_.b(_.t(_.' + method + '("' + esc(id) + '",c,p,0)));';
666
+ function tripleStache(node, context) {
667
+ context.code += 't.b(t.t(t.' + chooseMethod(node.n) + '("' + esc(node.n) + '",c,p,0)));';
538
668
  }
539
669
 
540
- function variable(id, method) {
541
- return '_.b(_.v(_.' + method + '("' + esc(id) + '",c,p,0)));';
670
+ function write(s) {
671
+ return 't.b(' + s + ');';
542
672
  }
543
673
 
544
- function text(id) {
545
- return '_.b(' + id + ');';
674
+ Hogan.walk = function (nodelist, context) {
675
+ var func;
676
+ for (var i = 0, l = nodelist.length; i < l; i++) {
677
+ func = Hogan.codegen[nodelist[i].tag];
678
+ func && func(nodelist[i], context);
679
+ }
680
+ return context;
546
681
  }
547
682
 
548
683
  Hogan.parse = function(tokens, text, options) {
@@ -552,30 +687,21 @@ var Hogan = {};
552
687
 
553
688
  Hogan.cache = {};
554
689
 
690
+ Hogan.cacheKey = function(text, options) {
691
+ return [text, !!options.asString, !!options.disableLambda].join('||');
692
+ },
693
+
555
694
  Hogan.compile = function(text, options) {
556
- // options
557
- //
558
- // asString: false (default)
559
- //
560
- // sectionTags: [{o: '_foo', c: 'foo'}]
561
- // An array of object with o and c fields that indicate names for custom
562
- // section tags. The example above allows parsing of {{_foo}}{{/foo}}.
563
- //
564
- // delimiters: A string that overrides the default delimiters.
565
- // Example: "<% %>"
566
- //
567
695
  options = options || {};
696
+ var key = Hogan.cacheKey(text, options);
697
+ var template = this.cache[key];
568
698
 
569
- var key = text + '||' + !!options.asString;
570
-
571
- var t = this.cache[key];
572
-
573
- if (t) {
574
- return t;
699
+ if (template) {
700
+ return template;
575
701
  }
576
702
 
577
- t = this.generate(writeCode(this.parse(this.scan(text, options.delimiters), text, options)), text, options);
578
- return this.cache[key] = t;
703
+ template = this.generate(this.parse(this.scan(text, options.delimiters), text, options), text, options);
704
+ return this.cache[key] = template;
579
705
  };
580
706
  })(typeof exports !== 'undefined' ? exports : Hogan);
581
707
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hogan_assets
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.0
4
+ version: 1.2.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-05-28 00:00:00.000000000 Z
12
+ date: 2012-05-31 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: execjs