soca 0.1.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.
Files changed (45) hide show
  1. data/.document +5 -0
  2. data/.gitignore +21 -0
  3. data/HISTORY +3 -0
  4. data/LICENSE +20 -0
  5. data/README.md +89 -0
  6. data/Rakefile +58 -0
  7. data/bin/soca +5 -0
  8. data/lib/soca.rb +34 -0
  9. data/lib/soca/cli.rb +189 -0
  10. data/lib/soca/plugin.rb +31 -0
  11. data/lib/soca/plugins/compass.rb +24 -0
  12. data/lib/soca/plugins/jim.rb +19 -0
  13. data/lib/soca/pusher.rb +186 -0
  14. data/lib/soca/templates/Jimfile +12 -0
  15. data/lib/soca/templates/config.js.erb +4 -0
  16. data/lib/soca/templates/couchapprc.erb +10 -0
  17. data/lib/soca/templates/css/screen.css +1 -0
  18. data/lib/soca/templates/db/views/by_type/map.js +3 -0
  19. data/lib/soca/templates/hooks/before_build.rb +2 -0
  20. data/lib/soca/templates/index.html.erb +17 -0
  21. data/lib/soca/templates/js/app.js +12 -0
  22. data/lib/soca/templates/js/vendor/jquery-1.4.2.js +6240 -0
  23. data/lib/soca/templates/js/vendor/jquery.couch-0.11.js +668 -0
  24. data/lib/soca/templates/js/vendor/sammy-0.6.1.js +1809 -0
  25. data/lib/soca/templates/js/vendor/sammy.couch-0.1.0.js +122 -0
  26. data/lib/soca/templates/js/vendor/sha1.js +202 -0
  27. data/soca.gemspec +107 -0
  28. data/test/helper.rb +36 -0
  29. data/test/test_soca_cli.rb +120 -0
  30. data/test/test_soca_pusher.rb +79 -0
  31. data/test/testapp/.couchapprc +10 -0
  32. data/test/testapp/Jimfile +11 -0
  33. data/test/testapp/config.js +11 -0
  34. data/test/testapp/css/app.css +3 -0
  35. data/test/testapp/db/views/recent/map.js +5 -0
  36. data/test/testapp/hooks/before_build.rb +1 -0
  37. data/test/testapp/index.html +11 -0
  38. data/test/testapp/js/app.js +5 -0
  39. data/test/testapp/js/bundled.js +8544 -0
  40. data/test/testapp/js/vendor/jquery-1.4.2.js +6240 -0
  41. data/test/testapp/js/vendor/json2.js +478 -0
  42. data/test/testapp/js/vendor/sammy-0.5.4.js +1403 -0
  43. data/test/testapp/js/vendor/sammy.mustache-0.5.4.js +415 -0
  44. data/test/testapp/templates/index.mustache +1 -0
  45. metadata +205 -0
