spine-rails 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in spine-rails.gemspec
4
+ gemspec
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
@@ -0,0 +1,84 @@
1
+ require 'rails'
2
+ require 'curb'
3
+
4
+ module Spinejs
5
+ module Generators
6
+ class InstallGenerator < ::Rails::Generators::Base
7
+ @@spine_version = "0.0.3"
8
+ @@icanhaz_version = "0.9"
9
+
10
+ desc "This generator installs spine.js #{@@spine_version}, json2.js, and (optionally) icanhaz.js #{@@icanhaz_version}"
11
+ class_option :ich, :type => :boolean, :default => false, :desc => "Include ICanHaz.js"
12
+ source_root File.expand_path('../../../../../vendor/assets/javascripts', __FILE__)
13
+
14
+ def fetch_libraries
15
+ url_icanhaz = "https://github.com/andyet/ICanHaz.js/raw/master/ICanHaz.js"
16
+ url_icanhaz_min = "https://github.com/andyet/ICanHaz.js/raw/master/ICanHaz.min.js"
17
+ url_json2 = "https://github.com/douglascrockford/JSON-js/raw/master/json2.js"
18
+ url_spine = "https://github.com/maccman/spine/raw/master/spine.js"
19
+ url_spine_min = "https://github.com/maccman/spine/raw/master/spine.min.js"
20
+ #urls = [url_spine, url_spine_min] #, url_json2, url_icanhaz, url_icanhaz_min]
21
+ urls = {"spine" => url_spine, "spine.min" => url_spine_min, "json2" => url_json2, "icanhaz" => url_icanhaz, "icanhaz.min" => url_icanhaz_min }
22
+
23
+ urls.each do |url|
24
+
25
+ # puts url[0]
26
+ the_url = url[1]
27
+ # puts the_url
28
+
29
+ filename = url[0]
30
+ new_file = "public/javascripts/#{filename}.js"
31
+
32
+
33
+ begin
34
+ c = Curl::Easy.new(the_url)
35
+ c.perform
36
+
37
+ # puts c.body_str
38
+ # end
39
+
40
+
41
+ if File.exist?(new_file)
42
+ puts "Skipping #{filename}.js because it already exists"
43
+ else
44
+ puts "Generating #{new_file}"
45
+ #FileUtils.cp(source, destination)
46
+ create_file new_file
47
+ append_to_file new_file, c.body_str
48
+ end
49
+
50
+ rescue
51
+ puts "Connection to #{the_url} failed!"
52
+ puts "Falling back to copying over a, most likely, older version."
53
+
54
+ say_status("copying", "#{filename}.js", :green)
55
+ copy_file "#{filename}.js", "public/javascripts/#{filename}.js"
56
+ #copy_file "spine.min.js", "public/javascripts/#{filename}.js"
57
+ end
58
+
59
+ end
60
+ end
61
+
62
+ # def copy_spine
63
+ # say_status("copying", "spine.js (#{@@spine_version})", :green)
64
+ # copy_file "spine.js", "public/javascripts/spine.js"
65
+ # copy_file "spine.min.js", "public/javascripts/spine.min.js"
66
+ # end
67
+ #
68
+ # def copy_json2
69
+ # say_status("copying", "json2.js", :green)
70
+ # copy_file "json2.js", "public/javascripts/json2.js"
71
+ # #copy_file "json2.min.js", "public/javascripts/json2.min.js"
72
+ # end
73
+ #
74
+ # def copy_icanhaz
75
+ # if options.ich?
76
+ # say_status("copying", "icanhaz.js (#{@@icanhaz_version})", :green)
77
+ # copy_file "icanhaz.js", "public/javascripts/icanhaz.js"
78
+ # copy_file "icanhaz.min.js", "public/javascripts/icanhaz.min.js"
79
+ # end
80
+ # end
81
+
82
+ end
83
+ end
84
+ end #if ::Rails.version < "3.1"
@@ -0,0 +1,18 @@
1
+ # Configure Rails 3.0 to use public/javascripts/spine et al
2
+ module Spinejs
3
+ module Rails
4
+
5
+ class Railtie < ::Rails::Railtie
6
+ config.before_configuration do
7
+
8
+ js_defaults = ::Rails.env.production? ? %w(spine.min) : %w(spine)
9
+
10
+ # Merge the jQuery scripts, remove the Prototype defaults and finally add 'rails'
11
+ # at the end, because load order is important
12
+ config.action_view.javascript_expansions[:defaults] |= js_defaults
13
+ #config.action_view.javascript_expansions[:defaults] << 'jquery_ujs'
14
+ end
15
+ end
16
+
17
+ end
18
+ end
@@ -0,0 +1,5 @@
1
+ module Spinejs
2
+ module Rails
3
+ VERSION = "0.0.1"
4
+ end
5
+ end
@@ -0,0 +1,12 @@
1
+ require 'rails/generators/base'
2
+
3
+ #$: << File.expand_path(File.dirname(__FILE__))
4
+
5
+ module Spinejs
6
+ module Rails #Generators
7
+ # Your code goes here...
8
+ if ::Rails.version < "3.1"
9
+ require 'spine-rails/railtie'
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,52 @@
1
+ desc "Fetch common recent versions of JS files"
2
+ task :get_js => :environment do
3
+
4
+ #require 'nokogiri'
5
+ #require 'open-uri'
6
+ require 'curb'
7
+
8
+ url_icanhaz = "https://github.com/andyet/ICanHaz.js/raw/master/ICanHaz.js"
9
+ url_icanhaz_min = "https://github.com/andyet/ICanHaz.js/raw/master/ICanHaz.min.js"
10
+ url_json2 = "https://github.com/douglascrockford/JSON-js/raw/master/json2.js"
11
+ url_spine = "https://github.com/maccman/spine/raw/master/spine.js"
12
+ url_spine_min = "https://github.com/maccman/spine/raw/master/spine.min.js"
13
+ urls = [url_spine, url_spine_min] #, url_json2, url_icanhaz, url_icanhaz_min]
14
+
15
+ source_root File.expand_path('../../../../../vendor/assets/javascripts', __FILE__)
16
+
17
+ urls.each do |url|
18
+
19
+ puts url
20
+
21
+ #doc = Nokogiri::HTML(open(url))
22
+
23
+ create_file "public/javascripts/spine.js"
24
+
25
+
26
+ c = Curl::Easy.new(url)
27
+ c.perform
28
+ #puts c.body_str
29
+
30
+
31
+ #copy_file "spine.js", "public/javascripts/spine.js"
32
+
33
+
34
+ # h2_exists = false
35
+ #
36
+ # doc.css("h2").each do |item|
37
+ # h2_exists = true
38
+ #
39
+ # end
40
+ #
41
+ # if h2_exists
42
+ # puts "is available"
43
+ # #theurl = "http://iwantmyname.com/search/add/#{threeio.word}/io/0"
44
+ # threeio.update_attributes(:date_checked => Date.today, :checked => checked)
45
+ # else
46
+ # puts "does not exist"
47
+ # threeio.update_attributes(:available => false, :date_checked => Date.today, :checked => checked)
48
+ # end
49
+
50
+ end
51
+
52
+ end
@@ -0,0 +1,27 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "spine-rails/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "spine-rails"
7
+ s.version = Spinejs::Rails::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Andrew Gertig"]
10
+ s.email = ["andrew.gertig@gmail.com"]
11
+ s.homepage = ""
12
+ s.summary = %q{Add Spine.js, json2.js, and icanhaz.js to your Rails app.}
13
+ s.description = %q{A gem of convenience.}
14
+
15
+ s.rubyforge_project = "spine-rails"
16
+
17
+ s.add_dependency "railties", "~> 3.0"
18
+ s.add_dependency "thor", "~> 0.14"
19
+ s.add_dependency "curb", "~> 0.7.15"
20
+ s.add_development_dependency "bundler", "~> 1.0.0"
21
+ s.add_development_dependency "rails", "~> 3.0"
22
+
23
+ s.files = `git ls-files`.split("\n")
24
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
25
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
26
+ s.require_paths = ["lib"]
27
+ end
data/tasks/get_js.rake ADDED
@@ -0,0 +1,52 @@
1
+ desc "Fetch common recent versions of JS files"
2
+ task :get_js => :environment do
3
+
4
+ #require 'nokogiri'
5
+ #require 'open-uri'
6
+ require 'curb'
7
+
8
+ url_icanhaz = "https://github.com/andyet/ICanHaz.js/raw/master/ICanHaz.js"
9
+ url_icanhaz_min = "https://github.com/andyet/ICanHaz.js/raw/master/ICanHaz.min.js"
10
+ url_json2 = "https://github.com/douglascrockford/JSON-js/raw/master/json2.js"
11
+ url_spine = "https://github.com/maccman/spine/raw/master/spine.js"
12
+ url_spine_min = "https://github.com/maccman/spine/raw/master/spine.min.js"
13
+ urls = [url_spine, url_spine_min] #, url_json2, url_icanhaz, url_icanhaz_min]
14
+
15
+ source_root File.expand_path('../../../../../vendor/assets/javascripts', __FILE__)
16
+
17
+ urls.each do |url|
18
+
19
+ puts url
20
+
21
+ #doc = Nokogiri::HTML(open(url))
22
+
23
+ create_file "public/javascripts/spine.js"
24
+
25
+
26
+ c = Curl::Easy.new(url)
27
+ c.perform
28
+ #puts c.body_str
29
+
30
+
31
+ #copy_file "spine.js", "public/javascripts/spine.js"
32
+
33
+
34
+ # h2_exists = false
35
+ #
36
+ # doc.css("h2").each do |item|
37
+ # h2_exists = true
38
+ #
39
+ # end
40
+ #
41
+ # if h2_exists
42
+ # puts "is available"
43
+ # #theurl = "http://iwantmyname.com/search/add/#{threeio.word}/io/0"
44
+ # threeio.update_attributes(:date_checked => Date.today, :checked => checked)
45
+ # else
46
+ # puts "does not exist"
47
+ # threeio.update_attributes(:available => false, :date_checked => Date.today, :checked => checked)
48
+ # end
49
+
50
+ end
51
+
52
+ end
@@ -0,0 +1,401 @@
1
+ /*!
2
+ ICanHaz.js version 0.9 -- by @HenrikJoreteg
3
+ More info at: http://icanhazjs.com
4
+ */
5
+ (function ($) {
6
+ /*!
7
+ mustache.js -- Logic-less templates in JavaScript
8
+
9
+ by @janl (MIT Licensed, https://github.com/janl/mustache.js/blob/master/LICENSE).
10
+
11
+ See http://mustache.github.com/ for more info.
12
+ */
13
+
14
+ var Mustache = function() {
15
+ var Renderer = function() {};
16
+
17
+ Renderer.prototype = {
18
+ otag: "{{",
19
+ ctag: "}}",
20
+ pragmas: {},
21
+ buffer: [],
22
+ pragmas_implemented: {
23
+ "IMPLICIT-ITERATOR": true
24
+ },
25
+ context: {},
26
+
27
+ render: function(template, context, partials, in_recursion) {
28
+ // reset buffer & set context
29
+ if(!in_recursion) {
30
+ this.context = context;
31
+ this.buffer = []; // TODO: make this non-lazy
32
+ }
33
+
34
+ // fail fast
35
+ if(!this.includes("", template)) {
36
+ if(in_recursion) {
37
+ return template;
38
+ } else {
39
+ this.send(template);
40
+ return;
41
+ }
42
+ }
43
+
44
+ template = this.render_pragmas(template);
45
+ var html = this.render_section(template, context, partials);
46
+ if(in_recursion) {
47
+ return this.render_tags(html, context, partials, in_recursion);
48
+ }
49
+
50
+ this.render_tags(html, context, partials, in_recursion);
51
+ },
52
+
53
+ /*
54
+ Sends parsed lines
55
+ */
56
+ send: function(line) {
57
+ if(line != "") {
58
+ this.buffer.push(line);
59
+ }
60
+ },
61
+
62
+ /*
63
+ Looks for %PRAGMAS
64
+ */
65
+ render_pragmas: function(template) {
66
+ // no pragmas
67
+ if(!this.includes("%", template)) {
68
+ return template;
69
+ }
70
+
71
+ var that = this;
72
+ var regex = new RegExp(this.otag + "%([\\w-]+) ?([\\w]+=[\\w]+)?" +
73
+ this.ctag);
74
+ return template.replace(regex, function(match, pragma, options) {
75
+ if(!that.pragmas_implemented[pragma]) {
76
+ throw({message:
77
+ "This implementation of mustache doesn't understand the '" +
78
+ pragma + "' pragma"});
79
+ }
80
+ that.pragmas[pragma] = {};
81
+ if(options) {
82
+ var opts = options.split("=");
83
+ that.pragmas[pragma][opts[0]] = opts[1];
84
+ }
85
+ return "";
86
+ // ignore unknown pragmas silently
87
+ });
88
+ },
89
+
90
+ /*
91
+ Tries to find a partial in the curent scope and render it
92
+ */
93
+ render_partial: function(name, context, partials) {
94
+ name = this.trim(name);
95
+ if(!partials || partials[name] === undefined) {
96
+ throw({message: "unknown_partial '" + name + "'"});
97
+ }
98
+ if(typeof(context[name]) != "object") {
99
+ return this.render(partials[name], context, partials, true);
100
+ }
101
+ return this.render(partials[name], context[name], partials, true);
102
+ },
103
+
104
+ /*
105
+ Renders inverted (^) and normal (#) sections
106
+ */
107
+ render_section: function(template, context, partials) {
108
+ if(!this.includes("#", template) && !this.includes("^", template)) {
109
+ return template;
110
+ }
111
+
112
+ var that = this;
113
+ // CSW - Added "+?" so it finds the tighest bound, not the widest
114
+ var regex = new RegExp(this.otag + "(\\^|\\#)\\s*(.+)\\s*" + this.ctag +
115
+ "\n*([\\s\\S]+?)" + this.otag + "\\/\\s*\\2\\s*" + this.ctag +
116
+ "\\s*", "mg");
117
+
118
+ // for each {{#foo}}{{/foo}} section do...
119
+ return template.replace(regex, function(match, type, name, content) {
120
+ var value = that.find(name, context);
121
+ if(type == "^") { // inverted section
122
+ if(!value || that.is_array(value) && value.length === 0) {
123
+ // false or empty list, render it
124
+ return that.render(content, context, partials, true);
125
+ } else {
126
+ return "";
127
+ }
128
+ } else if(type == "#") { // normal section
129
+ if(that.is_array(value)) { // Enumerable, Let's loop!
130
+ return that.map(value, function(row) {
131
+ return that.render(content, that.create_context(row),
132
+ partials, true);
133
+ }).join("");
134
+ } else if(that.is_object(value)) { // Object, Use it as subcontext!
135
+ return that.render(content, that.create_context(value),
136
+ partials, true);
137
+ } else if(typeof value === "function") {
138
+ // higher order section
139
+ return value.call(context, content, function(text) {
140
+ return that.render(text, context, partials, true);
141
+ });
142
+ } else if(value) { // boolean section
143
+ return that.render(content, context, partials, true);
144
+ } else {
145
+ return "";
146
+ }
147
+ }
148
+ });
149
+ },
150
+
151
+ /*
152
+ Replace {{foo}} and friends with values from our view
153
+ */
154
+ render_tags: function(template, context, partials, in_recursion) {
155
+ // tit for tat
156
+ var that = this;
157
+
158
+ var new_regex = function() {
159
+ return new RegExp(that.otag + "(=|!|>|\\{|%)?([^\\/#\\^]+?)\\1?" +
160
+ that.ctag + "+", "g");
161
+ };
162
+
163
+ var regex = new_regex();
164
+ var tag_replace_callback = function(match, operator, name) {
165
+ switch(operator) {
166
+ case "!": // ignore comments
167
+ return "";
168
+ case "=": // set new delimiters, rebuild the replace regexp
169
+ that.set_delimiters(name);
170
+ regex = new_regex();
171
+ return "";
172
+ case ">": // render partial
173
+ return that.render_partial(name, context, partials);
174
+ case "{": // the triple mustache is unescaped
175
+ return that.find(name, context);
176
+ default: // escape the value
177
+ return that.escape(that.find(name, context));
178
+ }
179
+ };
180
+ var lines = template.split("\n");
181
+ for(var i = 0; i < lines.length; i++) {
182
+ lines[i] = lines[i].replace(regex, tag_replace_callback, this);
183
+ if(!in_recursion) {
184
+ this.send(lines[i]);
185
+ }
186
+ }
187
+
188
+ if(in_recursion) {
189
+ return lines.join("\n");
190
+ }
191
+ },
192
+
193
+ set_delimiters: function(delimiters) {
194
+ var dels = delimiters.split(" ");
195
+ this.otag = this.escape_regex(dels[0]);
196
+ this.ctag = this.escape_regex(dels[1]);
197
+ },
198
+
199
+ escape_regex: function(text) {
200
+ // thank you Simon Willison
201
+ if(!arguments.callee.sRE) {
202
+ var specials = [
203
+ '/', '.', '*', '+', '?', '|',
204
+ '(', ')', '[', ']', '{', '}', '\\'
205
+ ];
206
+ arguments.callee.sRE = new RegExp(
207
+ '(\\' + specials.join('|\\') + ')', 'g'
208
+ );
209
+ }
210
+ return text.replace(arguments.callee.sRE, '\\$1');
211
+ },
212
+
213
+ /*
214
+ find `name` in current `context`. That is find me a value
215
+ from the view object
216
+ */
217
+ find: function(name, context) {
218
+ name = this.trim(name);
219
+
220
+ // Checks whether a value is thruthy or false or 0
221
+ function is_kinda_truthy(bool) {
222
+ return bool === false || bool === 0 || bool;
223
+ }
224
+
225
+ var value;
226
+ if(is_kinda_truthy(context[name])) {
227
+ value = context[name];
228
+ } else if(is_kinda_truthy(this.context[name])) {
229
+ value = this.context[name];
230
+ }
231
+
232
+ if(typeof value === "function") {
233
+ return value.apply(context);
234
+ }
235
+ if(value !== undefined) {
236
+ return value;
237
+ }
238
+ // silently ignore unkown variables
239
+ return "";
240
+ },
241
+
242
+ // Utility methods
243
+
244
+ /* includes tag */
245
+ includes: function(needle, haystack) {
246
+ return haystack.indexOf(this.otag + needle) != -1;
247
+ },
248
+
249
+ /*
250
+ Does away with nasty characters
251
+ */
252
+ escape: function(s) {
253
+ s = String(s === null ? "" : s);
254
+ return s.replace(/&(?!\w+;)|["<>\\]/g, function(s) {
255
+ switch(s) {
256
+ case "&": return "&amp;";
257
+ case "\\": return "\\\\";
258
+ case '"': return '\"';
259
+ case "<": return "&lt;";
260
+ case ">": return "&gt;";
261
+ default: return s;
262
+ }
263
+ });
264
+ },
265
+
266
+ // by @langalex, support for arrays of strings
267
+ create_context: function(_context) {
268
+ if(this.is_object(_context)) {
269
+ return _context;
270
+ } else {
271
+ var iterator = ".";
272
+ if(this.pragmas["IMPLICIT-ITERATOR"]) {
273
+ iterator = this.pragmas["IMPLICIT-ITERATOR"].iterator;
274
+ }
275
+ var ctx = {};
276
+ ctx[iterator] = _context;
277
+ return ctx;
278
+ }
279
+ },
280
+
281
+ is_object: function(a) {
282
+ return a && typeof a == "object";
283
+ },
284
+
285
+ is_array: function(a) {
286
+ return Object.prototype.toString.call(a) === '[object Array]';
287
+ },
288
+
289
+ /*
290
+ Gets rid of leading and trailing whitespace
291
+ */
292
+ trim: function(s) {
293
+ return s.replace(/^\s*|\s*$/g, "");
294
+ },
295
+
296
+ /*
297
+ Why, why, why? Because IE. Cry, cry cry.
298
+ */
299
+ map: function(array, fn) {
300
+ if (typeof array.map == "function") {
301
+ return array.map(fn);
302
+ } else {
303
+ var r = [];
304
+ var l = array.length;
305
+ for(var i = 0; i < l; i++) {
306
+ r.push(fn(array[i]));
307
+ }
308
+ return r;
309
+ }
310
+ }
311
+ };
312
+
313
+ return({
314
+ name: "mustache.js",
315
+ version: "0.3.0",
316
+
317
+ /*
318
+ Turns a template and view into HTML
319
+ */
320
+ to_html: function(template, view, partials, send_fun) {
321
+ var renderer = new Renderer();
322
+ if(send_fun) {
323
+ renderer.send = send_fun;
324
+ }
325
+ renderer.render(template, view, partials);
326
+ if(!send_fun) {
327
+ return renderer.buffer.join("\n");
328
+ }
329
+ }
330
+ });
331
+ }();/*!
332
+ ICanHaz.js -- by @HenrikJoreteg
333
+ */
334
+ /*global jQuery */
335
+ function ICanHaz() {
336
+ var self = this;
337
+ self.VERSION = "0.9";
338
+ self.templates = {};
339
+ self.partials = {};
340
+
341
+ // public function for adding templates
342
+ // We're enforcing uniqueness to avoid accidental template overwrites.
343
+ // If you want a different template, it should have a different name.
344
+ self.addTemplate = function (name, templateString) {
345
+ if (self[name]) throw "Invalid name: " + name + ".";
346
+ if (self.templates[name]) throw "Template \" + name + \" exists";
347
+
348
+ self.templates[name] = templateString;
349
+ self[name] = function (data, raw) {
350
+ data = data || {};
351
+ var result = Mustache.to_html(self.templates[name], data, self.partials);
352
+ return raw ? result : $(result);
353
+ };
354
+ };
355
+
356
+ // public function for adding partials
357
+ self.addPartial = function (name, templateString) {
358
+ if (self.partials[name]) {
359
+ throw "Partial \" + name + \" exists";
360
+ } else {
361
+ self.partials[name] = templateString;
362
+ }
363
+ };
364
+
365
+ // grabs templates from the DOM and caches them.
366
+ // Loop through and add templates.
367
+ // Whitespace at beginning and end of all templates inside <script> tags will
368
+ // be trimmed. If you want whitespace around a partial, add it in the parent,
369
+ // not the partial. Or do it explicitly using <br/> or &nbsp;
370
+ self.grabTemplates = function () {
371
+ $('script[type="text/html"]').each(function (a, b) {
372
+ var script = $((typeof a === 'number') ? b : a), // Zepto doesn't bind this
373
+ text = (''.trim) ? script.html().trim() : $.trim(script.html());
374
+
375
+ self[script.hasClass('partial') ? 'addPartial' : 'addTemplate'](script.attr('id'), text);
376
+ script.remove();
377
+ });
378
+ };
379
+
380
+ // clears all retrieval functions and empties caches
381
+ self.clearAll = function () {
382
+ for (var key in self.templates) {
383
+ delete self[key];
384
+ }
385
+ self.templates = {};
386
+ self.partials = {};
387
+ };
388
+
389
+ self.refresh = function () {
390
+ self.clearAll();
391
+ self.grabTemplates();
392
+ };
393
+ }
394
+
395
+ window.ich = new ICanHaz();
396
+
397
+ // init itself on document ready
398
+ $(function () {
399
+ ich.grabTemplates();
400
+ });
401
+ })(window.jQuery || window.Zepto);
@@ -0,0 +1,9 @@
1
+ (function(i){var n=function(){var f=function(){};f.prototype={otag:"{{",ctag:"}}",pragmas:{},buffer:[],pragmas_implemented:{"IMPLICIT-ITERATOR":true},context:{},render:function(a,b,c,d){if(!d){this.context=b;this.buffer=[]}if(!this.includes("",a))if(d)return a;else{this.send(a);return}a=this.render_pragmas(a);a=this.render_section(a,b,c);if(d)return this.render_tags(a,b,c,d);this.render_tags(a,b,c,d)},send:function(a){a!=""&&this.buffer.push(a)},render_pragmas:function(a){if(!this.includes("%",a))return a;
2
+ var b=this;return a.replace(RegExp(this.otag+"%([\\w-]+) ?([\\w]+=[\\w]+)?"+this.ctag),function(c,d,e){if(!b.pragmas_implemented[d])throw{message:"This implementation of mustache doesn't understand the '"+d+"' pragma"};b.pragmas[d]={};if(e){c=e.split("=");b.pragmas[d][c[0]]=c[1]}return""})},render_partial:function(a,b,c){a=this.trim(a);if(!c||c[a]===undefined)throw{message:"unknown_partial '"+a+"'"};if(typeof b[a]!="object")return this.render(c[a],b,c,true);return this.render(c[a],b[a],c,true)},render_section:function(a,
3
+ b,c){if(!this.includes("#",a)&&!this.includes("^",a))return a;var d=this;return a.replace(RegExp(this.otag+"(\\^|\\#)\\s*(.+)\\s*"+this.ctag+"\n*([\\s\\S]+?)"+this.otag+"\\/\\s*\\2\\s*"+this.ctag+"\\s*","mg"),function(e,j,k,h){e=d.find(k,b);if(j=="^")return!e||d.is_array(e)&&e.length===0?d.render(h,b,c,true):"";else if(j=="#")return d.is_array(e)?d.map(e,function(g){return d.render(h,d.create_context(g),c,true)}).join(""):d.is_object(e)?d.render(h,d.create_context(e),c,true):typeof e==="function"?
4
+ e.call(b,h,function(g){return d.render(g,b,c,true)}):e?d.render(h,b,c,true):""})},render_tags:function(a,b,c,d){var e=this,j=function(){return RegExp(e.otag+"(=|!|>|\\{|%)?([^\\/#\\^]+?)\\1?"+e.ctag+"+","g")},k=j(),h=function(o,m,l){switch(m){case "!":return"";case "=":e.set_delimiters(l);k=j();return"";case ">":return e.render_partial(l,b,c);case "{":return e.find(l,b);default:return e.escape(e.find(l,b))}};a=a.split("\n");for(var g=0;g<a.length;g++){a[g]=a[g].replace(k,h,this);d||this.send(a[g])}if(d)return a.join("\n")},
5
+ set_delimiters:function(a){a=a.split(" ");this.otag=this.escape_regex(a[0]);this.ctag=this.escape_regex(a[1])},escape_regex:function(a){if(!arguments.callee.sRE)arguments.callee.sRE=RegExp("(\\/|\\.|\\*|\\+|\\?|\\||\\(|\\)|\\[|\\]|\\{|\\}|\\\\)","g");return a.replace(arguments.callee.sRE,"\\$1")},find:function(a,b){a=this.trim(a);var c;if(b[a]===false||b[a]===0||b[a])c=b[a];else if(this.context[a]===false||this.context[a]===0||this.context[a])c=this.context[a];if(typeof c==="function")return c.apply(b);
6
+ if(c!==undefined)return c;return""},includes:function(a,b){return b.indexOf(this.otag+a)!=-1},escape:function(a){a=String(a===null?"":a);return a.replace(/&(?!\w+;)|["<>\\]/g,function(b){switch(b){case "&":return"&amp;";case "\\":return"\\\\";case '"':return'"';case "<":return"&lt;";case ">":return"&gt;";default:return b}})},create_context:function(a){if(this.is_object(a))return a;else{var b=".";if(this.pragmas["IMPLICIT-ITERATOR"])b=this.pragmas["IMPLICIT-ITERATOR"].iterator;var c={};c[b]=a;return c}},
7
+ is_object:function(a){return a&&typeof a=="object"},is_array:function(a){return Object.prototype.toString.call(a)==="[object Array]"},trim:function(a){return a.replace(/^\s*|\s*$/g,"")},map:function(a,b){if(typeof a.map=="function")return a.map(b);else{for(var c=[],d=a.length,e=0;e<d;e++)c.push(b(a[e]));return c}}};return{name:"mustache.js",version:"0.3.0",to_html:function(a,b,c,d){var e=new f;if(d)e.send=d;e.render(a,b,c);if(!d)return e.buffer.join("\n")}}}();window.ich=new function(){var f=this;
8
+ f.VERSION="0.9";f.templates={};f.partials={};f.addTemplate=function(a,b){if(f[a])throw"Invalid name: "+a+".";if(f.templates[a])throw'Template " + name + " exists';f.templates[a]=b;f[a]=function(c,d){c=c||{};var e=n.to_html(f.templates[a],c,f.partials);return d?e:i(e)}};f.addPartial=function(a,b){if(f.partials[a])throw'Partial " + name + " exists';else f.partials[a]=b};f.grabTemplates=function(){i('script[type="text/html"]').each(function(a,b){var c=i(typeof a==="number"?b:a),d="".trim?c.html().trim():
9
+ i.trim(c.html());f[c.hasClass("partial")?"addPartial":"addTemplate"](c.attr("id"),d);c.remove()})};f.clearAll=function(){for(var a in f.templates)delete f[a];f.templates={};f.partials={}};f.refresh=function(){f.clearAll();f.grabTemplates()}};i(function(){ich.grabTemplates()})})(window.jQuery||window.Zepto);