jim 0.1.2 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. data/HISTORY +28 -0
  2. data/README.rdoc +1 -1
  3. data/Rakefile +2 -1
  4. data/jim.gemspec +67 -9
  5. data/lib/jim/bundler.rb +14 -11
  6. data/lib/jim/cli.rb +51 -9
  7. data/lib/jim/index.rb +3 -7
  8. data/lib/jim/installer.rb +140 -22
  9. data/lib/jim/templates/commands +21 -6
  10. data/lib/jim/version_parser.rb +2 -3
  11. data/lib/jim.rb +19 -2
  12. data/test/fixtures/jimfile +3 -3
  13. data/test/fixtures/sammy-0.5.0/HISTORY.md +135 -0
  14. data/test/fixtures/sammy-0.5.0/LICENSE +22 -0
  15. data/test/fixtures/sammy-0.5.0/README.md +81 -0
  16. data/test/fixtures/sammy-0.5.0/Rakefile +174 -0
  17. data/test/fixtures/sammy-0.5.0/examples/backend/README.md +23 -0
  18. data/test/fixtures/sammy-0.5.0/examples/backend/Rakefile +15 -0
  19. data/test/fixtures/sammy-0.5.0/examples/backend/app.rb +17 -0
  20. data/test/fixtures/sammy-0.5.0/examples/backend/app.ru +3 -0
  21. data/test/fixtures/sammy-0.5.0/examples/backend/public/javascripts/app.js +106 -0
  22. data/test/fixtures/sammy-0.5.0/examples/backend/public/javascripts/jquery.cloudkit.js +840 -0
  23. data/test/fixtures/sammy-0.5.0/examples/backend/public/javascripts/jquery.js +19 -0
  24. data/test/fixtures/sammy-0.5.0/examples/backend/public/javascripts/sammy.js +1013 -0
  25. data/test/fixtures/sammy-0.5.0/examples/backend/public/templates/index.html.erb +11 -0
  26. data/test/fixtures/sammy-0.5.0/examples/backend/public/templates/task.html.erb +4 -0
  27. data/test/fixtures/sammy-0.5.0/examples/backend/public/templates/task_details.html.erb +4 -0
  28. data/test/fixtures/sammy-0.5.0/examples/backend/views/app.sass +63 -0
  29. data/test/fixtures/sammy-0.5.0/examples/backend/views/index.haml +18 -0
  30. data/test/fixtures/sammy-0.5.0/examples/form_handling/files/form.html +12 -0
  31. data/test/fixtures/sammy-0.5.0/examples/form_handling/index.html +65 -0
  32. data/test/fixtures/sammy-0.5.0/examples/hello_world/index.html +50 -0
  33. data/test/fixtures/sammy-0.5.0/examples/location_override/README.md +15 -0
  34. data/test/fixtures/sammy-0.5.0/examples/location_override/data.html +110 -0
  35. data/test/fixtures/sammy-0.5.0/examples/location_override/index.html +79 -0
  36. data/test/fixtures/sammy-0.5.0/examples/location_override/test.html +121 -0
  37. data/test/fixtures/sammy-0.5.0/lib/min/sammy-0.5.0.min.js +5 -0
  38. data/test/fixtures/sammy-0.5.0/lib/min/sammy-lastest.min.js +5 -0
  39. data/test/fixtures/sammy-0.5.0/lib/plugins/sammy.cache.js +117 -0
  40. data/test/fixtures/sammy-0.5.0/lib/plugins/sammy.haml.js +539 -0
  41. data/test/fixtures/sammy-0.5.0/lib/plugins/sammy.json.js +362 -0
  42. data/test/fixtures/sammy-0.5.0/lib/plugins/sammy.mustache.js +415 -0
  43. data/test/fixtures/sammy-0.5.0/lib/plugins/sammy.nested_params.js +118 -0
  44. data/test/fixtures/sammy-0.5.0/lib/plugins/sammy.storage.js +515 -0
  45. data/test/fixtures/sammy-0.5.0/lib/plugins/sammy.template.js +117 -0
  46. data/test/fixtures/sammy-0.5.0/lib/sammy.js +1367 -0
  47. data/test/fixtures/sammy-0.5.0/test/fixtures/partial +1 -0
  48. data/test/fixtures/sammy-0.5.0/test/fixtures/partial.html +1 -0
  49. data/test/fixtures/sammy-0.5.0/test/fixtures/partial.noengine +1 -0
  50. data/test/fixtures/sammy-0.5.0/test/fixtures/partial.template +1 -0
  51. data/test/fixtures/sammy-0.5.0/test/index.html +84 -0
  52. data/test/fixtures/sammy-0.5.0/test/test_sammy_application.js +953 -0
  53. data/test/fixtures/sammy-0.5.0/test/test_sammy_event_context.js +252 -0
  54. data/test/fixtures/sammy-0.5.0/test/test_sammy_location_proxy.js +91 -0
  55. data/test/fixtures/sammy-0.5.0/test/test_sammy_plugins.js +296 -0
  56. data/test/fixtures/sammy-0.5.0/test/test_sammy_storage.js +175 -0
  57. data/test/fixtures/sammy-0.5.0/test/test_server +27 -0
  58. data/test/fixtures/sammy-0.5.0/vendor/jquery-1.4.1.js +6078 -0
  59. data/test/fixtures/sammy-0.5.0/vendor/jquery-1.4.1.min.js +152 -0
  60. data/test/fixtures/sammy-0.5.0/vendor/jsdoc/doc.haml +58 -0
  61. data/test/fixtures/sammy-0.5.0/vendor/jsdoc/jsdoc.rb +143 -0
  62. data/test/fixtures/sammy-0.5.0/vendor/jslitmus.js +670 -0
  63. data/test/fixtures/sammy-0.5.0/vendor/qunit/qunit.css +119 -0
  64. data/test/fixtures/sammy-0.5.0/vendor/qunit/qunit.js +1043 -0
  65. data/test/fixtures/sammy-0.5.0/vendor/qunit-spec.js +127 -0
  66. data/test/helper.rb +23 -3
  67. data/test/test_jim_bundler.rb +9 -8
  68. data/test/test_jim_cli.rb +21 -12
  69. data/test/test_jim_installer.rb +152 -35
  70. data/test/test_jim_version_parser.rb +4 -0
  71. metadata +117 -27
  72. data/.document +0 -5
