poirot 0.0.3 → 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.
- data/lib/poirot/asset_helper.rb +19 -6
- data/lib/poirot/handler.rb +1 -0
- data/lib/poirot/version.rb +1 -1
- data/lib/poirot/view.rb +33 -6
- data/vendor/assets/javascripts/poirot/mustache.js +135 -38
- data/vendor/assets/javascripts/poirot/poirot.js +9 -4
- metadata +41 -59
data/lib/poirot/asset_helper.rb
CHANGED
@@ -2,13 +2,27 @@ module Poirot
|
|
2
2
|
module AssetHelper
|
3
3
|
def template_include_tag(*sources)
|
4
4
|
sources.collect do |source|
|
5
|
-
template = File.open(
|
6
|
-
content_tag :script, template.read.html_safe, :type => "text/mustache", :id => "#{source.parameterize.dasherize}-template"
|
5
|
+
template = File.open(resolve_partial_path(source), "rb")
|
6
|
+
content_tag :script, template.read.html_safe, :type => "text/mustache", :id => "#{template_name(source).parameterize.dasherize}-template"
|
7
7
|
end.join("\n").html_safe
|
8
8
|
end
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
def is_absolute_path?(source)
|
13
|
+
source.to_s =~ /^\//
|
14
|
+
end
|
15
|
+
|
16
|
+
def template_name(source)
|
17
|
+
if is_absolute_path?(source)
|
18
|
+
source.to_s.split('/').last
|
19
|
+
else
|
20
|
+
source
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def resolve_partial_path(source)
|
25
|
+
if is_absolute_path?(source)
|
12
26
|
segments = source.to_s.split('/')
|
13
27
|
partial_name = "_#{segments.pop}.html.mustache"
|
14
28
|
segments << partial_name
|
@@ -17,6 +31,5 @@ module Poirot
|
|
17
31
|
Rails.root.join('app/views', controller_name, "_#{source}.html.mustache")
|
18
32
|
end
|
19
33
|
end
|
20
|
-
|
21
34
|
end
|
22
35
|
end
|
data/lib/poirot/handler.rb
CHANGED
data/lib/poirot/version.rb
CHANGED
data/lib/poirot/view.rb
CHANGED
@@ -3,18 +3,42 @@ module Poirot
|
|
3
3
|
|
4
4
|
def initialize(view_context, template_source)
|
5
5
|
@view_context = view_context
|
6
|
+
@params = view_context.params || {}
|
6
7
|
self.template = template_source
|
7
8
|
assign_variables!
|
8
9
|
end
|
9
10
|
|
11
|
+
self.template_extension = 'html.mustache'
|
12
|
+
|
13
|
+
def self.inherited(view_class)
|
14
|
+
self.template_path = Rails.root.join('app', 'views', view_class.name.split('::').first.downcase)
|
15
|
+
end
|
16
|
+
|
10
17
|
def respond_to?(method_sym, include_private = false)
|
11
|
-
if view_context.respond_to?(method_sym)
|
18
|
+
if view_context.respond_to?(method_sym)
|
12
19
|
true
|
13
20
|
else
|
14
21
|
super
|
15
22
|
end
|
16
23
|
end
|
17
24
|
|
25
|
+
def render_buffer(buffer)
|
26
|
+
self.render(buffer, context).html_safe
|
27
|
+
end
|
28
|
+
|
29
|
+
def include_partial(name)
|
30
|
+
path = ["app/views", controller_name]
|
31
|
+
path += name.split("/")
|
32
|
+
path.delete(nil)
|
33
|
+
path.last.replace("_#{path.last}.html.mustache")
|
34
|
+
|
35
|
+
filename = path.join("/")
|
36
|
+
|
37
|
+
Dir.chdir(Rails.root) do
|
38
|
+
render_buffer(File.read(filename))
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
18
42
|
def method_missing(method_name, *args, &block)
|
19
43
|
instance_var = instance_variable_get("@#{method_name}")
|
20
44
|
if defined?(instance_var) && args.empty?
|
@@ -27,6 +51,7 @@ module Poirot
|
|
27
51
|
private
|
28
52
|
|
29
53
|
attr_reader :view_context
|
54
|
+
attr_reader :params
|
30
55
|
|
31
56
|
def assign_variables!
|
32
57
|
variables = view_context.instance_variable_names.select{|name| name =~ /^@[^_]/}
|
@@ -36,12 +61,14 @@ module Poirot
|
|
36
61
|
self[name.tr('@','').to_sym] = instance_var
|
37
62
|
end
|
38
63
|
|
39
|
-
|
40
|
-
|
64
|
+
if Rails.version >= "3.1"
|
65
|
+
# get the locals from the view context, is there a better way?
|
66
|
+
locals = view_context.send(:view_renderer).send(:_partial_renderer).instance_variable_get("@locals") || {}
|
41
67
|
|
42
|
-
|
43
|
-
|
44
|
-
|
68
|
+
locals.each do |name, val|
|
69
|
+
instance_variable_set("@#{name}", val)
|
70
|
+
self[name] = val
|
71
|
+
end
|
45
72
|
end
|
46
73
|
end
|
47
74
|
end
|
@@ -5,6 +5,7 @@
|
|
5
5
|
*/
|
6
6
|
|
7
7
|
var Mustache = function() {
|
8
|
+
var regexCache = {};
|
8
9
|
var Renderer = function() {};
|
9
10
|
|
10
11
|
Renderer.prototype = {
|
@@ -34,13 +35,22 @@ var Mustache = function() {
|
|
34
35
|
}
|
35
36
|
}
|
36
37
|
|
38
|
+
// get the pragmas together
|
37
39
|
template = this.render_pragmas(template);
|
40
|
+
|
41
|
+
// render the template
|
38
42
|
var html = this.render_section(template, context, partials);
|
39
|
-
|
40
|
-
|
43
|
+
|
44
|
+
// render_section did not find any sections, we still need to render the tags
|
45
|
+
if (html === false) {
|
46
|
+
html = this.render_tags(template, context, partials, in_recursion);
|
41
47
|
}
|
42
48
|
|
43
|
-
|
49
|
+
if (in_recursion) {
|
50
|
+
return html;
|
51
|
+
} else {
|
52
|
+
this.sendLines(html);
|
53
|
+
}
|
44
54
|
},
|
45
55
|
|
46
56
|
/*
|
@@ -52,6 +62,15 @@ var Mustache = function() {
|
|
52
62
|
}
|
53
63
|
},
|
54
64
|
|
65
|
+
sendLines: function(text) {
|
66
|
+
if (text) {
|
67
|
+
var lines = text.split("\n");
|
68
|
+
for (var i = 0; i < lines.length; i++) {
|
69
|
+
this.send(lines[i]);
|
70
|
+
}
|
71
|
+
}
|
72
|
+
},
|
73
|
+
|
55
74
|
/*
|
56
75
|
Looks for %PRAGMAS
|
57
76
|
*/
|
@@ -62,11 +81,13 @@ var Mustache = function() {
|
|
62
81
|
}
|
63
82
|
|
64
83
|
var that = this;
|
65
|
-
var regex =
|
66
|
-
|
84
|
+
var regex = this.getCachedRegex("render_pragmas", function(otag, ctag) {
|
85
|
+
return new RegExp(otag + "%([\\w-]+) ?([\\w]+=[\\w]+)?" + ctag, "g");
|
86
|
+
});
|
87
|
+
|
67
88
|
return template.replace(regex, function(match, pragma, options) {
|
68
89
|
if(!that.pragmas_implemented[pragma]) {
|
69
|
-
throw({message:
|
90
|
+
throw({message:
|
70
91
|
"This implementation of mustache doesn't understand the '" +
|
71
92
|
pragma + "' pragma"});
|
72
93
|
}
|
@@ -99,45 +120,74 @@ var Mustache = function() {
|
|
99
120
|
*/
|
100
121
|
render_section: function(template, context, partials) {
|
101
122
|
if(!this.includes("#", template) && !this.includes("^", template)) {
|
102
|
-
|
123
|
+
// did not render anything, there were no sections
|
124
|
+
return false;
|
103
125
|
}
|
104
126
|
|
105
127
|
var that = this;
|
106
|
-
|
107
|
-
var regex =
|
108
|
-
|
109
|
-
|
128
|
+
|
129
|
+
var regex = this.getCachedRegex("render_section", function(otag, ctag) {
|
130
|
+
// This regex matches _the first_ section ({{#foo}}{{/foo}}), and captures the remainder
|
131
|
+
return new RegExp(
|
132
|
+
"^([\\s\\S]*?)" + // all the crap at the beginning that is not {{*}} ($1)
|
133
|
+
|
134
|
+
otag + // {{
|
135
|
+
"(\\^|\\#)\\s*(.+)\\s*" + // #foo (# == $2, foo == $3)
|
136
|
+
ctag + // }}
|
137
|
+
|
138
|
+
"\n*([\\s\\S]*?)" + // between the tag ($2). leading newlines are dropped
|
139
|
+
|
140
|
+
otag + // {{
|
141
|
+
"\\/\\s*\\3\\s*" + // /foo (backreference to the opening tag).
|
142
|
+
ctag + // }}
|
143
|
+
|
144
|
+
"\\s*([\\s\\S]*)$", // everything else in the string ($4). leading whitespace is dropped.
|
145
|
+
|
146
|
+
"g");
|
147
|
+
});
|
148
|
+
|
110
149
|
|
111
150
|
// for each {{#foo}}{{/foo}} section do...
|
112
|
-
return template.replace(regex, function(match, type, name, content) {
|
113
|
-
|
114
|
-
|
115
|
-
|
151
|
+
return template.replace(regex, function(match, before, type, name, content, after) {
|
152
|
+
// before contains only tags, no sections
|
153
|
+
var renderedBefore = before ? that.render_tags(before, context, partials, true) : "",
|
154
|
+
|
155
|
+
// after may contain both sections and tags, so use full rendering function
|
156
|
+
renderedAfter = after ? that.render(after, context, partials, true) : "",
|
157
|
+
|
158
|
+
// will be computed below
|
159
|
+
renderedContent,
|
160
|
+
|
161
|
+
value = that.find(name, context);
|
162
|
+
|
163
|
+
if (type === "^") { // inverted section
|
164
|
+
if (!value || that.is_array(value) && value.length === 0) {
|
116
165
|
// false or empty list, render it
|
117
|
-
|
166
|
+
renderedContent = that.render(content, context, partials, true);
|
118
167
|
} else {
|
119
|
-
|
168
|
+
renderedContent = "";
|
120
169
|
}
|
121
|
-
} else if(type
|
122
|
-
if(that.is_array(value)) { // Enumerable, Let's loop!
|
123
|
-
|
124
|
-
return that.render(content, that.create_context(row),
|
125
|
-
partials, true);
|
170
|
+
} else if (type === "#") { // normal section
|
171
|
+
if (that.is_array(value)) { // Enumerable, Let's loop!
|
172
|
+
renderedContent = that.map(value, function(row) {
|
173
|
+
return that.render(content, that.create_context(row), partials, true);
|
126
174
|
}).join("");
|
127
|
-
} else if(that.is_object(value)) { // Object, Use it as subcontext!
|
128
|
-
|
175
|
+
} else if (that.is_object(value)) { // Object, Use it as subcontext!
|
176
|
+
renderedContent = that.render(content, that.create_context(value),
|
129
177
|
partials, true);
|
130
|
-
} else if(typeof value === "function") {
|
178
|
+
} else if (typeof value === "function") {
|
131
179
|
// higher order section
|
132
|
-
|
180
|
+
renderedContent = value.call(context, content, function(text) {
|
133
181
|
return that.render(text, context, partials, true);
|
134
182
|
});
|
135
|
-
} else if(value) { // boolean section
|
136
|
-
|
183
|
+
} else if (value) { // boolean section
|
184
|
+
renderedContent = that.render(content, context, partials, true);
|
137
185
|
} else {
|
138
|
-
|
186
|
+
renderedContent = "";
|
139
187
|
}
|
140
188
|
}
|
189
|
+
|
190
|
+
return renderedBefore + renderedContent + renderedAfter;
|
141
191
|
});
|
142
192
|
},
|
143
193
|
|
@@ -148,9 +198,12 @@ var Mustache = function() {
|
|
148
198
|
// tit for tat
|
149
199
|
var that = this;
|
150
200
|
|
201
|
+
|
202
|
+
|
151
203
|
var new_regex = function() {
|
152
|
-
return
|
153
|
-
|
204
|
+
return that.getCachedRegex("render_tags", function(otag, ctag) {
|
205
|
+
return new RegExp(otag + "(=|!|>|\\{|%)?([^\\/#\\^]+?)\\1?" + ctag + "+", "g");
|
206
|
+
});
|
154
207
|
};
|
155
208
|
|
156
209
|
var regex = new_regex();
|
@@ -216,10 +269,20 @@ var Mustache = function() {
|
|
216
269
|
}
|
217
270
|
|
218
271
|
var value;
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
272
|
+
|
273
|
+
// check for dot notation eg. foo.bar
|
274
|
+
if(name.match(/([a-z_]+)\./ig)){
|
275
|
+
var childValue = this.walk_context(name, context);
|
276
|
+
if(is_kinda_truthy(childValue)) {
|
277
|
+
value = childValue;
|
278
|
+
}
|
279
|
+
}
|
280
|
+
else{
|
281
|
+
if(is_kinda_truthy(context[name])) {
|
282
|
+
value = context[name];
|
283
|
+
} else if(is_kinda_truthy(this.context[name])) {
|
284
|
+
value = this.context[name];
|
285
|
+
}
|
223
286
|
}
|
224
287
|
|
225
288
|
if(typeof value === "function") {
|
@@ -232,6 +295,22 @@ var Mustache = function() {
|
|
232
295
|
return "";
|
233
296
|
},
|
234
297
|
|
298
|
+
walk_context: function(name, context){
|
299
|
+
var path = name.split('.');
|
300
|
+
// if the var doesn't exist in current context, check the top level context
|
301
|
+
var value_context = (context[path[0]] != undefined) ? context : this.context;
|
302
|
+
var value = value_context[path.shift()];
|
303
|
+
while(value != undefined && path.length > 0){
|
304
|
+
value_context = value;
|
305
|
+
value = value[path.shift()];
|
306
|
+
}
|
307
|
+
// if the value is a function, call it, binding the correct context
|
308
|
+
if(typeof value === "function") {
|
309
|
+
return value.apply(value_context);
|
310
|
+
}
|
311
|
+
return value;
|
312
|
+
},
|
313
|
+
|
235
314
|
// Utility methods
|
236
315
|
|
237
316
|
/* includes tag */
|
@@ -247,7 +326,6 @@ var Mustache = function() {
|
|
247
326
|
return s.replace(/&(?!\w+;)|["'<>\\]/g, function(s) {
|
248
327
|
switch(s) {
|
249
328
|
case "&": return "&";
|
250
|
-
case "\\": return "\\\\";
|
251
329
|
case '"': return '"';
|
252
330
|
case "'": return ''';
|
253
331
|
case "<": return "<";
|
@@ -301,12 +379,31 @@ var Mustache = function() {
|
|
301
379
|
}
|
302
380
|
return r;
|
303
381
|
}
|
382
|
+
},
|
383
|
+
|
384
|
+
getCachedRegex: function(name, generator) {
|
385
|
+
var byOtag = regexCache[this.otag];
|
386
|
+
if (!byOtag) {
|
387
|
+
byOtag = regexCache[this.otag] = {};
|
388
|
+
}
|
389
|
+
|
390
|
+
var byCtag = byOtag[this.ctag];
|
391
|
+
if (!byCtag) {
|
392
|
+
byCtag = byOtag[this.ctag] = {};
|
393
|
+
}
|
394
|
+
|
395
|
+
var regex = byCtag[name];
|
396
|
+
if (!regex) {
|
397
|
+
regex = byCtag[name] = generator(this.otag, this.ctag);
|
398
|
+
}
|
399
|
+
|
400
|
+
return regex;
|
304
401
|
}
|
305
402
|
};
|
306
403
|
|
307
404
|
return({
|
308
405
|
name: "mustache.js",
|
309
|
-
version: "0.
|
406
|
+
version: "0.4.0-dev",
|
310
407
|
|
311
408
|
/*
|
312
409
|
Turns a template and view into HTML
|
@@ -316,7 +413,7 @@ var Mustache = function() {
|
|
316
413
|
if(send_fun) {
|
317
414
|
renderer.send = send_fun;
|
318
415
|
}
|
319
|
-
renderer.render(template, view, partials);
|
416
|
+
renderer.render(template, view || {}, partials);
|
320
417
|
if(!send_fun) {
|
321
418
|
return renderer.buffer.join("\n");
|
322
419
|
}
|
@@ -1,7 +1,14 @@
|
|
1
1
|
var poirot = (function ($) {
|
2
2
|
|
3
|
+
var viewFactory = function (template, partials) {
|
4
|
+
return function (data) {
|
5
|
+
return $(Mustache.to_html(template, data, partials))
|
6
|
+
}
|
7
|
+
}
|
8
|
+
|
3
9
|
var poirot = {
|
4
|
-
partials: {}
|
10
|
+
partials: {},
|
11
|
+
_viewFactory: viewFactory
|
5
12
|
}
|
6
13
|
|
7
14
|
$(document).ready(function () {
|
@@ -13,9 +20,7 @@ var poirot = (function ($) {
|
|
13
20
|
|
14
21
|
poirot.partials[methodName] = template
|
15
22
|
|
16
|
-
poirot[methodName] =
|
17
|
-
return $(Mustache.to_html(template, presenter, poirot.partials))
|
18
|
-
}
|
23
|
+
poirot[methodName] = poirot._viewFactory(template, poirot.partials)
|
19
24
|
})
|
20
25
|
})
|
21
26
|
|
metadata
CHANGED
@@ -1,57 +1,46 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: poirot
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
|
6
|
-
- 0
|
7
|
-
- 0
|
8
|
-
- 3
|
9
|
-
version: 0.0.3
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
prerelease:
|
10
6
|
platform: ruby
|
11
|
-
authors:
|
7
|
+
authors:
|
12
8
|
- Oliver Nightingale
|
13
9
|
- Mark Evans
|
14
10
|
autorequire:
|
15
11
|
bindir: bin
|
16
12
|
cert_chain: []
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
dependencies:
|
21
|
-
- !ruby/object:Gem::Dependency
|
13
|
+
date: 2012-01-04 00:00:00.000000000 Z
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
22
16
|
name: rails
|
23
|
-
|
24
|
-
|
25
|
-
requirements:
|
26
|
-
- -
|
27
|
-
- !ruby/object:Gem::Version
|
28
|
-
|
29
|
-
- 3
|
30
|
-
version: "3"
|
17
|
+
requirement: &70170133189960 !ruby/object:Gem::Requirement
|
18
|
+
none: false
|
19
|
+
requirements:
|
20
|
+
- - ! '>'
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: '3'
|
31
23
|
type: :runtime
|
32
|
-
version_requirements: *id001
|
33
|
-
- !ruby/object:Gem::Dependency
|
34
|
-
name: mustache
|
35
24
|
prerelease: false
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
25
|
+
version_requirements: *70170133189960
|
26
|
+
- !ruby/object:Gem::Dependency
|
27
|
+
name: mustache
|
28
|
+
requirement: &70170133189380 !ruby/object:Gem::Requirement
|
29
|
+
none: false
|
30
|
+
requirements:
|
31
|
+
- - ! '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
43
34
|
type: :runtime
|
44
|
-
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: *70170133189380
|
45
37
|
description: mustaches are cool
|
46
|
-
email:
|
38
|
+
email:
|
47
39
|
- oliver.nightingale1@gmail.com
|
48
40
|
executables: []
|
49
|
-
|
50
41
|
extensions: []
|
51
|
-
|
52
42
|
extra_rdoc_files: []
|
53
|
-
|
54
|
-
files:
|
43
|
+
files:
|
55
44
|
- .gitignore
|
56
45
|
- Gemfile
|
57
46
|
- Gemfile.lock
|
@@ -67,35 +56,28 @@ files:
|
|
67
56
|
- vendor/assets/javascripts/poirot/index.js
|
68
57
|
- vendor/assets/javascripts/poirot/mustache.js
|
69
58
|
- vendor/assets/javascripts/poirot/poirot.js
|
70
|
-
has_rdoc: true
|
71
59
|
homepage: http://rubygems.org/gems/poirot
|
72
60
|
licenses: []
|
73
|
-
|
74
61
|
post_install_message:
|
75
62
|
rdoc_options: []
|
76
|
-
|
77
|
-
require_paths:
|
63
|
+
require_paths:
|
78
64
|
- lib
|
79
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
requirements:
|
88
|
-
- -
|
89
|
-
- !ruby/object:Gem::Version
|
90
|
-
|
91
|
-
- 0
|
92
|
-
version: "0"
|
65
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
66
|
+
none: false
|
67
|
+
requirements:
|
68
|
+
- - ! '>='
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
version: '0'
|
71
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
72
|
+
none: false
|
73
|
+
requirements:
|
74
|
+
- - ! '>='
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: '0'
|
93
77
|
requirements: []
|
94
|
-
|
95
78
|
rubyforge_project: poirot
|
96
|
-
rubygems_version: 1.
|
79
|
+
rubygems_version: 1.8.11
|
97
80
|
signing_key:
|
98
81
|
specification_version: 3
|
99
82
|
summary: mustaches
|
100
83
|
test_files: []
|
101
|
-
|