@@ -0,0 +1,415 @@
1
+ (function($) {
2
+
3
+ if (!Mustache) {
4
+
5
+ /*
6
+ Shamless port of http://github.com/defunkt/mustache
7
+ by Jan Lehnardt <jan@apache.org>,
8
+ Alexander Lang <alex@upstream-berlin.com>,
9
+ Sebastian Cohnen <sebastian.cohnen@googlemail.com>
10
+
11
+ Thanks @defunkt for the awesome code.
12
+
13
+ See http://github.com/defunkt/mustache for more info.
14
+ */
15
+
16
+ var Mustache = function() {
17
+ var Renderer = function() {};
18
+
19
+ Renderer.prototype = {
20
+ otag: "{{",
21
+ ctag: "}}",
22
+ pragmas: {},
23
+ buffer: [],
24
+
25
+ render: function(template, context, partials, in_recursion) {
26
+ // fail fast
27
+ if(template.indexOf(this.otag) == -1) {
28
+ if(in_recursion) {
29
+ return template;
30
+ } else {
31
+ this.send(template);
32
+ }
33
+ }
34
+
35
+ if(!in_recursion) {
36
+ this.buffer = [];
37
+ }
38
+
39
+ template = this.render_pragmas(template);
40
+ var html = this.render_section(template, context, partials);
41
+ if(in_recursion) {
42
+ return this.render_tags(html, context, partials, in_recursion);
43
+ }
44
+
45
+ this.render_tags(html, context, partials, in_recursion);
46
+ },
47
+
48
+ /*
49
+ Sends parsed lines
50
+ */
51
+ send: function(line) {
52
+ if(line != "") {
53
+ this.buffer.push(line);
54
+ }
55
+ },
56
+
57
+ /*
58
+ Looks for %PRAGMAS
59
+ */
60
+ render_pragmas: function(template) {
61
+ // no pragmas
62
+ if(template.indexOf(this.otag + "%") == -1) {
63
+ return template;
64
+ }
65
+
66
+ var that = this;
67
+ var regex = new RegExp(this.otag + "%([\\w_-]+) ?([\\w]+=[\\w]+)?"
68
+ + this.ctag);
69
+ return template.replace(regex, function(match, pragma, options) {
70
+ that.pragmas[pragma] = {};
71
+ if(options) {
72
+ var opts = options.split("=");
73
+ that.pragmas[pragma][opts[0]] = opts[1];
74
+ }
75
+ return "";
76
+ // ignore unknown pragmas silently
77
+ });
78
+ },
79
+
80
+ /*
81
+ Tries to find a partial in the global scope and render it
82
+ */
83
+ render_partial: function(name, context, partials) {
84
+ if(typeof(context[name]) != "object") {
85
+ throw({message: "subcontext for '" + name + "' is not an object"});
86
+ }
87
+ if(!partials || !partials[name]) {
88
+ throw({message: "unknown_partial"});
89
+ }
90
+ return this.render(partials[name], context[name], partials, true);
91
+ },
92
+
93
+ /*
94
+ Renders boolean and enumerable sections
95
+ */
96
+ render_section: function(template, context, partials) {
97
+ if(template.indexOf(this.otag + "#") == -1) {
98
+ return template;
99
+ }
100
+ var that = this;
101
+ // CSW - Added "+?" so it finds the tighest bound, not the widest
102
+ var regex = new RegExp(this.otag + "\\#(.+)" + this.ctag +
103
+ "\\s*([\\s\\S]+?)" + this.otag + "\\/\\1" + this.ctag + "\\s*", "mg");
104
+
105
+ // for each {{#foo}}{{/foo}} section do...
106
+ return template.replace(regex, function(match, name, content) {
107
+ var value = that.find(name, context);
108
+ if(that.is_array(value)) { // Enumerable, Let's loop!
109
+ return that.map(value, function(row) {
110
+ return that.render(content, that.merge(context,
111
+ that.create_context(row)), partials, true);
112
+ }).join("");
113
+ } else if(value) { // boolean section
114
+ return that.render(content, context, partials, true);
115
+ } else {
116
+ return "";
117
+ }
118
+ });
119
+ },
120
+
121
+ /*
122
+ Replace {{foo}} and friends with values from our view
123
+ */
124
+ render_tags: function(template, context, partials, in_recursion) {
125
+ // tit for tat
126
+ var that = this;
127
+
128
+ var new_regex = function() {
129
+ return new RegExp(that.otag + "(=|!|>|\\{|%)?([^\/#]+?)\\1?" +
130
+ that.ctag + "+", "g");
131
+ };
132
+
133
+ var regex = new_regex();
134
+ var lines = template.split("\n");
135
+ for (var i=0; i < lines.length; i++) {
136
+ lines[i] = lines[i].replace(regex, function(match, operator, name) {
137
+ switch(operator) {
138
+ case "!": // ignore comments
139
+ return match;
140
+ case "=": // set new delimiters, rebuild the replace regexp
141
+ that.set_delimiters(name);
142
+ regex = new_regex();
143
+ return "";
144
+ case ">": // render partial
145
+ return that.render_partial(name, context, partials);
146
+ case "{": // the triple mustache is unescaped
147
+ return that.find(name, context);
148
+ default: // escape the value
149
+ return that.escape(that.find(name, context));
150
+ }
151
+ }, this);
152
+ if(!in_recursion) {
153
+ this.send(lines[i]);
154
+ }
155
+ }
156
+ return lines.join("\n");
157
+ },
158
+
159
+ set_delimiters: function(delimiters) {
160
+ var dels = delimiters.split(" ");
161
+ this.otag = this.escape_regex(dels[0]);
162
+ this.ctag = this.escape_regex(dels[1]);
163
+ },
164
+
165
+ escape_regex: function(text) {
166
+ // thank you Simon Willison
167
+ if(!arguments.callee.sRE) {
168
+ var specials = [
169
+ '/', '.', '*', '+', '?', '|',
170
+ '(', ')', '[', ']', '{', '}', '\\'
171
+ ];
172
+ arguments.callee.sRE = new RegExp(
173
+ '(\\' + specials.join('|\\') + ')', 'g'
174
+ );
175
+ }
176
+ return text.replace(arguments.callee.sRE, '\\$1');
177
+ },
178
+
179
+ /*
180
+ find `name` in current `context`. That is find me a value
181
+ from the view object
182
+ */
183
+ find: function(name, context) {
184
+ name = this.trim(name);
185
+ if(typeof context[name] === "function") {
186
+ return context[name].apply(context);
187
+ }
188
+ if(context[name] !== undefined) {
189
+ return context[name];
190
+ }
191
+ // silently ignore unkown variables
192
+ return "";
193
+ },
194
+
195
+ // Utility methods
196
+
197
+ /*
198
+ Does away with nasty characters
199
+ */
200
+ escape: function(s) {
201
+ return s.toString().replace(/[&"<>\\]/g, function(s) {
202
+ switch(s) {
203
+ case "&": return "&amp;";
204
+ case "\\": return "\\\\";;
205
+ case '"': return '\"';;
206
+ case "<": return "&lt;";
207
+ case ">": return "&gt;";
208
+ default: return s;
209
+ }
210
+ });
211
+ },
212
+
213
+ /*
214
+ Merges all properties of object `b` into object `a`.
215
+ `b.property` overwrites a.property`
216
+ */
217
+ merge: function(a, b) {
218
+ var _new = {};
219
+ for(var name in a) {
220
+ if(a.hasOwnProperty(name)) {
221
+ _new[name] = a[name];
222
+ }
223
+ };
224
+ for(var name in b) {
225
+ if(b.hasOwnProperty(name)) {
226
+ _new[name] = b[name];
227
+ }
228
+ };
229
+ return _new;
230
+ },
231
+
232
+ // by @langalex, support for arrays of strings
233
+ create_context: function(_context) {
234
+ if(this.is_object(_context)) {
235
+ return _context;
236
+ } else if(this.pragmas["IMPLICIT-ITERATOR"]) {
237
+ var iterator = this.pragmas["IMPLICIT-ITERATOR"].iterator || ".";
238
+ var ctx = {};
239
+ ctx[iterator] = _context
240
+ return ctx;
241
+ }
242
+ },
243
+
244
+ is_object: function(a) {
245
+ return a && typeof a == "object"
246
+ },
247
+
248
+ /*
249
+ Thanks Doug Crockford
250
+ JavaScript — The Good Parts lists an alternative that works better with
251
+ frames. Frames can suck it, we use the simple version.
252
+ */
253
+ is_array: function(a) {
254
+ return (a &&
255
+ typeof a === "object" &&
256
+ a.constructor === Array);
257
+ },
258
+
259
+ /*
260
+ Gets rid of leading and trailing whitespace
261
+ */
262
+ trim: function(s) {
263
+ return s.replace(/^\s*|\s*$/g, "");
264
+ },
265
+
266
+ /*
267
+ Why, why, why? Because IE. Cry, cry cry.
268
+ */
269
+ map: function(array, fn) {
270
+ if (typeof array.map == "function") {
271
+ return array.map(fn)
272
+ } else {
273
+ var r = [];
274
+ var l = array.length;
275
+ for(i=0;i<l;i++) {
276
+ r.push(fn(array[i]));
277
+ }
278
+ return r;
279
+ }
280
+ }
281
+ };
282
+
283
+ return({
284
+ name: "mustache.js",
285
+ version: "0.2.2",
286
+
287
+ /*
288
+ Turns a template and view into HTML
289
+ */
290
+ to_html: function(template, view, partials, send_fun) {
291
+ var renderer = new Renderer();
292
+ if(send_fun) {
293
+ renderer.send = send_fun;
294
+ }
295
+ renderer.render(template, view, partials);
296
+ return renderer.buffer.join("\n");
297
+ }
298
+ });
299
+ }();
300
+
301
+ } // Ensure Mustache
302
+
303
+ Sammy = Sammy || {};
304
+
305
+ // <tt>Sammy.Mustache</tt> provides a quick way of using mustache style templates in your app.
306
+ // The plugin itself includes the awesome mustache.js lib created and maintained by Jan Lehnardt
307
+ // at http://github.com/janl/mustache.js
308
+ //
309
+ // Mustache is a clever templating system that relys on double brackets {{}} for interpolation.
310
+ // For full details on syntax check out the original Ruby implementation created by Chris Wanstrath at
311
+ // http://github.com/defunkt/mustache
312
+ //
313
+ // By default using Sammy.Mustache in your app adds the <tt>mustache()</tt> method to the EventContext
314
+ // prototype. However, just like <tt>Sammy.Template</tt> you can change the default name of the method
315
+ // by passing a second argument (e.g. you could use the ms() as the method alias so that all the template
316
+ // files could be in the form file.ms instead of file.mustache)
317
+ //
318
+ // ### Example #1
319
+ //
320
+ // The template (mytemplate.ms):
321
+ //
322
+ // <h1>\{\{title\}\}<h1>
323
+ //
324
+ // Hey, {{name}}! Welcome to Mustache!
325
+ //
326
+ // The app:
327
+ //
328
+ // var $.app = $.sammy(function() {
329
+ // // include the plugin and alias mustache() to ms()
330
+ // this.use(Sammy.Mustache, 'ms');
331
+ //
332
+ // this.get('#/hello/:name', function() {
333
+ // // set local vars
334
+ // this.title = 'Hello!'
335
+ // this.name = this.params.name;
336
+ // // render the template and pass it through mustache
337
+ // this.partial('mytemplate.ms');
338
+ // });
339
+ //
340
+ // });
341
+ //
342
+ // If I go to #/hello/AQ in the browser, Sammy will render this to the <tt>body</tt>:
343
+ //
344
+ // <h1>Hello!</h1>
345
+ //
346
+ // Hey, AQ! Welcome to Mustache!
347
+ //
348
+ //
349
+ // ### Example #2 - Mustache partials
350
+ //
351
+ // The template (mytemplate.ms)
352
+ //
353
+ // Hey, {{name}}! {{>hello_friend}}
354
+ //
355
+ //
356
+ // The partial (mypartial.ms)
357
+ //
358
+ // Say hello to your friend {{friend}}!
359
+ //
360
+ // The app:
361
+ //
362
+ // var $.app = $.sammy(function() {
363
+ // // include the plugin and alias mustache() to ms()
364
+ // this.use(Sammy.Mustache, 'ms');
365
+ //
366
+ // this.get('#/hello/:name/to/:friend', function() {
367
+ // var context = this;
368
+ //
369
+ // // fetch mustache-partial first
370
+ // $.get('mypartial.ms', function(response){
371
+ // context.partials = response;
372
+ //
373
+ // // set local vars
374
+ // context.name = this.params.name;
375
+ // context.hello_friend = {name: this.params.friend};
376
+ //
377
+ // // render the template and pass it through mustache
378
+ // context.partial('mytemplate.ms');
379
+ // });
380
+ // });
381
+ //
382
+ // });
383
+ //
384
+ // If I go to #/hello/AQ/to/dP in the browser, Sammy will render this to the <tt>body</tt>:
385
+ //
386
+ // Hey, AQ! Say hello to your friend dP!
387
+ //
388
+ // Note: You dont have to include the mustache.js file on top of the plugin as the plugin
389
+ // includes the full source.
390
+ //
391
+ Sammy.Mustache = function(app, method_alias) {
392
+
393
+ // *Helper* Uses Mustache.js to parse a template and interpolate and work with the passed data
394
+ //
395
+ // ### Arguments
396
+ //
397
+ // * `template` A String template. {{}} Tags are evaluated and interpolated by Mustache.js
398
+ // * `data` An Object containing the replacement values for the template.
399
+ // data is extended with the <tt>EventContext</tt> allowing you to call its methods within the template.
400
+ // * `partials` An Object containing one or more partials (String templates
401
+ // that are called from the main template).
402
+ //
403
+ var mustache = function(template, data, partials) {
404
+ data = $.extend({}, this, data);
405
+ partials = $.extend({}, data.partials, partials);
406
+ return Mustache.to_html(template, data, partials);
407
+ };
408
+
409
+ // set the default method name/extension
410
+ if (!method_alias) method_alias = 'mustache';
411
+ app.helper(method_alias, mustache);
412
+
413
+ };
414
+
415
+ })(jQuery);
@@ -0,0 +1 @@
1
+ <h1>{{name}}</h1>
metadata ADDED
@@ -0,0 +1,205 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: soca
3
+ version: !ruby/object:Gem::Version
4
+ hash: 27
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 0
10
+ version: 0.1.0
11
+ platform: ruby
12
+ authors:
13
+ - Aaron Quint
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2010-09-26 00:00:00 +02:00
19
+ default_executable: soca
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: json
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ hash: 11
30
+ segments:
31
+ - 1
32
+ - 4
33
+ - 6
34
+ version: 1.4.6
35
+ type: :runtime
36
+ version_requirements: *id001
37
+ - !ruby/object:Gem::Dependency
38
+ name: typhoeus
39
+ prerelease: false
40
+ requirement: &id002 !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ hash: 37
46
+ segments:
47
+ - 0
48
+ - 1
49
+ - 31
50
+ version: 0.1.31
51
+ type: :runtime
52
+ version_requirements: *id002
53
+ - !ruby/object:Gem::Dependency
54
+ name: jim
55
+ prerelease: false
56
+ requirement: &id003 !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ hash: 17
62
+ segments:
63
+ - 0
64
+ - 2
65
+ - 3
66
+ version: 0.2.3
67
+ type: :runtime
68
+ version_requirements: *id003
69
+ - !ruby/object:Gem::Dependency
70
+ name: compass
71
+ prerelease: false
72
+ requirement: &id004 !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ~>
76
+ - !ruby/object:Gem::Version
77
+ hash: 61
78
+ segments:
79
+ - 0
80
+ - 10
81
+ - 5
82
+ version: 0.10.5
83
+ type: :runtime
84
+ version_requirements: *id004
85
+ - !ruby/object:Gem::Dependency
86
+ name: shoulda
87
+ prerelease: false
88
+ requirement: &id005 !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ">="
92
+ - !ruby/object:Gem::Version
93
+ hash: 3
94
+ segments:
95
+ - 0
96
+ version: "0"
97
+ type: :development
98
+ version_requirements: *id005
99
+ - !ruby/object:Gem::Dependency
100
+ name: yard
101
+ prerelease: false
102
+ requirement: &id006 !ruby/object:Gem::Requirement
103
+ none: false
104
+ requirements:
105
+ - - ">="
106
+ - !ruby/object:Gem::Version
107
+ hash: 3
108
+ segments:
109
+ - 0
110
+ version: "0"
111
+ type: :development
112
+ version_requirements: *id006
113
+ description: soca is a different way of writing apps for CouchDB. The structure is up to you.
114
+ email: aaron@quirkey.com
115
+ executables:
116
+ - soca
117
+ extensions: []
118
+
119
+ extra_rdoc_files:
120
+ - LICENSE
121
+ - README.md
122
+ files:
123
+ - .document
124
+ - .gitignore
125
+ - HISTORY
126
+ - LICENSE
127
+ - README.md
128
+ - Rakefile
129
+ - bin/soca
130
+ - lib/soca.rb
131
+ - lib/soca/cli.rb
132
+ - lib/soca/plugin.rb
133
+ - lib/soca/plugins/compass.rb
134
+ - lib/soca/plugins/jim.rb
135
+ - lib/soca/pusher.rb
136
+ - lib/soca/templates/Jimfile
137
+ - lib/soca/templates/config.js.erb
138
+ - lib/soca/templates/couchapprc.erb
139
+ - lib/soca/templates/css/screen.css
140
+ - lib/soca/templates/db/views/by_type/map.js
141
+ - lib/soca/templates/hooks/before_build.rb
142
+ - lib/soca/templates/index.html.erb
143
+ - lib/soca/templates/js/app.js
144
+ - lib/soca/templates/js/vendor/jquery-1.4.2.js
145
+ - lib/soca/templates/js/vendor/jquery.couch-0.11.js
146
+ - lib/soca/templates/js/vendor/sammy-0.6.1.js
147
+ - lib/soca/templates/js/vendor/sammy.couch-0.1.0.js
148
+ - lib/soca/templates/js/vendor/sha1.js
149
+ - soca.gemspec
150
+ - test/helper.rb
151
+ - test/test_soca_cli.rb
152
+ - test/test_soca_pusher.rb
153
+ - test/testapp/.couchapprc
154
+ - test/testapp/Jimfile
155
+ - test/testapp/config.js
156
+ - test/testapp/css/app.css
157
+ - test/testapp/db/views/recent/map.js
158
+ - test/testapp/hooks/before_build.rb
159
+ - test/testapp/index.html
160
+ - test/testapp/js/app.js
161
+ - test/testapp/js/bundled.js
162
+ - test/testapp/js/vendor/jquery-1.4.2.js
163
+ - test/testapp/js/vendor/json2.js
164
+ - test/testapp/js/vendor/sammy-0.5.4.js
165
+ - test/testapp/js/vendor/sammy.mustache-0.5.4.js
166
+ - test/testapp/templates/index.mustache
167
+ has_rdoc: true
168
+ homepage: http://github.com/quirkey/soca
169
+ licenses: []
170
+
171
+ post_install_message:
172
+ rdoc_options:
173
+ - --charset=UTF-8
174
+ require_paths:
175
+ - lib
176
+ required_ruby_version: !ruby/object:Gem::Requirement
177
+ none: false
178
+ requirements:
179
+ - - ">="
180
+ - !ruby/object:Gem::Version
181
+ hash: 3
182
+ segments:
183
+ - 0
184
+ version: "0"
185
+ required_rubygems_version: !ruby/object:Gem::Requirement
186
+ none: false
187
+ requirements:
188
+ - - ">="
189
+ - !ruby/object:Gem::Version
190
+ hash: 3
191
+ segments:
192
+ - 0
193
+ version: "0"
194
+ requirements: []
195
+
196
+ rubyforge_project:
197
+ rubygems_version: 1.3.7
198
+ signing_key:
199
+ specification_version: 3
200
+ summary: Sammy on CouchApp
201
+ test_files:
202
+ - test/helper.rb
203
+ - test/test_soca_cli.rb
204
+ - test/test_soca_pusher.rb
205
+ - test/testapp/hooks/before_build.rb