guard-hogan 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,18 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ vendor/ruby
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in guard-hogan.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Andrew Smith
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,29 @@
1
+ # Guard::Hogan
2
+
3
+ TODO: Write a gem description
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'guard-hogan'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install guard-hogan
18
+
19
+ ## Usage
20
+
21
+ TODO: Write usage instructions here
22
+
23
+ ## Contributing
24
+
25
+ 1. Fork it
26
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
27
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
28
+ 4. Push to the branch (`git push origin my-new-feature`)
29
+ 5. Create new Pull Request
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
@@ -0,0 +1,11 @@
1
+ guard-hogan
2
+ ===========
3
+
4
+ Let Guard compile your Hogan.js templates for you!
5
+
6
+
7
+ ``` ruby
8
+ gem 'guard-hogan'
9
+ ```
10
+
11
+
@@ -0,0 +1,20 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/guard/hogan/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["Andrew Smith"]
6
+ gem.email = ["fullsailor@me.com"]
7
+ gem.description = %q{Compiles your Hogan mustache templates with Guard}
8
+ gem.summary = %q{Compiles your Hogan mustache templates with Guard}
9
+ gem.homepage = "http://github.com/fullsailor/guard-hogan"
10
+
11
+ gem.files = `git ls-files`.split($\)
12
+ gem.executables = [] #gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
13
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
14
+ gem.name = "guard-hogan"
15
+ gem.require_paths = ["lib"]
16
+ gem.version = Guard::HoganVersion::VERSION
17
+
18
+ gem.add_runtime_dependency "execjs", "~> 1.3.0"
19
+ gem.add_runtime_dependency "guard", "~> 1.0.1"
20
+ end
@@ -0,0 +1,30 @@
1
+ require 'guard'
2
+ require 'guard/guard'
3
+
4
+ module ::Guard
5
+ class Hogan < ::Guard::Guard
6
+
7
+ autoload :Runner, 'guard/hogan/runner'
8
+ autoload :Compiler, 'guard/hogan/compiler'
9
+
10
+ def initialize(watchers=[], options={})
11
+ if options[:input]
12
+ watchers << ::Guard::Watcher.new(/^#{ options[:input] }\/(.+)\.mustache$/)
13
+ end
14
+ @runner = Runner.new(options)
15
+ super(watchers, options)
16
+ end
17
+
18
+ def start
19
+ run_all
20
+ end
21
+
22
+ def run_all
23
+ @runner.run(Watcher.match_files(self, Dir.glob('**{,/*/**}/*.mustache')))
24
+ end
25
+
26
+ def run_on_change(paths)
27
+ run_all
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,36 @@
1
+ # Based on https://github.com/leshill/hogan_assets
2
+ require 'execjs'
3
+ require 'pathname'
4
+
5
+ module Guard
6
+ class Hogan < ::Guard::Guard
7
+ class Compiler
8
+ class BareString < ::String
9
+ def to_json(*)
10
+ self
11
+ end
12
+ end
13
+ class << self
14
+ def compile(source)
15
+ template = context.eval("Hogan.compile(#{source.inspect}, {asString: true})")
16
+ BareString.new(template)
17
+ end
18
+
19
+ private
20
+
21
+ def context
22
+ @context ||= ExecJS.compile(hogan)
23
+ end
24
+
25
+ def hogan
26
+ @hogan ||= path.read
27
+ end
28
+
29
+ def path
30
+ @path ||= Pathname(__FILE__).dirname.join('..','..','..','vendor','hogan.js')
31
+ end
32
+
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,43 @@
1
+ require 'json'
2
+ module Guard
3
+ class Hogan < ::Guard::Guard
4
+ class Runner
5
+
6
+ def initialize(options)
7
+ @options = options
8
+ end
9
+
10
+ def run(paths=[])
11
+ templates = paths.collect { |path| compile(path) }
12
+ write_templates_file(templates, paths)
13
+ end
14
+
15
+ private
16
+
17
+ def write_templates_file(templates, paths)
18
+ names = paths.collect { |path| File.basename(path, '.mustache') }
19
+ templates = Hash[names.zip(templates)]
20
+ filename = File.expand_path(@options[:output])
21
+ FileUtils.mkdir_p(File.dirname(filename))
22
+ File.open(File.expand_path(filename), 'w') do |f|
23
+ f.write(<<JAVASCRIPT
24
+ (function(root, Hogan){
25
+ root.hoganTemplates = #{templates.to_json}
26
+ for (var key in root.hoganTemplates) {
27
+ root.hoganTemplates[key] =
28
+ new Hogan.Template(root.hoganTemplates[key])
29
+ }
30
+ })(window,window.Hogan)
31
+ JAVASCRIPT
32
+ )
33
+ end
34
+
35
+ filename
36
+ end
37
+
38
+ def compile(file)
39
+ Compiler.compile(File.read(file))
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,2 @@
1
+ guard :hogan, input: 'assets/templates/src', output: 'assets/templates/compiled/templates.js'
2
+
@@ -0,0 +1,5 @@
1
+ module Guard
2
+ module HoganVersion
3
+ VERSION = "0.0.1"
4
+ end
5
+ end
@@ -0,0 +1,576 @@
1
+ /*
2
+ * Copyright 2011 Twitter, Inc.
3
+ * Licensed under the Apache License, Version 2.0 (the "License");
4
+ * you may not use this file except in compliance with the License.
5
+ * You may obtain a copy of the License at
6
+ *
7
+ * http://www.apache.org/licenses/LICENSE-2.0
8
+ *
9
+ * Unless required by applicable law or agreed to in writing, software
10
+ * distributed under the License is distributed on an "AS IS" BASIS,
11
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ * See the License for the specific language governing permissions and
13
+ * limitations under the License.
14
+ */
15
+
16
+
17
+
18
+ var Hogan = {};
19
+
20
+ (function (Hogan, useArrayBuffer) {
21
+ Hogan.Template = function (renderFunc, text, compiler, options) {
22
+ this.r = renderFunc || this.r;
23
+ this.c = compiler;
24
+ this.options = options;
25
+ this.text = text || '';
26
+ this.buf = (useArrayBuffer) ? [] : '';
27
+ }
28
+
29
+ Hogan.Template.prototype = {
30
+ // render: replaced by generated code.
31
+ r: function (context, partials, indent) { return ''; },
32
+
33
+ // variable escaping
34
+ v: hoganEscape,
35
+
36
+ // triple stache
37
+ t: coerceToString,
38
+
39
+ render: function render(context, partials, indent) {
40
+ return this.ri([context], partials || {}, indent);
41
+ },
42
+
43
+ // render internal -- a hook for overrides that catches partials too
44
+ ri: function (context, partials, indent) {
45
+ return this.r(context, partials, indent);
46
+ },
47
+
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
+
52
+ if (!partial) {
53
+ return '';
54
+ }
55
+
56
+ if (this.c && typeof partial == 'string') {
57
+ partial = this.c.compile(partial, this.options);
58
+ }
59
+
60
+ return partial.ri(context, partials, indent);
61
+ },
62
+
63
+ // render a section
64
+ rs: function(context, partials, section) {
65
+ var tail = context[context.length - 1];
66
+
67
+ if (!isArray(tail)) {
68
+ section(context, partials, this);
69
+ return;
70
+ }
71
+
72
+ for (var i = 0; i < tail.length; i++) {
73
+ context.push(tail[i]);
74
+ section(context, partials, this);
75
+ context.pop();
76
+ }
77
+ },
78
+
79
+ // maybe start a section
80
+ s: function(val, ctx, partials, inverted, start, end, tags) {
81
+ var pass;
82
+
83
+ if (isArray(val) && val.length === 0) {
84
+ return false;
85
+ }
86
+
87
+ if (typeof val == 'function') {
88
+ val = this.ls(val, ctx, partials, inverted, start, end, tags);
89
+ }
90
+
91
+ pass = (val === '') || !!val;
92
+
93
+ if (!inverted && pass && ctx) {
94
+ ctx.push((typeof val == 'object') ? val : ctx[ctx.length - 1]);
95
+ }
96
+
97
+ return pass;
98
+ },
99
+
100
+ // find values with dotted names
101
+ d: function(key, ctx, partials, returnFound) {
102
+ var names = key.split('.'),
103
+ val = this.f(names[0], ctx, partials, returnFound),
104
+ cx = null;
105
+
106
+ if (key === '.' && isArray(ctx[ctx.length - 2])) {
107
+ return ctx[ctx.length - 1];
108
+ }
109
+
110
+ for (var i = 1; i < names.length; i++) {
111
+ if (val && typeof val == 'object' && names[i] in val) {
112
+ cx = val;
113
+ val = val[names[i]];
114
+ } else {
115
+ val = '';
116
+ }
117
+ }
118
+
119
+ if (returnFound && !val) {
120
+ return false;
121
+ }
122
+
123
+ if (!returnFound && typeof val == 'function') {
124
+ ctx.push(cx);
125
+ val = this.lv(val, ctx, partials);
126
+ ctx.pop();
127
+ }
128
+
129
+ return val;
130
+ },
131
+
132
+ // find values with normal names
133
+ f: function(key, ctx, partials, returnFound) {
134
+ var val = false,
135
+ v = null,
136
+ found = false;
137
+
138
+ for (var i = ctx.length - 1; i >= 0; i--) {
139
+ v = ctx[i];
140
+ if (v && typeof v == 'object' && key in v) {
141
+ val = v[key];
142
+ found = true;
143
+ break;
144
+ }
145
+ }
146
+
147
+ if (!found) {
148
+ return (returnFound) ? false : "";
149
+ }
150
+
151
+ if (!returnFound && typeof val == 'function') {
152
+ val = this.lv(val, ctx, partials);
153
+ }
154
+
155
+ return val;
156
+ },
157
+
158
+ // 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 text = val.call(cx, text);
164
+ text = (text == null) ? String(text) : text.toString();
165
+ this.b(compiler.compile(text, options).render(cx, partials));
166
+ return false;
167
+ },
168
+
169
+ // template result buffering
170
+ b: (useArrayBuffer) ? function(s) { this.buf.push(s); } :
171
+ function(s) { this.buf += s; },
172
+ fl: (useArrayBuffer) ? function() { var r = this.buf.join(''); this.buf = []; return r; } :
173
+ function() { var r = this.buf; this.buf = ''; return r; },
174
+
175
+ // lambda replace section
176
+ ls: function(val, ctx, partials, inverted, start, end, tags) {
177
+ var cx = ctx[ctx.length - 1],
178
+ t = null;
179
+
180
+ if (!inverted && this.c && val.length > 0) {
181
+ return this.ho(val, cx, partials, this.text.substring(start, end), tags);
182
+ }
183
+
184
+ t = val.call(cx);
185
+
186
+ if (typeof t == 'function') {
187
+ if (inverted) {
188
+ return true;
189
+ } else if (this.c) {
190
+ return this.ho(t, cx, partials, this.text.substring(start, end), tags);
191
+ }
192
+ }
193
+
194
+ return t;
195
+ },
196
+
197
+ // lambda replace variable
198
+ lv: function(val, ctx, partials) {
199
+ var cx = ctx[ctx.length - 1];
200
+ var result = val.call(cx);
201
+
202
+ if (typeof result == 'function') {
203
+ result = coerceToString(result.call(cx));
204
+ if (this.c && ~result.indexOf("{\u007B")) {
205
+ return this.c.compile(result, this.options).render(cx, partials);
206
+ }
207
+ }
208
+
209
+ return coerceToString(result);
210
+ }
211
+
212
+ };
213
+
214
+ var rAmp = /&/g,
215
+ rLt = /</g,
216
+ rGt = />/g,
217
+ rApos =/\'/g,
218
+ rQuot = /\"/g,
219
+ hChars =/[&<>\"\']/;
220
+
221
+
222
+ function coerceToString(val) {
223
+ return String((val === null || val === undefined) ? '' : val);
224
+ }
225
+
226
+ function hoganEscape(str) {
227
+ str = coerceToString(str);
228
+ return hChars.test(str) ?
229
+ str
230
+ .replace(rAmp,'&amp;')
231
+ .replace(rLt,'&lt;')
232
+ .replace(rGt,'&gt;')
233
+ .replace(rApos,'&#39;')
234
+ .replace(rQuot, '&quot;') :
235
+ str;
236
+ }
237
+
238
+ var isArray = Array.isArray || function(a) {
239
+ return Object.prototype.toString.call(a) === '[object Array]';
240
+ };
241
+
242
+ })(typeof exports !== 'undefined' ? exports : Hogan);
243
+
244
+
245
+
246
+
247
+ (function (Hogan) {
248
+ // Setup regex assignments
249
+ // remove whitespace according to Mustache spec
250
+ var rIsWhitespace = /\S/,
251
+ rQuot = /\"/g,
252
+ rNewline = /\n/g,
253
+ rCr = /\r/g,
254
+ rSlash = /\\/g,
255
+ tagTypes = {
256
+ '#': 1, '^': 2, '/': 3, '!': 4, '>': 5,
257
+ '<': 6, '=': 7, '_v': 8, '{': 9, '&': 10
258
+ };
259
+
260
+ Hogan.scan = function scan(text, delimiters) {
261
+ var len = text.length,
262
+ IN_TEXT = 0,
263
+ IN_TAG_TYPE = 1,
264
+ IN_TAG = 2,
265
+ state = IN_TEXT,
266
+ tagType = null,
267
+ tag = null,
268
+ buf = '',
269
+ tokens = [],
270
+ seenTag = false,
271
+ i = 0,
272
+ lineStart = 0,
273
+ otag = '{{',
274
+ ctag = '}}';
275
+
276
+ function addBuf() {
277
+ if (buf.length > 0) {
278
+ tokens.push(new String(buf));
279
+ buf = '';
280
+ }
281
+ }
282
+
283
+ function lineIsWhitespace() {
284
+ var isAllWhitespace = true;
285
+ for (var j = lineStart; j < tokens.length; j++) {
286
+ isAllWhitespace =
287
+ (tokens[j].tag && tagTypes[tokens[j].tag] < tagTypes['_v']) ||
288
+ (!tokens[j].tag && tokens[j].match(rIsWhitespace) === null);
289
+ if (!isAllWhitespace) {
290
+ return false;
291
+ }
292
+ }
293
+
294
+ return isAllWhitespace;
295
+ }
296
+
297
+ function filterLine(haveSeenTag, noNewLine) {
298
+ addBuf();
299
+
300
+ if (haveSeenTag && lineIsWhitespace()) {
301
+ for (var j = lineStart, next; j < tokens.length; j++) {
302
+ if (!tokens[j].tag) {
303
+ if ((next = tokens[j+1]) && next.tag == '>') {
304
+ // set indent to token value
305
+ next.indent = tokens[j].toString()
306
+ }
307
+ tokens.splice(j, 1);
308
+ }
309
+ }
310
+ } else if (!noNewLine) {
311
+ tokens.push({tag:'\n'});
312
+ }
313
+
314
+ seenTag = false;
315
+ lineStart = tokens.length;
316
+ }
317
+
318
+ function changeDelimiters(text, index) {
319
+ var close = '=' + ctag,
320
+ closeIndex = text.indexOf(close, index),
321
+ delimiters = trim(
322
+ text.substring(text.indexOf('=', index) + 1, closeIndex)
323
+ ).split(' ');
324
+
325
+ otag = delimiters[0];
326
+ ctag = delimiters[1];
327
+
328
+ return closeIndex + close.length - 1;
329
+ }
330
+
331
+ if (delimiters) {
332
+ delimiters = delimiters.split(' ');
333
+ otag = delimiters[0];
334
+ ctag = delimiters[1];
335
+ }
336
+
337
+ for (i = 0; i < len; i++) {
338
+ if (state == IN_TEXT) {
339
+ if (tagChange(otag, text, i)) {
340
+ --i;
341
+ addBuf();
342
+ state = IN_TAG_TYPE;
343
+ } else {
344
+ if (text.charAt(i) == '\n') {
345
+ filterLine(seenTag);
346
+ } else {
347
+ buf += text.charAt(i);
348
+ }
349
+ }
350
+ } else if (state == IN_TAG_TYPE) {
351
+ i += otag.length - 1;
352
+ tag = tagTypes[text.charAt(i + 1)];
353
+ tagType = tag ? text.charAt(i + 1) : '_v';
354
+ if (tagType == '=') {
355
+ i = changeDelimiters(text, i);
356
+ state = IN_TEXT;
357
+ } else {
358
+ if (tag) {
359
+ i++;
360
+ }
361
+ state = IN_TAG;
362
+ }
363
+ seenTag = i;
364
+ } else {
365
+ if (tagChange(ctag, text, i)) {
366
+ tokens.push({tag: tagType, n: trim(buf), otag: otag, ctag: ctag,
367
+ i: (tagType == '/') ? seenTag - ctag.length : i + otag.length});
368
+ buf = '';
369
+ i += ctag.length - 1;
370
+ state = IN_TEXT;
371
+ if (tagType == '{') {
372
+ if (ctag == '}}') {
373
+ i++;
374
+ } else {
375
+ cleanTripleStache(tokens[tokens.length - 1]);
376
+ }
377
+ }
378
+ } else {
379
+ buf += text.charAt(i);
380
+ }
381
+ }
382
+ }
383
+
384
+ filterLine(seenTag, true);
385
+
386
+ return tokens;
387
+ }
388
+
389
+ function cleanTripleStache(token) {
390
+ if (token.n.substr(token.n.length - 1) === '}') {
391
+ token.n = token.n.substring(0, token.n.length - 1);
392
+ }
393
+ }
394
+
395
+ function trim(s) {
396
+ if (s.trim) {
397
+ return s.trim();
398
+ }
399
+
400
+ return s.replace(/^\s*|\s*$/g, '');
401
+ }
402
+
403
+ function tagChange(tag, text, index) {
404
+ if (text.charAt(index) != tag.charAt(0)) {
405
+ return false;
406
+ }
407
+
408
+ for (var i = 1, l = tag.length; i < l; i++) {
409
+ if (text.charAt(index + i) != tag.charAt(i)) {
410
+ return false;
411
+ }
412
+ }
413
+
414
+ return true;
415
+ }
416
+
417
+ function buildTree(tokens, kind, stack, customTags) {
418
+ var instructions = [],
419
+ opener = null,
420
+ token = null;
421
+
422
+ while (tokens.length > 0) {
423
+ token = tokens.shift();
424
+ if (token.tag == '#' || token.tag == '^' || isOpener(token, customTags)) {
425
+ stack.push(token);
426
+ token.nodes = buildTree(tokens, token.tag, stack, customTags);
427
+ instructions.push(token);
428
+ } else if (token.tag == '/') {
429
+ if (stack.length === 0) {
430
+ throw new Error('Closing tag without opener: /' + token.n);
431
+ }
432
+ opener = stack.pop();
433
+ if (token.n != opener.n && !isCloser(token.n, opener.n, customTags)) {
434
+ throw new Error('Nesting error: ' + opener.n + ' vs. ' + token.n);
435
+ }
436
+ opener.end = token.i;
437
+ return instructions;
438
+ } else {
439
+ instructions.push(token);
440
+ }
441
+ }
442
+
443
+ if (stack.length > 0) {
444
+ throw new Error('missing closing tag: ' + stack.pop().n);
445
+ }
446
+
447
+ return instructions;
448
+ }
449
+
450
+ function isOpener(token, tags) {
451
+ for (var i = 0, l = tags.length; i < l; i++) {
452
+ if (tags[i].o == token.n) {
453
+ token.tag = '#';
454
+ return true;
455
+ }
456
+ }
457
+ }
458
+
459
+ function isCloser(close, open, tags) {
460
+ for (var i = 0, l = tags.length; i < l; i++) {
461
+ if (tags[i].c == close && tags[i].o == open) {
462
+ return true;
463
+ }
464
+ }
465
+ }
466
+
467
+ Hogan.generate = function (tree, text, options) {
468
+ var code = 'var _=this;_.b(i=i||"");' + walk(tree) + 'return _.fl();';
469
+ if (options.asString) {
470
+ return 'function(c,p,i){' + code + ';}';
471
+ }
472
+
473
+ return new Hogan.Template(new Function('c', 'p', 'i', code), text, Hogan, options);
474
+ }
475
+
476
+ function esc(s) {
477
+ return s.replace(rSlash, '\\\\')
478
+ .replace(rQuot, '\\\"')
479
+ .replace(rNewline, '\\n')
480
+ .replace(rCr, '\\r');
481
+ }
482
+
483
+ function chooseMethod(s) {
484
+ return (~s.indexOf('.')) ? 'd' : 'f';
485
+ }
486
+
487
+ function walk(tree) {
488
+ var code = '';
489
+ for (var i = 0, l = tree.length; i < l; i++) {
490
+ var tag = tree[i].tag;
491
+ if (tag == '#') {
492
+ code += section(tree[i].nodes, tree[i].n, chooseMethod(tree[i].n),
493
+ tree[i].i, tree[i].end, tree[i].otag + " " + tree[i].ctag);
494
+ } else if (tag == '^') {
495
+ code += invertedSection(tree[i].nodes, tree[i].n,
496
+ chooseMethod(tree[i].n));
497
+ } else if (tag == '<' || tag == '>') {
498
+ code += partial(tree[i]);
499
+ } else if (tag == '{' || tag == '&') {
500
+ code += tripleStache(tree[i].n, chooseMethod(tree[i].n));
501
+ } else if (tag == '\n') {
502
+ code += text('"\\n"' + (tree.length-1 == i ? '' : ' + i'));
503
+ } else if (tag == '_v') {
504
+ code += variable(tree[i].n, chooseMethod(tree[i].n));
505
+ } else if (tag === undefined) {
506
+ code += text('"' + esc(tree[i]) + '"');
507
+ }
508
+ }
509
+ return code;
510
+ }
511
+
512
+ function section(nodes, id, method, start, end, tags) {
513
+ return 'if(_.s(_.' + method + '("' + esc(id) + '",c,p,1),' +
514
+ 'c,p,0,' + start + ',' + end + ',"' + tags + '")){' +
515
+ '_.rs(c,p,' +
516
+ 'function(c,p,_){' +
517
+ walk(nodes) +
518
+ '});c.pop();}';
519
+ }
520
+
521
+ function invertedSection(nodes, id, method) {
522
+ return 'if(!_.s(_.' + method + '("' + esc(id) + '",c,p,1),c,p,1,0,0,"")){' +
523
+ walk(nodes) +
524
+ '};';
525
+ }
526
+
527
+ function partial(tok) {
528
+ return '_.b(_.rp("' + esc(tok.n) + '",c,p,"' + (tok.indent || '') + '"));';
529
+ }
530
+
531
+ function tripleStache(id, method) {
532
+ return '_.b(_.t(_.' + method + '("' + esc(id) + '",c,p,0)));';
533
+ }
534
+
535
+ function variable(id, method) {
536
+ return '_.b(_.v(_.' + method + '("' + esc(id) + '",c,p,0)));';
537
+ }
538
+
539
+ function text(id) {
540
+ return '_.b(' + id + ');';
541
+ }
542
+
543
+ Hogan.parse = function(tokens, text, options) {
544
+ options = options || {};
545
+ return buildTree(tokens, '', [], options.sectionTags || []);
546
+ },
547
+
548
+ Hogan.cache = {};
549
+
550
+ Hogan.compile = function(text, options) {
551
+ // options
552
+ //
553
+ // asString: false (default)
554
+ //
555
+ // sectionTags: [{o: '_foo', c: 'foo'}]
556
+ // An array of object with o and c fields that indicate names for custom
557
+ // section tags. The example above allows parsing of {{_foo}}{{/foo}}.
558
+ //
559
+ // delimiters: A string that overrides the default delimiters.
560
+ // Example: "<% %>"
561
+ //
562
+ options = options || {};
563
+
564
+ var key = text + '||' + !!options.asString;
565
+
566
+ var t = this.cache[key];
567
+
568
+ if (t) {
569
+ return t;
570
+ }
571
+
572
+ t = this.generate(this.parse(this.scan(text, options.delimiters), text, options), text, options);
573
+ return this.cache[key] = t;
574
+ };
575
+ })(typeof exports !== 'undefined' ? exports : Hogan);
576
+
metadata ADDED
@@ -0,0 +1,80 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: guard-hogan
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Andrew Smith
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-03-28 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: execjs
16
+ requirement: &70140008441440 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: 1.3.0
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *70140008441440
25
+ - !ruby/object:Gem::Dependency
26
+ name: guard
27
+ requirement: &70140008440740 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ~>
31
+ - !ruby/object:Gem::Version
32
+ version: 1.0.1
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: *70140008440740
36
+ description: Compiles your Hogan mustache templates with Guard
37
+ email:
38
+ - fullsailor@me.com
39
+ executables: []
40
+ extensions: []
41
+ extra_rdoc_files: []
42
+ files:
43
+ - .gitignore
44
+ - Gemfile
45
+ - LICENSE
46
+ - README.md
47
+ - Rakefile
48
+ - Readme.markdown
49
+ - guard-hogan.gemspec
50
+ - lib/guard/hogan.rb
51
+ - lib/guard/hogan/compiler.rb
52
+ - lib/guard/hogan/runner.rb
53
+ - lib/guard/hogan/templates/Guardfile
54
+ - lib/guard/hogan/version.rb
55
+ - vendor/hogan.js
56
+ homepage: http://github.com/fullsailor/guard-hogan
57
+ licenses: []
58
+ post_install_message:
59
+ rdoc_options: []
60
+ require_paths:
61
+ - lib
62
+ required_ruby_version: !ruby/object:Gem::Requirement
63
+ none: false
64
+ requirements:
65
+ - - ! '>='
66
+ - !ruby/object:Gem::Version
67
+ version: '0'
68
+ required_rubygems_version: !ruby/object:Gem::Requirement
69
+ none: false
70
+ requirements:
71
+ - - ! '>='
72
+ - !ruby/object:Gem::Version
73
+ version: '0'
74
+ requirements: []
75
+ rubyforge_project:
76
+ rubygems_version: 1.8.16
77
+ signing_key:
78
+ specification_version: 3
79
+ summary: Compiles your Hogan mustache templates with Guard
80
+ test_files: []