couch 0.1.1 → 0.1.2
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.
- data/.gitmodules +2 -2
- data/README.rdoc +4 -4
- data/Rakefile +19 -0
- data/couch.gemspec +2 -1
- data/lib/couch/generators/application/application_generator.rb +1 -1
- data/lib/couch/generators/application/templates/lib/mustache.js +305 -0
- data/lib/couch/version.rb +1 -1
- metadata +3 -2
data/.gitmodules
CHANGED
@@ -1,3 +1,3 @@
|
|
1
|
-
[submodule "
|
2
|
-
path =
|
1
|
+
[submodule "vendor/mustache.js"]
|
2
|
+
path = vendor/mustache.js
|
3
3
|
url = git://github.com/janl/mustache.js.git
|
data/README.rdoc
CHANGED
@@ -31,13 +31,13 @@ Building standalone CouchDB applications according to correct principles affords
|
|
31
31
|
== What comes next
|
32
32
|
|
33
33
|
At the moment, Couch supports generating a scaffold application, pushing to a CouchDB server and pulling from a CouchDB.
|
34
|
+
Couch injects the !code and !json makros introduced by CouchApp.
|
34
35
|
|
35
36
|
The next big steps are:
|
36
37
|
|
37
|
-
*
|
38
|
-
*
|
39
|
-
*
|
40
|
-
|
38
|
+
* make use of mustache.js in generators
|
39
|
+
* build a lightweight JavaScript library to assist client side JavaScript work
|
40
|
+
* enhance generators to build a full flavored scaffold with all CRUD operations
|
41
41
|
|
42
42
|
== I need your help!
|
43
43
|
|
data/Rakefile
CHANGED
@@ -2,6 +2,25 @@ require 'rubygems'
|
|
2
2
|
require 'rake'
|
3
3
|
require File.join(File.dirname(__FILE__), 'lib', 'couch', 'version')
|
4
4
|
|
5
|
+
namespace :vendor do
|
6
|
+
desc "Update vendor"
|
7
|
+
task :update do
|
8
|
+
`git submodule update`
|
9
|
+
end
|
10
|
+
|
11
|
+
desc "vendor mustache"
|
12
|
+
task :mustache do
|
13
|
+
dir = File.expand_path('..', __FILE__)
|
14
|
+
source = File.join(dir, 'vendor/mustache.js/mustache.js')
|
15
|
+
target = File.join(dir, 'lib/couch/generators/application/templates/lib/')
|
16
|
+
FileUtils.cp source, target
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
desc "Vendor all"
|
21
|
+
task :vendor => ["vendor:update", "vendor:mustache"]
|
22
|
+
|
23
|
+
|
5
24
|
begin
|
6
25
|
require 'jeweler'
|
7
26
|
Jeweler::Tasks.new do |gem|
|
data/couch.gemspec
CHANGED
@@ -5,7 +5,7 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{couch}
|
8
|
-
s.version = "0.1.
|
8
|
+
s.version = "0.1.2"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Johannes J. Schmidt"]
|
@@ -47,6 +47,7 @@ Gem::Specification.new do |s|
|
|
47
47
|
"lib/couch/generators/application/templates/_id.js",
|
48
48
|
"lib/couch/generators/application/templates/couchrc",
|
49
49
|
"lib/couch/generators/application/templates/gitignore",
|
50
|
+
"lib/couch/generators/application/templates/lib/mustache.js",
|
50
51
|
"lib/couch/generators/application/templates/validate_doc_update.js",
|
51
52
|
"lib/couch/generators/base.rb",
|
52
53
|
"lib/couch/generators/list/USAGE",
|
@@ -0,0 +1,305 @@
|
|
1
|
+
/*
|
2
|
+
Shameless port of http://github.com/defunkt/mustache
|
3
|
+
by Jan Lehnardt <jan@apache.org>,
|
4
|
+
Alexander Lang <alex@upstream-berlin.com>,
|
5
|
+
Sebastian Cohnen <sebastian.cohnen@googlemail.com>
|
6
|
+
|
7
|
+
Thanks @defunkt for the awesome code.
|
8
|
+
|
9
|
+
See http://github.com/defunkt/mustache for more info.
|
10
|
+
*/
|
11
|
+
|
12
|
+
var Mustache = function() {
|
13
|
+
var Renderer = function() {};
|
14
|
+
|
15
|
+
Renderer.prototype = {
|
16
|
+
otag: "{{",
|
17
|
+
ctag: "}}",
|
18
|
+
pragmas: {},
|
19
|
+
buffer: [],
|
20
|
+
pragmas_parsed: false,
|
21
|
+
pragmas_implemented: {
|
22
|
+
"IMPLICIT-ITERATOR": true
|
23
|
+
},
|
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
|
+
return;
|
33
|
+
}
|
34
|
+
}
|
35
|
+
|
36
|
+
if(!in_recursion) {
|
37
|
+
this.buffer = [];
|
38
|
+
}
|
39
|
+
|
40
|
+
if(!this.pragmas_parsed) {
|
41
|
+
template = this.render_pragmas(template);
|
42
|
+
}
|
43
|
+
var html = this.render_section(template, context, partials);
|
44
|
+
if(in_recursion) {
|
45
|
+
return this.render_tags(html, context, partials, in_recursion);
|
46
|
+
}
|
47
|
+
|
48
|
+
this.render_tags(html, context, partials, in_recursion);
|
49
|
+
},
|
50
|
+
|
51
|
+
/*
|
52
|
+
Sends parsed lines
|
53
|
+
*/
|
54
|
+
send: function(line) {
|
55
|
+
if(line != "") {
|
56
|
+
this.buffer.push(line);
|
57
|
+
}
|
58
|
+
},
|
59
|
+
|
60
|
+
/*
|
61
|
+
Looks for %PRAGMAS
|
62
|
+
*/
|
63
|
+
render_pragmas: function(template) {
|
64
|
+
this.pragmas_parsed = true;
|
65
|
+
// no pragmas
|
66
|
+
if(template.indexOf(this.otag + "%") == -1) {
|
67
|
+
return template;
|
68
|
+
}
|
69
|
+
|
70
|
+
var that = this;
|
71
|
+
var regex = new RegExp(this.otag + "%([\\w_-]+) ?([\\w]+=[\\w]+)?"
|
72
|
+
+ this.ctag);
|
73
|
+
return template.replace(regex, function(match, pragma, options) {
|
74
|
+
if(!that.pragmas_implemented[pragma]) {
|
75
|
+
throw({message: "This implementation of mustache doesn't understand the '"
|
76
|
+
+ pragma + "' pragma"});
|
77
|
+
}
|
78
|
+
that.pragmas[pragma] = {};
|
79
|
+
if(options) {
|
80
|
+
var opts = options.split("=");
|
81
|
+
that.pragmas[pragma][opts[0]] = opts[1];
|
82
|
+
}
|
83
|
+
return "";
|
84
|
+
// ignore unknown pragmas silently
|
85
|
+
});
|
86
|
+
},
|
87
|
+
|
88
|
+
/*
|
89
|
+
Tries to find a partial in the global scope and render it
|
90
|
+
*/
|
91
|
+
render_partial: function(name, context, partials) {
|
92
|
+
if(typeof(context[name]) != "object") {
|
93
|
+
throw({message: "subcontext for '" + name + "' is not an object"});
|
94
|
+
}
|
95
|
+
if(!partials || !partials[name]) {
|
96
|
+
throw({message: "unknown_partial '" + name + "'"});
|
97
|
+
}
|
98
|
+
return this.render(partials[name], context[name], partials, true);
|
99
|
+
},
|
100
|
+
|
101
|
+
/*
|
102
|
+
Renders boolean and enumerable sections
|
103
|
+
*/
|
104
|
+
render_section: function(template, context, partials) {
|
105
|
+
if(template.indexOf(this.otag + "#") == -1) {
|
106
|
+
return template;
|
107
|
+
}
|
108
|
+
var that = this;
|
109
|
+
// CSW - Added "+?" so it finds the tighest bound, not the widest
|
110
|
+
var regex = new RegExp(this.otag + "\\#(.+)" + this.ctag +
|
111
|
+
"\\s*([\\s\\S]+?)" + this.otag + "\\/\\1" + this.ctag + "\\s*", "mg");
|
112
|
+
|
113
|
+
// for each {{#foo}}{{/foo}} section do...
|
114
|
+
return template.replace(regex, function(match, name, content) {
|
115
|
+
var value = that.find(name, context);
|
116
|
+
if(that.is_array(value)) { // Enumerable, Let's loop!
|
117
|
+
return that.map(value, function(row) {
|
118
|
+
return that.render(content, that.merge(context,
|
119
|
+
that.create_context(row)), partials, true);
|
120
|
+
}).join("");
|
121
|
+
} else if(value) { // boolean section
|
122
|
+
return that.render(content, context, partials, true);
|
123
|
+
} else {
|
124
|
+
return "";
|
125
|
+
}
|
126
|
+
});
|
127
|
+
},
|
128
|
+
|
129
|
+
/*
|
130
|
+
Replace {{foo}} and friends with values from our view
|
131
|
+
*/
|
132
|
+
render_tags: function(template, context, partials, in_recursion) {
|
133
|
+
// tit for tat
|
134
|
+
var that = this;
|
135
|
+
|
136
|
+
var new_regex = function() {
|
137
|
+
return new RegExp(that.otag + "(=|!|>|\\{|%)?([^\/#]+?)\\1?" +
|
138
|
+
that.ctag + "+", "g");
|
139
|
+
};
|
140
|
+
|
141
|
+
var regex = new_regex();
|
142
|
+
var lines = template.split("\n");
|
143
|
+
for (var i=0; i < lines.length; i++) {
|
144
|
+
lines[i] = lines[i].replace(regex, function(match, operator, name) {
|
145
|
+
switch(operator) {
|
146
|
+
case "!": // ignore comments
|
147
|
+
return match;
|
148
|
+
case "=": // set new delimiters, rebuild the replace regexp
|
149
|
+
that.set_delimiters(name);
|
150
|
+
regex = new_regex();
|
151
|
+
return "";
|
152
|
+
case ">": // render partial
|
153
|
+
return that.render_partial(name, context, partials);
|
154
|
+
case "{": // the triple mustache is unescaped
|
155
|
+
return that.find(name, context);
|
156
|
+
default: // escape the value
|
157
|
+
return that.escape(that.find(name, context));
|
158
|
+
}
|
159
|
+
}, this);
|
160
|
+
if(!in_recursion) {
|
161
|
+
this.send(lines[i]);
|
162
|
+
}
|
163
|
+
}
|
164
|
+
|
165
|
+
if(in_recursion) {
|
166
|
+
return lines.join("\n");
|
167
|
+
}
|
168
|
+
},
|
169
|
+
|
170
|
+
set_delimiters: function(delimiters) {
|
171
|
+
var dels = delimiters.split(" ");
|
172
|
+
this.otag = this.escape_regex(dels[0]);
|
173
|
+
this.ctag = this.escape_regex(dels[1]);
|
174
|
+
},
|
175
|
+
|
176
|
+
escape_regex: function(text) {
|
177
|
+
// thank you Simon Willison
|
178
|
+
if(!arguments.callee.sRE) {
|
179
|
+
var specials = [
|
180
|
+
'/', '.', '*', '+', '?', '|',
|
181
|
+
'(', ')', '[', ']', '{', '}', '\\'
|
182
|
+
];
|
183
|
+
arguments.callee.sRE = new RegExp(
|
184
|
+
'(\\' + specials.join('|\\') + ')', 'g'
|
185
|
+
);
|
186
|
+
}
|
187
|
+
return text.replace(arguments.callee.sRE, '\\$1');
|
188
|
+
},
|
189
|
+
|
190
|
+
/*
|
191
|
+
find `name` in current `context`. That is find me a value
|
192
|
+
from the view object
|
193
|
+
*/
|
194
|
+
find: function(name, context) {
|
195
|
+
name = this.trim(name);
|
196
|
+
if(typeof context[name] === "function") {
|
197
|
+
return context[name].apply(context);
|
198
|
+
}
|
199
|
+
if(context[name] !== undefined) {
|
200
|
+
return context[name];
|
201
|
+
}
|
202
|
+
// silently ignore unkown variables
|
203
|
+
return "";
|
204
|
+
},
|
205
|
+
|
206
|
+
// Utility methods
|
207
|
+
|
208
|
+
/*
|
209
|
+
Does away with nasty characters
|
210
|
+
*/
|
211
|
+
escape: function(s) {
|
212
|
+
return ((s == null) ? "" : s).toString().replace(/[&"<>\\]/g, function(s) {
|
213
|
+
switch(s) {
|
214
|
+
case "&": return "&";
|
215
|
+
case "\\": return "\\\\";;
|
216
|
+
case '"': return '\"';;
|
217
|
+
case "<": return "<";
|
218
|
+
case ">": return ">";
|
219
|
+
default: return s;
|
220
|
+
}
|
221
|
+
});
|
222
|
+
},
|
223
|
+
|
224
|
+
/*
|
225
|
+
Merges all properties of object `b` into object `a`.
|
226
|
+
`b.property` overwrites a.property`
|
227
|
+
*/
|
228
|
+
merge: function(a, b) {
|
229
|
+
var _new = {};
|
230
|
+
for(var name in a) {
|
231
|
+
if(a.hasOwnProperty(name)) {
|
232
|
+
_new[name] = a[name];
|
233
|
+
}
|
234
|
+
};
|
235
|
+
for(var name in b) {
|
236
|
+
if(b.hasOwnProperty(name)) {
|
237
|
+
_new[name] = b[name];
|
238
|
+
}
|
239
|
+
};
|
240
|
+
return _new;
|
241
|
+
},
|
242
|
+
|
243
|
+
// by @langalex, support for arrays of strings
|
244
|
+
create_context: function(_context) {
|
245
|
+
if(this.is_object(_context)) {
|
246
|
+
return _context;
|
247
|
+
} else if(this.pragmas["IMPLICIT-ITERATOR"]) {
|
248
|
+
var iterator = this.pragmas["IMPLICIT-ITERATOR"].iterator || ".";
|
249
|
+
var ctx = {};
|
250
|
+
ctx[iterator] = _context
|
251
|
+
return ctx;
|
252
|
+
}
|
253
|
+
},
|
254
|
+
|
255
|
+
is_object: function(a) {
|
256
|
+
return a && typeof a == "object";
|
257
|
+
},
|
258
|
+
|
259
|
+
is_array: function(a) {
|
260
|
+
return Object.prototype.toString.call(a) === '[object Array]';
|
261
|
+
},
|
262
|
+
|
263
|
+
/*
|
264
|
+
Gets rid of leading and trailing whitespace
|
265
|
+
*/
|
266
|
+
trim: function(s) {
|
267
|
+
return s.replace(/^\s*|\s*$/g, "");
|
268
|
+
},
|
269
|
+
|
270
|
+
/*
|
271
|
+
Why, why, why? Because IE. Cry, cry cry.
|
272
|
+
*/
|
273
|
+
map: function(array, fn) {
|
274
|
+
if (typeof array.map == "function") {
|
275
|
+
return array.map(fn)
|
276
|
+
} else {
|
277
|
+
var r = [];
|
278
|
+
var l = array.length;
|
279
|
+
for(i=0;i<l;i++) {
|
280
|
+
r.push(fn(array[i]));
|
281
|
+
}
|
282
|
+
return r;
|
283
|
+
}
|
284
|
+
}
|
285
|
+
};
|
286
|
+
|
287
|
+
return({
|
288
|
+
name: "mustache.js",
|
289
|
+
version: "0.2.3-dev",
|
290
|
+
|
291
|
+
/*
|
292
|
+
Turns a template and view into HTML
|
293
|
+
*/
|
294
|
+
to_html: function(template, view, partials, send_fun) {
|
295
|
+
var renderer = new Renderer();
|
296
|
+
if(send_fun) {
|
297
|
+
renderer.send = send_fun;
|
298
|
+
}
|
299
|
+
renderer.render(template, view, partials);
|
300
|
+
if(!send_fun) {
|
301
|
+
return renderer.buffer.join("\n");
|
302
|
+
}
|
303
|
+
}
|
304
|
+
});
|
305
|
+
}();
|
data/lib/couch/version.rb
CHANGED
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 1
|
8
|
-
-
|
9
|
-
version: 0.1.
|
8
|
+
- 2
|
9
|
+
version: 0.1.2
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Johannes J. Schmidt
|
@@ -112,6 +112,7 @@ files:
|
|
112
112
|
- lib/couch/generators/application/templates/_id.js
|
113
113
|
- lib/couch/generators/application/templates/couchrc
|
114
114
|
- lib/couch/generators/application/templates/gitignore
|
115
|
+
- lib/couch/generators/application/templates/lib/mustache.js
|
115
116
|
- lib/couch/generators/application/templates/validate_doc_update.js
|
116
117
|
- lib/couch/generators/base.rb
|
117
118
|
- lib/couch/generators/list/USAGE
|