hogan_assets 1.1.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/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