@@ -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,118 @@
1
+ (function($) {
2
+
3
+ Sammy = Sammy || {};
4
+
5
+ function parseNestedParam(field_value, field_name, params) {
6
+ var match, name, rest;
7
+
8
+ if (field_name.match(/^[^\[]+$/)) {
9
+ // basic value
10
+ params[field_name] = unescape(field_value);
11
+ } else if (match = field_name.match(/^([^\[]+)\[\](.*)$/)) {
12
+ // array
13
+ name = match[1];
14
+ rest = match[2];
15
+
16
+ if(params[name] && !$.isArray(params[name])) { throw('400 Bad Request'); }
17
+
18
+ if (rest) {
19
+ // array is not at the end of the parameter string
20
+ match = rest.match(/^\[([^\]]+)\](.*)$/);
21
+ if(!match) { throw('400 Bad Request'); }
22
+
23
+ if (params[name]) {
24
+ if(params[name][params[name].length - 1][match[1]]) {
25
+ params[name].push(parseNestedParam(field_value, match[1] + match[2], {}));
26
+ } else {
27
+ $.extend(true, params[name][params[name].length - 1], parseNestedParam(field_value, match[1] + match[2], {}));
28
+ }
29
+ } else {
30
+ params[name] = [parseNestedParam(field_value, match[1] + match[2], {})];
31
+ }
32
+ } else {
33
+ // array is at the end of the parameter string
34
+ if (params[name]) {
35
+ params[name].push(unescape(field_value));
36
+ } else {
37
+ params[name] = [unescape(field_value)];
38
+ }
39
+ }
40
+ } else if (match = field_name.match(/^([^\[]+)\[([^\[]+)\](.*)$/)) {
41
+ // hash
42
+ name = match[1];
43
+ rest = match[2] + match[3];
44
+
45
+ if (params[name] && $.isArray(params[name])) { throw('400 Bad Request'); }
46
+
47
+ if (params[name]) {
48
+ $.extend(true, params[name], parseNestedParam(field_value, rest, params[name]));
49
+ } else {
50
+ params[name] = parseNestedParam(field_value, rest, {});
51
+ }
52
+ }
53
+ return params;
54
+ };
55
+
56
+
57
+ // <tt>Sammy.NestedParams</tt> overrides the default form parsing behavior to provide
58
+ // extended functionality for parsing Rack/Rails style form name/value pairs into JS
59
+ // Objects. In fact it passes the same suite of tests as Rack's nested query parsing.
60
+ // The code and tests were ported to JavaScript/Sammy by http://github.com/endor
61
+ //
62
+ // This allows you to translate a form with properly named inputs into a JSON object.
63
+ //
64
+ // === Example
65
+ //
66
+ // Given an HTML form like so:
67
+ //
68
+ // <form action="#/parse_me" method="post">
69
+ // <input type="text" name="obj[first]" />
70
+ // <input type="text" name="obj[second]" />
71
+ // <input type="text" name="obj[hash][first]" />
72
+ // <input type="text" name="obj[hash][second]" />
73
+ // </form>
74
+ //
75
+ // And a Sammy app like:
76
+ //
77
+ // var app = $.sammy(function(app) {
78
+ // this.use(Sammy.NestedParams);
79
+ //
80
+ // this.post('#/parse_me', function(context) {
81
+ // $.log(this.params);
82
+ // });
83
+ // });
84
+ //
85
+ // If you filled out the form with some values and submitted it, you would see something
86
+ // like this in your log:
87
+ //
88
+ // {
89
+ // 'obj': {
90
+ // 'first': 'value',
91
+ // 'second': 'value',
92
+ // 'hash': {
93
+ // 'first': 'value',
94
+ // 'second': 'value'
95
+ // }
96
+ // }
97
+ // '$form': .. jQuery ..
98
+ // }
99
+ //
100
+ // It supports creating arrays with [] and other niceities. Check out the tests for
101
+ // full specs.
102
+ //
103
+ Sammy.NestedParams = function(app) {
104
+
105
+ $.extend(app, {
106
+ _parseFormParams: function($form) {
107
+ var params = {};
108
+ $.each($form.serializeArray(), function(i, field) {
109
+ $.extend(true, params, parseNestedParam(field.value, field.name, params));
110
+ });
111
+
112
+ return params;
113
+ }
114
+ });
115
+
116
+ };
117
+
118
+ })(jQuery);