smt_rails 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,18 @@
1
+ *.gem
2
+ *.rbc
3
+ .rvmrc
4
+ .bundle
5
+ .config
6
+ .yardoc
7
+ Gemfile.lock
8
+ InstalledFiles
9
+ _yardoc
10
+ coverage
11
+ doc/
12
+ lib/bundler/man
13
+ pkg
14
+ rdoc
15
+ spec/reports
16
+ test/tmp
17
+ test/version_tmp
18
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in smt_rails.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Alexey
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.
data/README.md ADDED
@@ -0,0 +1,49 @@
1
+ # SmtRails
2
+
3
+ Shared mustache templates for rails 3.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'smt_rails', :git => 'git://github.com/railsware/smt_rails.git'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ ## Usage
16
+
17
+ $ rails g smt_rails:install
18
+
19
+ Generator add into "application.js" requirements for mustache and "templates" folder in "app/views". Next you can create mustache templates in this folder or subfolders.
20
+
21
+ For example:
22
+
23
+ File: "app/views/templates/_test.mustache"
24
+
25
+ Hello {{msg}}!!!
26
+
27
+ In view you can render this template by this way:
28
+
29
+ <%= render "templates/test", :mustache => {msg: "Test"} %>
30
+
31
+ The same template you can render in JavaScript:
32
+
33
+ var content = SMT['templates/_test']({msg: "Test"});
34
+
35
+ ## Configuration
36
+
37
+ SmtRails.configure do |config|
38
+ config.template_extension = 'mustache' # change extension of mustache templates
39
+ config.action_view_key = 'mustache' # change name of key for rendering in ActionView mustache template
40
+ config.template_namespace = 'SMT' # change templates namespace in javascript
41
+ end
42
+
43
+ ## Contributing
44
+
45
+ 1. Fork it
46
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
47
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
48
+ 4. Push to the branch (`git push origin my-new-feature`)
49
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
@@ -0,0 +1,19 @@
1
+ module SmtRails
2
+ module Generators
3
+ module Helpers
4
+
5
+ def asset_path
6
+ "app/assets"
7
+ end
8
+
9
+ def js_path
10
+ "#{asset_path}/javascripts"
11
+ end
12
+
13
+ def views_path
14
+ "app/views"
15
+ end
16
+
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,40 @@
1
+ require 'generators/smt_rails/helpers'
2
+ require 'rails'
3
+
4
+ module SmtRails
5
+ module Generators
6
+ class InstallGenerator < Rails::Generators::Base
7
+ include SmtRails::Generators::Helpers
8
+
9
+ desc "Install into rails"
10
+
11
+ class_option :manifest, :type => :string, :aliases => "-m", :default => 'application.js',
12
+ :desc => "Javascript manifest file to modify (or create)"
13
+
14
+ class_option :template_dir, :type => :string, :aliases => "-t", :default => 'templates',
15
+ :desc => "Template dir for mustache templates"
16
+
17
+ def inject_mustache
18
+ manifest = options[:manifest]
19
+ template_dir = options[:template_dir]
20
+
21
+ create_file("#{js_path}/#{manifest}") unless File.exists?("#{js_path}/#{manifest}")
22
+
23
+ append_to_file "#{js_path}/#{manifest}" do
24
+ out = ""
25
+ out << "//= require mustache"
26
+ out << "\n"
27
+ out << "//= require_tree ../../views/#{template_dir}"
28
+ out << "\n"
29
+ out << "\n"
30
+ end
31
+ end
32
+
33
+ def create_dir
34
+ template_dir = options[:template_dir]
35
+ empty_directory "#{views_path}/#{template_dir}"
36
+ end
37
+
38
+ end
39
+ end
40
+ end
data/lib/smt_rails.rb ADDED
@@ -0,0 +1,18 @@
1
+ require "smt_rails/version"
2
+ require "smt_rails/config"
3
+
4
+ module SmtRails
5
+ extend Config
6
+
7
+ autoload(:Tilt, 'smt_rails/tilt')
8
+
9
+ if defined?(Rails)
10
+ require 'smt_rails/engine'
11
+ else
12
+ require 'sprockets'
13
+ Sprockets.register_engine ".#{SmtRails.template_extension}", Tilt
14
+ end
15
+ end
16
+
17
+ # init action view handler
18
+ require "smt_rails/mustache"
@@ -0,0 +1,31 @@
1
+ module SmtRails
2
+ # Change config options in an initializer:
3
+ #
4
+ # SmtRails.template_extension = 'mustache'
5
+ #
6
+ # Or in a block:
7
+ #
8
+ # SmtRails.configure do |config|
9
+ # config.template_extension = 'mustache'
10
+ # end
11
+
12
+ module Config
13
+ attr_accessor :template_base_path, :template_extension, :action_view_key, :template_namespace
14
+
15
+ def configure
16
+ yield self
17
+ end
18
+
19
+ def template_extension
20
+ @template_extension ||= 'mustache'
21
+ end
22
+
23
+ def action_view_key
24
+ @action_view_key ||= 'mustache'
25
+ end
26
+
27
+ def template_namespace
28
+ @template_namespace ||= 'SMT'
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,9 @@
1
+ module SmtRails
2
+ class Engine < ::Rails::Engine
3
+ initializer "sprockets.smt_rails", :after => "sprockets.environment", :group => :all do |app|
4
+ next unless app.assets
5
+ app.assets.register_engine(".#{SmtRails.template_extension}", Tilt)
6
+ app.config.assets.paths << Rails.root.join("app", "views")
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,18 @@
1
+ require "mustache"
2
+ require "active_support"
3
+
4
+ module SmtRails
5
+ module Mustache
6
+ def self.call(template)
7
+ if template.locals.include? SmtRails.action_view_key
8
+ "Mustache.render(#{template.source.inspect}, #{SmtRails.action_view_key}).html_safe"
9
+ else
10
+ "#{template.source.inspect}.html_safe"
11
+ end
12
+ end
13
+ end
14
+ end
15
+
16
+ ActiveSupport.on_load(:action_view) do
17
+ ActionView::Template.register_template_handler(::SmtRails.template_extension.to_sym, ::SmtRails::Mustache)
18
+ end
@@ -0,0 +1,24 @@
1
+ require 'tilt'
2
+
3
+ module SmtRails
4
+ class Tilt < Tilt::Template
5
+ def self.default_mime_type
6
+ 'application/javascript'
7
+ end
8
+
9
+ def prepare
10
+ @namespace = "this.#{SmtRails.template_namespace}"
11
+ end
12
+
13
+ attr_reader :namespace
14
+
15
+ def evaluate(scope, locals, &block)
16
+ <<-MustacheTemplate
17
+ (function() {
18
+ #{namespace} || (#{namespace} = {});
19
+ #{namespace}[#{scope.logical_path.inspect}] = function(object) { return Mustache.render(#{data.inspect}, object) };
20
+ }).call(this);
21
+ MustacheTemplate
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,3 @@
1
+ module SmtRails
2
+ VERSION = "0.1.1"
3
+ end
data/smt_rails.gemspec ADDED
@@ -0,0 +1,27 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/smt_rails/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["Alexey Vasiliev", "Alexander Chaplinsky"]
6
+ gem.email = ["contacts@railsware.com"]
7
+ gem.description = %q{Shared mustache templates for rails 3}
8
+ gem.summary = %q{Shared mustache templates for rails 3}
9
+ gem.homepage = "https://github.com/railsware/smt_rails"
10
+
11
+ gem.extra_rdoc_files = [ "LICENSE", "README.md" ]
12
+ gem.rdoc_options = ["--charset=UTF-8"]
13
+
14
+ #gem.add_development_dependency "jasmine", ">= 1.0.0"
15
+
16
+ gem.add_runtime_dependency "rails", ">= 3.1.0"
17
+ gem.add_runtime_dependency "tilt", ">= 1.3.3"
18
+ gem.add_runtime_dependency "sprockets", ">= 2.0.3"
19
+ gem.add_runtime_dependency "mustache", ">= 0.99.4"
20
+
21
+ gem.files = `git ls-files`.split($\)
22
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
23
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
24
+ gem.name = "smt_rails"
25
+ gem.require_paths = ["lib"]
26
+ gem.version = SmtRails::VERSION
27
+ end
@@ -0,0 +1,536 @@
1
+ /*!
2
+ * mustache.js - Logic-less {{mustache}} templates with JavaScript
3
+ * http://github.com/janl/mustache.js
4
+ */
5
+ var Mustache = (typeof module !== "undefined" && module.exports) || {};
6
+
7
+ (function (exports) {
8
+
9
+ exports.name = "mustache.js";
10
+ exports.version = "0.5.0-dev";
11
+ exports.tags = ["{{", "}}"];
12
+ exports.parse = parse;
13
+ exports.compile = compile;
14
+ exports.render = render;
15
+ exports.clearCache = clearCache;
16
+
17
+ // This is here for backwards compatibility with 0.4.x.
18
+ exports.to_html = function (template, view, partials, send) {
19
+ var result = render(template, view, partials);
20
+
21
+ if (typeof send === "function") {
22
+ send(result);
23
+ } else {
24
+ return result;
25
+ }
26
+ };
27
+
28
+ var _toString = Object.prototype.toString;
29
+ var _isArray = Array.isArray;
30
+ var _forEach = Array.prototype.forEach;
31
+ var _trim = String.prototype.trim;
32
+
33
+ var isArray;
34
+ if (_isArray) {
35
+ isArray = _isArray;
36
+ } else {
37
+ isArray = function (obj) {
38
+ return _toString.call(obj) === "[object Array]";
39
+ };
40
+ }
41
+
42
+ var forEach;
43
+ if (_forEach) {
44
+ forEach = function (obj, callback, scope) {
45
+ return _forEach.call(obj, callback, scope);
46
+ };
47
+ } else {
48
+ forEach = function (obj, callback, scope) {
49
+ for (var i = 0, len = obj.length; i < len; ++i) {
50
+ callback.call(scope, obj[i], i, obj);
51
+ }
52
+ };
53
+ }
54
+
55
+ var spaceRe = /^\s*$/;
56
+
57
+ function isWhitespace(string) {
58
+ return spaceRe.test(string);
59
+ }
60
+
61
+ var trim;
62
+ if (_trim) {
63
+ trim = function (string) {
64
+ return string == null ? "" : _trim.call(string);
65
+ };
66
+ } else {
67
+ var trimLeft, trimRight;
68
+
69
+ if (isWhitespace("\xA0")) {
70
+ trimLeft = /^\s+/;
71
+ trimRight = /\s+$/;
72
+ } else {
73
+ // IE doesn't match non-breaking spaces with \s, thanks jQuery.
74
+ trimLeft = /^[\s\xA0]+/;
75
+ trimRight = /[\s\xA0]+$/;
76
+ }
77
+
78
+ trim = function (string) {
79
+ return string == null ? "" :
80
+ String(string).replace(trimLeft, "").replace(trimRight, "");
81
+ };
82
+ }
83
+
84
+ var escapeMap = {
85
+ "&": "&amp;",
86
+ "<": "&lt;",
87
+ ">": "&gt;",
88
+ '"': '&quot;',
89
+ "'": '&#39;'
90
+ };
91
+
92
+ function escapeHTML(string) {
93
+ return String(string).replace(/&(?!\w+;)|[<>"']/g, function (s) {
94
+ return escapeMap[s] || s;
95
+ });
96
+ }
97
+
98
+ /**
99
+ * Adds the `template`, `line`, and `file` properties to the given error
100
+ * object and alters the message to provide more useful debugging information.
101
+ */
102
+ function debug(e, template, line, file) {
103
+ file = file || "<template>";
104
+
105
+ var lines = template.split("\n"),
106
+ start = Math.max(line - 3, 0),
107
+ end = Math.min(lines.length, line + 3),
108
+ context = lines.slice(start, end);
109
+
110
+ var c;
111
+ for (var i = 0, len = context.length; i < len; ++i) {
112
+ c = i + start + 1;
113
+ context[i] = (c === line ? " >> " : " ") + context[i];
114
+ }
115
+
116
+ e.template = template;
117
+ e.line = line;
118
+ e.file = file;
119
+ e.message = [file + ":" + line, context.join("\n"), "", e.message].join("\n");
120
+
121
+ return e;
122
+ }
123
+
124
+ /**
125
+ * Looks up the value of the given `name` in the given context `stack`.
126
+ */
127
+ function lookup(name, stack, defaultValue) {
128
+ if (name === ".") {
129
+ return stack[stack.length - 1];
130
+ }
131
+
132
+ var names = name.split(".");
133
+ var lastIndex = names.length - 1;
134
+ var target = names[lastIndex];
135
+
136
+ var value, context, i = stack.length, j, localStack;
137
+ while (i) {
138
+ localStack = stack.slice(0);
139
+ context = stack[--i];
140
+
141
+ j = 0;
142
+ while (j < lastIndex) {
143
+ context = context[names[j++]];
144
+
145
+ if (context == null) {
146
+ break;
147
+ }
148
+
149
+ localStack.push(context);
150
+ }
151
+
152
+ if (context && typeof context === "object" && target in context) {
153
+ value = context[target];
154
+ break;
155
+ }
156
+ }
157
+
158
+ // If the value is a function, call it in the current context.
159
+ if (typeof value === "function") {
160
+ value = value.call(localStack[localStack.length - 1]);
161
+ }
162
+
163
+ if (value == null) {
164
+ return defaultValue;
165
+ }
166
+
167
+ return value;
168
+ }
169
+
170
+ function renderSection(name, stack, callback, inverted) {
171
+ var buffer = "";
172
+ var value = lookup(name, stack);
173
+
174
+ if (inverted) {
175
+ // From the spec: inverted sections may render text once based on the
176
+ // inverse value of the key. That is, they will be rendered if the key
177
+ // doesn't exist, is false, or is an empty list.
178
+ if (value == null || value === false || (isArray(value) && value.length === 0)) {
179
+ buffer += callback();
180
+ }
181
+ } else if (isArray(value)) {
182
+ forEach(value, function (value) {
183
+ stack.push(value);
184
+ buffer += callback();
185
+ stack.pop();
186
+ });
187
+ } else if (typeof value === "object") {
188
+ stack.push(value);
189
+ buffer += callback();
190
+ stack.pop();
191
+ } else if (typeof value === "function") {
192
+ var scope = stack[stack.length - 1];
193
+ var scopedRender = function (template) {
194
+ return render(template, scope);
195
+ };
196
+ buffer += value.call(scope, callback(), scopedRender) || "";
197
+ } else if (value) {
198
+ buffer += callback();
199
+ }
200
+
201
+ return buffer;
202
+ }
203
+
204
+ /**
205
+ * Parses the given `template` and returns the source of a function that,
206
+ * with the proper arguments, will render the template. Recognized options
207
+ * include the following:
208
+ *
209
+ * - file The name of the file the template comes from (displayed in
210
+ * error messages)
211
+ * - tags An array of open and close tags the `template` uses. Defaults
212
+ * to the value of Mustache.tags
213
+ * - debug Set `true` to log the body of the generated function to the
214
+ * console
215
+ * - space Set `true` to preserve whitespace from lines that otherwise
216
+ * contain only a {{tag}}. Defaults to `false`
217
+ */
218
+ function parse(template, options) {
219
+ options = options || {};
220
+
221
+ var tags = options.tags || exports.tags,
222
+ openTag = tags[0],
223
+ closeTag = tags[tags.length - 1];
224
+
225
+ var code = [
226
+ 'var buffer = "";', // output buffer
227
+ "\nvar line = 1;", // keep track of source line number
228
+ "\ntry {",
229
+ '\nbuffer += "'
230
+ ];
231
+
232
+ var spaces = [], // indices of whitespace in code on the current line
233
+ hasTag = false, // is there a {{tag}} on the current line?
234
+ nonSpace = false; // is there a non-space char on the current line?
235
+
236
+ // Strips all space characters from the code array for the current line
237
+ // if there was a {{tag}} on it and otherwise only spaces.
238
+ var stripSpace = function () {
239
+ if (hasTag && !nonSpace && !options.space) {
240
+ while (spaces.length) {
241
+ code.splice(spaces.pop(), 1);
242
+ }
243
+ } else {
244
+ spaces = [];
245
+ }
246
+
247
+ hasTag = false;
248
+ nonSpace = false;
249
+ };
250
+
251
+ var sectionStack = [], updateLine, nextOpenTag, nextCloseTag;
252
+
253
+ var setTags = function (source) {
254
+ tags = trim(source).split(/\s+/);
255
+ nextOpenTag = tags[0];
256
+ nextCloseTag = tags[tags.length - 1];
257
+ };
258
+
259
+ var includePartial = function (source) {
260
+ code.push(
261
+ '";',
262
+ updateLine,
263
+ '\nvar partial = partials["' + trim(source) + '"];',
264
+ '\nif (partial) {',
265
+ '\n buffer += render(partial,stack[stack.length - 1],partials);',
266
+ '\n}',
267
+ '\nbuffer += "'
268
+ );
269
+ };
270
+
271
+ var openSection = function (source, inverted) {
272
+ var name = trim(source);
273
+
274
+ if (name === "") {
275
+ throw debug(new Error("Section name may not be empty"), template, line, options.file);
276
+ }
277
+
278
+ sectionStack.push({name: name, inverted: inverted});
279
+
280
+ code.push(
281
+ '";',
282
+ updateLine,
283
+ '\nvar name = "' + name + '";',
284
+ '\nvar callback = (function () {',
285
+ '\n return function () {',
286
+ '\n var buffer = "";',
287
+ '\nbuffer += "'
288
+ );
289
+ };
290
+
291
+ var openInvertedSection = function (source) {
292
+ openSection(source, true);
293
+ };
294
+
295
+ var closeSection = function (source) {
296
+ var name = trim(source);
297
+ var openName = sectionStack.length != 0 && sectionStack[sectionStack.length - 1].name;
298
+
299
+ if (!openName || name != openName) {
300
+ throw debug(new Error('Section named "' + name + '" was never opened'), template, line, options.file);
301
+ }
302
+
303
+ var section = sectionStack.pop();
304
+
305
+ code.push(
306
+ '";',
307
+ '\n return buffer;',
308
+ '\n };',
309
+ '\n})();'
310
+ );
311
+
312
+ if (section.inverted) {
313
+ code.push("\nbuffer += renderSection(name,stack,callback,true);");
314
+ } else {
315
+ code.push("\nbuffer += renderSection(name,stack,callback);");
316
+ }
317
+
318
+ code.push('\nbuffer += "');
319
+ };
320
+
321
+ var sendPlain = function (source) {
322
+ code.push(
323
+ '";',
324
+ updateLine,
325
+ '\nbuffer += lookup("' + trim(source) + '",stack,"");',
326
+ '\nbuffer += "'
327
+ );
328
+ };
329
+
330
+ var sendEscaped = function (source) {
331
+ code.push(
332
+ '";',
333
+ updateLine,
334
+ '\nbuffer += escapeHTML(lookup("' + trim(source) + '",stack,""));',
335
+ '\nbuffer += "'
336
+ );
337
+ };
338
+
339
+ var line = 1, c, callback;
340
+ for (var i = 0, len = template.length; i < len; ++i) {
341
+ if (template.slice(i, i + openTag.length) === openTag) {
342
+ i += openTag.length;
343
+ c = template.substr(i, 1);
344
+ updateLine = '\nline = ' + line + ';';
345
+ nextOpenTag = openTag;
346
+ nextCloseTag = closeTag;
347
+ hasTag = true;
348
+
349
+ switch (c) {
350
+ case "!": // comment
351
+ i++;
352
+ callback = null;
353
+ break;
354
+ case "=": // change open/close tags, e.g. {{=<% %>=}}
355
+ i++;
356
+ closeTag = "=" + closeTag;
357
+ callback = setTags;
358
+ break;
359
+ case ">": // include partial
360
+ i++;
361
+ callback = includePartial;
362
+ break;
363
+ case "#": // start section
364
+ i++;
365
+ callback = openSection;
366
+ break;
367
+ case "^": // start inverted section
368
+ i++;
369
+ callback = openInvertedSection;
370
+ break;
371
+ case "/": // end section
372
+ i++;
373
+ callback = closeSection;
374
+ break;
375
+ case "{": // plain variable
376
+ closeTag = "}" + closeTag;
377
+ // fall through
378
+ case "&": // plain variable
379
+ i++;
380
+ nonSpace = true;
381
+ callback = sendPlain;
382
+ break;
383
+ default: // escaped variable
384
+ nonSpace = true;
385
+ callback = sendEscaped;
386
+ }
387
+
388
+ var end = template.indexOf(closeTag, i);
389
+
390
+ if (end === -1) {
391
+ throw debug(new Error('Tag "' + openTag + '" was not closed properly'), template, line, options.file);
392
+ }
393
+
394
+ var source = template.substring(i, end);
395
+
396
+ if (callback) {
397
+ callback(source);
398
+ }
399
+
400
+ // Maintain line count for \n in source.
401
+ var n = 0;
402
+ while (~(n = source.indexOf("\n", n))) {
403
+ line++;
404
+ n++;
405
+ }
406
+
407
+ i = end + closeTag.length - 1;
408
+ openTag = nextOpenTag;
409
+ closeTag = nextCloseTag;
410
+ } else {
411
+ c = template.substr(i, 1);
412
+
413
+ switch (c) {
414
+ case '"':
415
+ case "\\":
416
+ nonSpace = true;
417
+ code.push("\\" + c);
418
+ break;
419
+ case "\r":
420
+ // Ignore carriage returns.
421
+ break;
422
+ case "\n":
423
+ spaces.push(code.length);
424
+ code.push("\\n");
425
+ stripSpace(); // Check for whitespace on the current line.
426
+ line++;
427
+ break;
428
+ default:
429
+ if (isWhitespace(c)) {
430
+ spaces.push(code.length);
431
+ } else {
432
+ nonSpace = true;
433
+ }
434
+
435
+ code.push(c);
436
+ }
437
+ }
438
+ }
439
+
440
+ if (sectionStack.length != 0) {
441
+ throw debug(new Error('Section "' + sectionStack[sectionStack.length - 1].name + '" was not closed properly'), template, line, options.file);
442
+ }
443
+
444
+ // Clean up any whitespace from a closing {{tag}} that was at the end
445
+ // of the template without a trailing \n.
446
+ stripSpace();
447
+
448
+ code.push(
449
+ '";',
450
+ "\nreturn buffer;",
451
+ "\n} catch (e) { throw {error: e, line: line}; }"
452
+ );
453
+
454
+ // Ignore `buffer += "";` statements.
455
+ var body = code.join("").replace(/buffer \+= "";\n/g, "");
456
+
457
+ if (options.debug) {
458
+ if (typeof console != "undefined" && console.log) {
459
+ console.log(body);
460
+ } else if (typeof print === "function") {
461
+ print(body);
462
+ }
463
+ }
464
+
465
+ return body;
466
+ }
467
+
468
+ /**
469
+ * Used by `compile` to generate a reusable function for the given `template`.
470
+ */
471
+ function _compile(template, options) {
472
+ var args = "view,partials,stack,lookup,escapeHTML,renderSection,render";
473
+ var body = parse(template, options);
474
+ var fn = new Function(args, body);
475
+
476
+ // This anonymous function wraps the generated function so we can do
477
+ // argument coercion, setup some variables, and handle any errors
478
+ // encountered while executing it.
479
+ return function (view, partials) {
480
+ partials = partials || {};
481
+
482
+ var stack = [view]; // context stack
483
+
484
+ try {
485
+ return fn(view, partials, stack, lookup, escapeHTML, renderSection, render);
486
+ } catch (e) {
487
+ throw debug(e.error, template, e.line, options.file);
488
+ }
489
+ };
490
+ }
491
+
492
+ // Cache of pre-compiled templates.
493
+ var _cache = {};
494
+
495
+ /**
496
+ * Clear the cache of compiled templates.
497
+ */
498
+ function clearCache() {
499
+ _cache = {};
500
+ }
501
+
502
+ /**
503
+ * Compiles the given `template` into a reusable function using the given
504
+ * `options`. In addition to the options accepted by Mustache.parse,
505
+ * recognized options include the following:
506
+ *
507
+ * - cache Set `false` to bypass any pre-compiled version of the given
508
+ * template. Otherwise, a given `template` string will be cached
509
+ * the first time it is parsed
510
+ */
511
+ function compile(template, options) {
512
+ options = options || {};
513
+
514
+ // Use a pre-compiled version from the cache if we have one.
515
+ if (options.cache !== false) {
516
+ if (!_cache[template]) {
517
+ _cache[template] = _compile(template, options);
518
+ }
519
+
520
+ return _cache[template];
521
+ }
522
+
523
+ return _compile(template, options);
524
+ }
525
+
526
+ /**
527
+ * High-level function that renders the given `template` using the given
528
+ * `view` and `partials`. If you need to use any of the template options (see
529
+ * `compile` above), you must compile in a separate step, and then call that
530
+ * compiled function.
531
+ */
532
+ function render(template, view, partials) {
533
+ return compile(template)(view, partials);
534
+ }
535
+
536
+ })(Mustache);
metadata ADDED
@@ -0,0 +1,108 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: smt_rails
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Alexey Vasiliev
9
+ - Alexander Chaplinsky
10
+ autorequire:
11
+ bindir: bin
12
+ cert_chain: []
13
+ date: 2012-04-12 00:00:00.000000000 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: rails
17
+ requirement: &70114162667300 !ruby/object:Gem::Requirement
18
+ none: false
19
+ requirements:
20
+ - - ! '>='
21
+ - !ruby/object:Gem::Version
22
+ version: 3.1.0
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: *70114162667300
26
+ - !ruby/object:Gem::Dependency
27
+ name: tilt
28
+ requirement: &70114162666640 !ruby/object:Gem::Requirement
29
+ none: false
30
+ requirements:
31
+ - - ! '>='
32
+ - !ruby/object:Gem::Version
33
+ version: 1.3.3
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: *70114162666640
37
+ - !ruby/object:Gem::Dependency
38
+ name: sprockets
39
+ requirement: &70114162664440 !ruby/object:Gem::Requirement
40
+ none: false
41
+ requirements:
42
+ - - ! '>='
43
+ - !ruby/object:Gem::Version
44
+ version: 2.0.3
45
+ type: :runtime
46
+ prerelease: false
47
+ version_requirements: *70114162664440
48
+ - !ruby/object:Gem::Dependency
49
+ name: mustache
50
+ requirement: &70114162663140 !ruby/object:Gem::Requirement
51
+ none: false
52
+ requirements:
53
+ - - ! '>='
54
+ - !ruby/object:Gem::Version
55
+ version: 0.99.4
56
+ type: :runtime
57
+ prerelease: false
58
+ version_requirements: *70114162663140
59
+ description: Shared mustache templates for rails 3
60
+ email:
61
+ - contacts@railsware.com
62
+ executables: []
63
+ extensions: []
64
+ extra_rdoc_files:
65
+ - LICENSE
66
+ - README.md
67
+ files:
68
+ - .gitignore
69
+ - Gemfile
70
+ - LICENSE
71
+ - README.md
72
+ - Rakefile
73
+ - lib/generators/smt_rails/helpers.rb
74
+ - lib/generators/smt_rails/install/install_generator.rb
75
+ - lib/smt_rails.rb
76
+ - lib/smt_rails/config.rb
77
+ - lib/smt_rails/engine.rb
78
+ - lib/smt_rails/mustache.rb
79
+ - lib/smt_rails/tilt.rb
80
+ - lib/smt_rails/version.rb
81
+ - smt_rails.gemspec
82
+ - vendor/assets/javascripts/mustache.js
83
+ homepage: https://github.com/railsware/smt_rails
84
+ licenses: []
85
+ post_install_message:
86
+ rdoc_options:
87
+ - --charset=UTF-8
88
+ require_paths:
89
+ - lib
90
+ required_ruby_version: !ruby/object:Gem::Requirement
91
+ none: false
92
+ requirements:
93
+ - - ! '>='
94
+ - !ruby/object:Gem::Version
95
+ version: '0'
96
+ required_rubygems_version: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ! '>='
100
+ - !ruby/object:Gem::Version
101
+ version: '0'
102
+ requirements: []
103
+ rubyforge_project:
104
+ rubygems_version: 1.8.16
105
+ signing_key:
106
+ specification_version: 3
107
+ summary: Shared mustache templates for rails 3
108
+ test_files: []