dust-sinatra 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +2 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +97 -0
- data/README.markdown +69 -0
- data/Rakefile +1 -0
- data/dust-sinatra.gemspec +24 -0
- data/lib/dust-sinatra.rb +20 -0
- data/lib/dust-sinatra/sinatra/base.rb +10 -0
- data/lib/dust-sinatra/sinatra/dust_template.rb +40 -0
- data/lib/dust-sinatra/sinatra/helpers.rb +7 -0
- data/lib/dust-sinatra/version.rb +5 -0
- data/vendor/assets/javascripts/dust-core.js +522 -0
- data/vendor/assets/javascripts/dust-core.min.js +21 -0
- data/vendor/assets/javascripts/dust-full-for-compile.js +3209 -0
- data/vendor/assets/javascripts/dust-full.js +3209 -0
- data/vendor/assets/javascripts/dust-full.min.js +61 -0
- metadata +96 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,97 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
dust-rails (0.1.0)
|
5
|
+
execjs
|
6
|
+
rails (~> 3.1.0)
|
7
|
+
tilt
|
8
|
+
|
9
|
+
GEM
|
10
|
+
remote: http://rubygems.org/
|
11
|
+
specs:
|
12
|
+
actionmailer (3.1.3)
|
13
|
+
actionpack (= 3.1.3)
|
14
|
+
mail (~> 2.3.0)
|
15
|
+
actionpack (3.1.3)
|
16
|
+
activemodel (= 3.1.3)
|
17
|
+
activesupport (= 3.1.3)
|
18
|
+
builder (~> 3.0.0)
|
19
|
+
erubis (~> 2.7.0)
|
20
|
+
i18n (~> 0.6)
|
21
|
+
rack (~> 1.3.5)
|
22
|
+
rack-cache (~> 1.1)
|
23
|
+
rack-mount (~> 0.8.2)
|
24
|
+
rack-test (~> 0.6.1)
|
25
|
+
sprockets (~> 2.0.3)
|
26
|
+
activemodel (3.1.3)
|
27
|
+
activesupport (= 3.1.3)
|
28
|
+
builder (~> 3.0.0)
|
29
|
+
i18n (~> 0.6)
|
30
|
+
activerecord (3.1.3)
|
31
|
+
activemodel (= 3.1.3)
|
32
|
+
activesupport (= 3.1.3)
|
33
|
+
arel (~> 2.2.1)
|
34
|
+
tzinfo (~> 0.3.29)
|
35
|
+
activeresource (3.1.3)
|
36
|
+
activemodel (= 3.1.3)
|
37
|
+
activesupport (= 3.1.3)
|
38
|
+
activesupport (3.1.3)
|
39
|
+
multi_json (~> 1.0)
|
40
|
+
arel (2.2.1)
|
41
|
+
builder (3.0.0)
|
42
|
+
erubis (2.7.0)
|
43
|
+
execjs (1.2.12)
|
44
|
+
multi_json (~> 1.0)
|
45
|
+
hike (1.2.1)
|
46
|
+
i18n (0.6.0)
|
47
|
+
json (1.6.3)
|
48
|
+
mail (2.3.0)
|
49
|
+
i18n (>= 0.4.0)
|
50
|
+
mime-types (~> 1.16)
|
51
|
+
treetop (~> 1.4.8)
|
52
|
+
mime-types (1.17.2)
|
53
|
+
multi_json (1.0.4)
|
54
|
+
polyglot (0.3.3)
|
55
|
+
rack (1.3.5)
|
56
|
+
rack-cache (1.1)
|
57
|
+
rack (>= 0.4)
|
58
|
+
rack-mount (0.8.3)
|
59
|
+
rack (>= 1.0.0)
|
60
|
+
rack-ssl (1.3.2)
|
61
|
+
rack
|
62
|
+
rack-test (0.6.1)
|
63
|
+
rack (>= 1.0)
|
64
|
+
rails (3.1.3)
|
65
|
+
actionmailer (= 3.1.3)
|
66
|
+
actionpack (= 3.1.3)
|
67
|
+
activerecord (= 3.1.3)
|
68
|
+
activeresource (= 3.1.3)
|
69
|
+
activesupport (= 3.1.3)
|
70
|
+
bundler (~> 1.0)
|
71
|
+
railties (= 3.1.3)
|
72
|
+
railties (3.1.3)
|
73
|
+
actionpack (= 3.1.3)
|
74
|
+
activesupport (= 3.1.3)
|
75
|
+
rack-ssl (~> 1.3.2)
|
76
|
+
rake (>= 0.8.7)
|
77
|
+
rdoc (~> 3.4)
|
78
|
+
thor (~> 0.14.6)
|
79
|
+
rake (0.9.2.2)
|
80
|
+
rdoc (3.12)
|
81
|
+
json (~> 1.4)
|
82
|
+
sprockets (2.0.3)
|
83
|
+
hike (~> 1.2)
|
84
|
+
rack (~> 1.0)
|
85
|
+
tilt (!= 1.3.0, ~> 1.1)
|
86
|
+
thor (0.14.6)
|
87
|
+
tilt (1.3.3)
|
88
|
+
treetop (1.4.10)
|
89
|
+
polyglot
|
90
|
+
polyglot (>= 0.3.1)
|
91
|
+
tzinfo (0.3.31)
|
92
|
+
|
93
|
+
PLATFORMS
|
94
|
+
ruby
|
95
|
+
|
96
|
+
DEPENDENCIES
|
97
|
+
dust-rails!
|
data/README.markdown
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
# Dust-Sinatra
|
2
|
+
|
3
|
+
This gem adds the Dust template and a corresponding assets engine to sinatra applications.
|
4
|
+
|
5
|
+
For detailed information about Dust, visit <http://akdubya.github.com/dustjs/>
|
6
|
+
|
7
|
+
## Installing
|
8
|
+
|
9
|
+
Add the following line to your Gemfile:
|
10
|
+
|
11
|
+
gem 'dust-sinatra'
|
12
|
+
|
13
|
+
Update your bundle:
|
14
|
+
|
15
|
+
bundle install
|
16
|
+
|
17
|
+
## Usage
|
18
|
+
|
19
|
+
Place individual Dust template file in their own file with `template_name.js.dust` extension.
|
20
|
+
|
21
|
+
```javascript
|
22
|
+
/* views/js/templates/demo.js.dust */
|
23
|
+
|
24
|
+
Hello {name}! You have {count} new messages.
|
25
|
+
```
|
26
|
+
|
27
|
+
Which will be compiled and rendered as:
|
28
|
+
|
29
|
+
```javascript
|
30
|
+
(function(){dust.register("demo",body_0);function body_0(chk,ctx){return chk.write("Hello ").reference(ctx.get("name"),ctx,"h").write("! You have ").reference(ctx.get("count"),ctx,"h").write(" new messages.");}return body_0;})();
|
31
|
+
```
|
32
|
+
|
33
|
+
|
34
|
+
Dust-sinatra resolves the name of the template out of request path of each template file.
|
35
|
+
Relative path starts from `/` by default.
|
36
|
+
|
37
|
+
/demo1.js -> demo1
|
38
|
+
/demos/demo2.js -> demos/demo2
|
39
|
+
|
40
|
+
If you want to change the default root path of template files, add following configuration:
|
41
|
+
|
42
|
+
```ruby
|
43
|
+
module YourApp
|
44
|
+
class YourApplication < Sinatra::Base
|
45
|
+
configure do
|
46
|
+
Dust.config.template_root = '/your_path_to_templates/'
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
```
|
51
|
+
|
52
|
+
In your html files, load `dust-core` and your own template files.
|
53
|
+
You are also able to use `require-js` or `sinatra-assetpack` to include the files.
|
54
|
+
|
55
|
+
```html
|
56
|
+
<!-- index.html -->
|
57
|
+
...
|
58
|
+
<script src="js/dust-core.js"></script>
|
59
|
+
<script src="js/dust_template_path.js"></script>
|
60
|
+
```
|
61
|
+
|
62
|
+
```javascript
|
63
|
+
...
|
64
|
+
dust.render("demo", {name: "Fred", count: 10}, function(err, out) {
|
65
|
+
console.log(out);
|
66
|
+
});
|
67
|
+
```
|
68
|
+
|
69
|
+
All done. Your template files will be compiled and registered.
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'bundler/gem_tasks'
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "dust-sinatra/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "dust-sinatra"
|
7
|
+
s.version = Dust::Sinatra::VERSION
|
8
|
+
s.authors = ["Sean Lee", "Hoseong Hwang"]
|
9
|
+
s.email = ["ssowonny@gmail.com", "thefron@wafflestudio.com"]
|
10
|
+
s.homepage = "https://github.com/ssowonny/dust-sinatra"
|
11
|
+
s.summary = %q{Use dust.js with sinatra}
|
12
|
+
s.description = %q{This gem makes you dust.js easy to use with sinatra.}
|
13
|
+
|
14
|
+
s.rubyforge_project = "dust-sinatra"
|
15
|
+
|
16
|
+
s.add_dependency('sinatra')
|
17
|
+
s.add_dependency('tilt')
|
18
|
+
s.add_dependency('execjs')
|
19
|
+
|
20
|
+
s.files = `git ls-files`.split("\n")
|
21
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
22
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
23
|
+
s.require_paths = ["lib"]
|
24
|
+
end
|
data/lib/dust-sinatra.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
require "dust-sinatra/version"
|
2
|
+
require "dust-sinatra/sinatra/helpers.rb"
|
3
|
+
require "dust-sinatra/sinatra/dust_template.rb"
|
4
|
+
require "dust-sinatra/sinatra/base.rb"
|
5
|
+
|
6
|
+
module Dust
|
7
|
+
|
8
|
+
class Config
|
9
|
+
attr_accessor :template_root
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.config
|
13
|
+
@@config ||= Config.new
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.configure
|
17
|
+
yield self.config
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'tilt'
|
2
|
+
require 'execjs'
|
3
|
+
|
4
|
+
module Dust
|
5
|
+
module Sinatra
|
6
|
+
|
7
|
+
module Source
|
8
|
+
def self.path
|
9
|
+
@path ||= File.expand_path('../../../../vendor/assets/javascripts/dust-full-for-compile.js', __FILE__)
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.contents
|
13
|
+
@contents ||= File.read(path)
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.context
|
17
|
+
@context ||= ExecJS.compile(contents)
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
class DustTemplate < ::Tilt::Template
|
23
|
+
|
24
|
+
def self.default_mime_type
|
25
|
+
'application/javascript'
|
26
|
+
end
|
27
|
+
|
28
|
+
def prepare
|
29
|
+
end
|
30
|
+
|
31
|
+
def evaluate(scope, locals, &block)
|
32
|
+
template_root = Dust.config.template_root
|
33
|
+
template_name = scope.env["REQUEST_PATH"].split(template_root).last.split('.',2).first
|
34
|
+
Source.context.call("dust.compile", data, template_name)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
|
@@ -0,0 +1,522 @@
|
|
1
|
+
//
|
2
|
+
// Dust - Asynchronous Templating v0.3.0
|
3
|
+
// http://akdubya.github.com/dustjs
|
4
|
+
//
|
5
|
+
// Copyright (c) 2010, Aleksander Williams
|
6
|
+
// Released under the MIT License.
|
7
|
+
//
|
8
|
+
|
9
|
+
var dust = {};
|
10
|
+
|
11
|
+
(function(dust) {
|
12
|
+
|
13
|
+
dust.cache = {};
|
14
|
+
|
15
|
+
dust.register = function(name, tmpl) {
|
16
|
+
if (!name) return;
|
17
|
+
dust.cache[name] = tmpl;
|
18
|
+
};
|
19
|
+
|
20
|
+
dust.render = function(name, context, callback) {
|
21
|
+
var chunk = new Stub(callback).head;
|
22
|
+
dust.load(name, chunk, Context.wrap(context)).end();
|
23
|
+
};
|
24
|
+
|
25
|
+
dust.stream = function(name, context) {
|
26
|
+
var stream = new Stream();
|
27
|
+
dust.nextTick(function() {
|
28
|
+
dust.load(name, stream.head, Context.wrap(context)).end();
|
29
|
+
});
|
30
|
+
return stream;
|
31
|
+
};
|
32
|
+
|
33
|
+
dust.renderSource = function(source, context, callback) {
|
34
|
+
return dust.compileFn(source)(context, callback);
|
35
|
+
};
|
36
|
+
|
37
|
+
dust.compileFn = function(source, name) {
|
38
|
+
var tmpl = dust.loadSource(dust.compile(source, name));
|
39
|
+
return function(context, callback) {
|
40
|
+
var master = callback ? new Stub(callback) : new Stream();
|
41
|
+
dust.nextTick(function() {
|
42
|
+
tmpl(master.head, Context.wrap(context)).end();
|
43
|
+
});
|
44
|
+
return master;
|
45
|
+
}
|
46
|
+
};
|
47
|
+
|
48
|
+
dust.load = function(name, chunk, context) {
|
49
|
+
var tmpl = dust.cache[name];
|
50
|
+
if (tmpl) {
|
51
|
+
return tmpl(chunk, context);
|
52
|
+
} else {
|
53
|
+
if (dust.onLoad) {
|
54
|
+
return chunk.map(function(chunk) {
|
55
|
+
dust.onLoad(name, function(err, src) {
|
56
|
+
if (err) return chunk.setError(err);
|
57
|
+
if (!dust.cache[name]) dust.loadSource(dust.compile(src, name));
|
58
|
+
dust.cache[name](chunk, context).end();
|
59
|
+
});
|
60
|
+
});
|
61
|
+
}
|
62
|
+
return chunk.setError(new Error("Template Not Found: " + name));
|
63
|
+
}
|
64
|
+
};
|
65
|
+
|
66
|
+
dust.loadSource = function(source, path) {
|
67
|
+
return eval(source);
|
68
|
+
};
|
69
|
+
|
70
|
+
if (Array.isArray) {
|
71
|
+
dust.isArray = Array.isArray;
|
72
|
+
} else {
|
73
|
+
dust.isArray = function(arr) {
|
74
|
+
return Object.prototype.toString.call(arr) == "[object Array]";
|
75
|
+
};
|
76
|
+
}
|
77
|
+
|
78
|
+
dust.nextTick = function(callback) {
|
79
|
+
setTimeout(callback, 0);
|
80
|
+
}
|
81
|
+
|
82
|
+
dust.isEmpty = function(value) {
|
83
|
+
if (dust.isArray(value) && !value.length) return true;
|
84
|
+
if (value === 0) return false;
|
85
|
+
return (!value);
|
86
|
+
};
|
87
|
+
|
88
|
+
dust.filter = function(string, auto, filters) {
|
89
|
+
if (filters) {
|
90
|
+
for (var i=0, len=filters.length; i<len; i++) {
|
91
|
+
var name = filters[i];
|
92
|
+
if (name === "s") {
|
93
|
+
auto = null;
|
94
|
+
} else {
|
95
|
+
string = dust.filters[name](string);
|
96
|
+
}
|
97
|
+
}
|
98
|
+
}
|
99
|
+
if (auto) {
|
100
|
+
string = dust.filters[auto](string);
|
101
|
+
}
|
102
|
+
return string;
|
103
|
+
};
|
104
|
+
|
105
|
+
dust.filters = {
|
106
|
+
h: function(value) { return dust.escapeHtml(value); },
|
107
|
+
j: function(value) { return dust.escapeJs(value); },
|
108
|
+
u: encodeURI,
|
109
|
+
uc: encodeURIComponent
|
110
|
+
}
|
111
|
+
|
112
|
+
function Context(stack, global, blocks) {
|
113
|
+
this.stack = stack;
|
114
|
+
this.global = global;
|
115
|
+
this.blocks = blocks;
|
116
|
+
}
|
117
|
+
|
118
|
+
dust.makeBase = function(global) {
|
119
|
+
return new Context(new Stack(), global);
|
120
|
+
}
|
121
|
+
|
122
|
+
Context.wrap = function(context) {
|
123
|
+
if (context instanceof Context) {
|
124
|
+
return context;
|
125
|
+
}
|
126
|
+
return new Context(new Stack(context));
|
127
|
+
}
|
128
|
+
|
129
|
+
Context.prototype.get = function(key) {
|
130
|
+
var ctx = this.stack, value;
|
131
|
+
|
132
|
+
while(ctx) {
|
133
|
+
if (ctx.isObject) {
|
134
|
+
value = ctx.head[key];
|
135
|
+
if (!(value === undefined)) {
|
136
|
+
return value;
|
137
|
+
}
|
138
|
+
}
|
139
|
+
ctx = ctx.tail;
|
140
|
+
}
|
141
|
+
return this.global ? this.global[key] : undefined;
|
142
|
+
};
|
143
|
+
|
144
|
+
Context.prototype.getPath = function(cur, down) {
|
145
|
+
var ctx = this.stack,
|
146
|
+
len = down.length;
|
147
|
+
|
148
|
+
if (cur && len === 0) return ctx.head;
|
149
|
+
if (!ctx.isObject) return undefined;
|
150
|
+
ctx = ctx.head;
|
151
|
+
var i = 0;
|
152
|
+
while(ctx && i < len) {
|
153
|
+
ctx = ctx[down[i]];
|
154
|
+
i++;
|
155
|
+
}
|
156
|
+
return ctx;
|
157
|
+
};
|
158
|
+
|
159
|
+
Context.prototype.push = function(head, idx, len) {
|
160
|
+
return new Context(new Stack(head, this.stack, idx, len), this.global, this.blocks);
|
161
|
+
};
|
162
|
+
|
163
|
+
Context.prototype.rebase = function(head) {
|
164
|
+
return new Context(new Stack(head), this.global, this.blocks);
|
165
|
+
};
|
166
|
+
|
167
|
+
Context.prototype.current = function() {
|
168
|
+
return this.stack.head;
|
169
|
+
};
|
170
|
+
|
171
|
+
Context.prototype.getBlock = function(key) {
|
172
|
+
var blocks = this.blocks;
|
173
|
+
|
174
|
+
if (!blocks) return;
|
175
|
+
var len = blocks.length, fn;
|
176
|
+
while (len--) {
|
177
|
+
fn = blocks[len][key];
|
178
|
+
if (fn) return fn;
|
179
|
+
}
|
180
|
+
}
|
181
|
+
|
182
|
+
Context.prototype.shiftBlocks = function(locals) {
|
183
|
+
var blocks = this.blocks;
|
184
|
+
|
185
|
+
if (locals) {
|
186
|
+
if (!blocks) {
|
187
|
+
newBlocks = [locals];
|
188
|
+
} else {
|
189
|
+
newBlocks = blocks.concat([locals]);
|
190
|
+
}
|
191
|
+
return new Context(this.stack, this.global, newBlocks);
|
192
|
+
}
|
193
|
+
return this;
|
194
|
+
}
|
195
|
+
|
196
|
+
function Stack(head, tail, idx, len) {
|
197
|
+
this.tail = tail;
|
198
|
+
this.isObject = !dust.isArray(head) && head && typeof head === "object";
|
199
|
+
this.head = head;
|
200
|
+
this.index = idx;
|
201
|
+
this.of = len;
|
202
|
+
}
|
203
|
+
|
204
|
+
function Stub(callback) {
|
205
|
+
this.head = new Chunk(this);
|
206
|
+
this.callback = callback;
|
207
|
+
this.out = '';
|
208
|
+
}
|
209
|
+
|
210
|
+
Stub.prototype.flush = function() {
|
211
|
+
var chunk = this.head;
|
212
|
+
|
213
|
+
while (chunk) {
|
214
|
+
if (chunk.flushable) {
|
215
|
+
this.out += chunk.data;
|
216
|
+
} else if (chunk.error) {
|
217
|
+
this.callback(chunk.error);
|
218
|
+
this.flush = function() {};
|
219
|
+
return;
|
220
|
+
} else {
|
221
|
+
return;
|
222
|
+
}
|
223
|
+
chunk = chunk.next;
|
224
|
+
this.head = chunk;
|
225
|
+
}
|
226
|
+
this.callback(null, this.out);
|
227
|
+
}
|
228
|
+
|
229
|
+
function Stream() {
|
230
|
+
this.head = new Chunk(this);
|
231
|
+
}
|
232
|
+
|
233
|
+
Stream.prototype.flush = function() {
|
234
|
+
var chunk = this.head;
|
235
|
+
|
236
|
+
while(chunk) {
|
237
|
+
if (chunk.flushable) {
|
238
|
+
this.emit('data', chunk.data);
|
239
|
+
} else if (chunk.error) {
|
240
|
+
this.emit('error', chunk.error);
|
241
|
+
this.flush = function() {};
|
242
|
+
return;
|
243
|
+
} else {
|
244
|
+
return;
|
245
|
+
}
|
246
|
+
chunk = chunk.next;
|
247
|
+
this.head = chunk;
|
248
|
+
}
|
249
|
+
this.emit('end');
|
250
|
+
}
|
251
|
+
|
252
|
+
Stream.prototype.emit = function(type, data) {
|
253
|
+
var events = this.events;
|
254
|
+
|
255
|
+
if (events && events[type]) {
|
256
|
+
events[type](data);
|
257
|
+
}
|
258
|
+
}
|
259
|
+
|
260
|
+
Stream.prototype.on = function(type, callback) {
|
261
|
+
if (!this.events) {
|
262
|
+
this.events = {};
|
263
|
+
}
|
264
|
+
this.events[type] = callback;
|
265
|
+
return this;
|
266
|
+
}
|
267
|
+
|
268
|
+
function Chunk(root, next, taps) {
|
269
|
+
this.root = root;
|
270
|
+
this.next = next;
|
271
|
+
this.data = '';
|
272
|
+
this.flushable = false;
|
273
|
+
this.taps = taps;
|
274
|
+
}
|
275
|
+
|
276
|
+
Chunk.prototype.write = function(data) {
|
277
|
+
var taps = this.taps;
|
278
|
+
|
279
|
+
if (taps) {
|
280
|
+
data = taps.go(data);
|
281
|
+
}
|
282
|
+
this.data += data;
|
283
|
+
return this;
|
284
|
+
}
|
285
|
+
|
286
|
+
Chunk.prototype.end = function(data) {
|
287
|
+
if (data) {
|
288
|
+
this.write(data);
|
289
|
+
}
|
290
|
+
this.flushable = true;
|
291
|
+
this.root.flush();
|
292
|
+
return this;
|
293
|
+
}
|
294
|
+
|
295
|
+
Chunk.prototype.map = function(callback) {
|
296
|
+
var cursor = new Chunk(this.root, this.next, this.taps),
|
297
|
+
branch = new Chunk(this.root, cursor, this.taps);
|
298
|
+
|
299
|
+
this.next = branch;
|
300
|
+
this.flushable = true;
|
301
|
+
callback(branch);
|
302
|
+
return cursor;
|
303
|
+
}
|
304
|
+
|
305
|
+
Chunk.prototype.tap = function(tap) {
|
306
|
+
var taps = this.taps;
|
307
|
+
|
308
|
+
if (taps) {
|
309
|
+
this.taps = taps.push(tap);
|
310
|
+
} else {
|
311
|
+
this.taps = new Tap(tap);
|
312
|
+
}
|
313
|
+
return this;
|
314
|
+
}
|
315
|
+
|
316
|
+
Chunk.prototype.untap = function() {
|
317
|
+
this.taps = this.taps.tail;
|
318
|
+
return this;
|
319
|
+
}
|
320
|
+
|
321
|
+
Chunk.prototype.render = function(body, context) {
|
322
|
+
return body(this, context);
|
323
|
+
}
|
324
|
+
|
325
|
+
Chunk.prototype.reference = function(elem, context, auto, filters) {
|
326
|
+
if (typeof elem === "function") {
|
327
|
+
elem = elem(this, context, null, {auto: auto, filters: filters});
|
328
|
+
if (elem instanceof Chunk) {
|
329
|
+
return elem;
|
330
|
+
}
|
331
|
+
}
|
332
|
+
if (!dust.isEmpty(elem)) {
|
333
|
+
return this.write(dust.filter(elem, auto, filters));
|
334
|
+
} else {
|
335
|
+
return this;
|
336
|
+
}
|
337
|
+
};
|
338
|
+
|
339
|
+
Chunk.prototype.section = function(elem, context, bodies, params) {
|
340
|
+
if (typeof elem === "function") {
|
341
|
+
elem = elem(this, context, bodies, params);
|
342
|
+
if (elem instanceof Chunk) {
|
343
|
+
return elem;
|
344
|
+
}
|
345
|
+
}
|
346
|
+
|
347
|
+
var body = bodies.block,
|
348
|
+
skip = bodies['else'];
|
349
|
+
|
350
|
+
if (params) {
|
351
|
+
context = context.push(params);
|
352
|
+
}
|
353
|
+
|
354
|
+
if (dust.isArray(elem)) {
|
355
|
+
if (body) {
|
356
|
+
var len = elem.length, chunk = this;
|
357
|
+
for (var i=0; i<len; i++) {
|
358
|
+
chunk = body(chunk, context.push(elem[i], i, len));
|
359
|
+
}
|
360
|
+
return chunk;
|
361
|
+
}
|
362
|
+
} else if (elem === true) {
|
363
|
+
if (body) return body(this, context);
|
364
|
+
} else if (elem || elem === 0) {
|
365
|
+
if (body) return body(this, context.push(elem));
|
366
|
+
} else if (skip) {
|
367
|
+
return skip(this, context);
|
368
|
+
}
|
369
|
+
return this;
|
370
|
+
};
|
371
|
+
|
372
|
+
Chunk.prototype.exists = function(elem, context, bodies) {
|
373
|
+
var body = bodies.block,
|
374
|
+
skip = bodies['else'];
|
375
|
+
|
376
|
+
if (!dust.isEmpty(elem)) {
|
377
|
+
if (body) return body(this, context);
|
378
|
+
} else if (skip) {
|
379
|
+
return skip(this, context);
|
380
|
+
}
|
381
|
+
return this;
|
382
|
+
}
|
383
|
+
|
384
|
+
Chunk.prototype.notexists = function(elem, context, bodies) {
|
385
|
+
var body = bodies.block,
|
386
|
+
skip = bodies['else'];
|
387
|
+
|
388
|
+
if (dust.isEmpty(elem)) {
|
389
|
+
if (body) return body(this, context);
|
390
|
+
} else if (skip) {
|
391
|
+
return skip(this, context);
|
392
|
+
}
|
393
|
+
return this;
|
394
|
+
}
|
395
|
+
|
396
|
+
Chunk.prototype.block = function(elem, context, bodies) {
|
397
|
+
var body = bodies.block;
|
398
|
+
|
399
|
+
if (elem) {
|
400
|
+
body = elem;
|
401
|
+
}
|
402
|
+
|
403
|
+
if (body) {
|
404
|
+
return body(this, context);
|
405
|
+
}
|
406
|
+
return this;
|
407
|
+
};
|
408
|
+
|
409
|
+
Chunk.prototype.partial = function(elem, context) {
|
410
|
+
if (typeof elem === "function") {
|
411
|
+
return this.capture(elem, context, function(name, chunk) {
|
412
|
+
dust.load(name, chunk, context).end();
|
413
|
+
});
|
414
|
+
}
|
415
|
+
return dust.load(elem, this, context);
|
416
|
+
};
|
417
|
+
|
418
|
+
Chunk.prototype.helper = function(name, context, bodies, params) {
|
419
|
+
return dust.helpers[name](this, context, bodies, params);
|
420
|
+
};
|
421
|
+
|
422
|
+
Chunk.prototype.capture = function(body, context, callback) {
|
423
|
+
return this.map(function(chunk) {
|
424
|
+
var stub = new Stub(function(err, out) {
|
425
|
+
if (err) {
|
426
|
+
chunk.setError(err);
|
427
|
+
} else {
|
428
|
+
callback(out, chunk);
|
429
|
+
}
|
430
|
+
});
|
431
|
+
body(stub.head, context).end();
|
432
|
+
});
|
433
|
+
};
|
434
|
+
|
435
|
+
Chunk.prototype.setError = function(err) {
|
436
|
+
this.error = err;
|
437
|
+
this.root.flush();
|
438
|
+
return this;
|
439
|
+
};
|
440
|
+
|
441
|
+
dust.helpers = {
|
442
|
+
sep: function(chunk, context, bodies) {
|
443
|
+
if (context.stack.index === context.stack.of - 1) {
|
444
|
+
return chunk;
|
445
|
+
}
|
446
|
+
return bodies.block(chunk, context);
|
447
|
+
},
|
448
|
+
|
449
|
+
idx: function(chunk, context, bodies) {
|
450
|
+
return bodies.block(chunk, context.push(context.stack.index));
|
451
|
+
}
|
452
|
+
}
|
453
|
+
|
454
|
+
function Tap(head, tail) {
|
455
|
+
this.head = head;
|
456
|
+
this.tail = tail;
|
457
|
+
}
|
458
|
+
|
459
|
+
Tap.prototype.push = function(tap) {
|
460
|
+
return new Tap(tap, this);
|
461
|
+
};
|
462
|
+
|
463
|
+
Tap.prototype.go = function(value) {
|
464
|
+
var tap = this;
|
465
|
+
|
466
|
+
while(tap) {
|
467
|
+
value = tap.head(value);
|
468
|
+
tap = tap.tail;
|
469
|
+
}
|
470
|
+
return value;
|
471
|
+
};
|
472
|
+
|
473
|
+
var HCHARS = new RegExp(/[&<>\"]/),
|
474
|
+
AMP = /&/g,
|
475
|
+
LT = /</g,
|
476
|
+
GT = />/g,
|
477
|
+
QUOT = /\"/g;
|
478
|
+
|
479
|
+
dust.escapeHtml = function(s) {
|
480
|
+
if (typeof s === "string") {
|
481
|
+
if (!HCHARS.test(s)) {
|
482
|
+
return s;
|
483
|
+
}
|
484
|
+
return s.replace(AMP,'&').replace(LT,'<').replace(GT,'>').replace(QUOT,'"');
|
485
|
+
}
|
486
|
+
return s;
|
487
|
+
};
|
488
|
+
|
489
|
+
var BS = /\\/g,
|
490
|
+
CR = /\r/g,
|
491
|
+
LS = /\u2028/g,
|
492
|
+
PS = /\u2029/g,
|
493
|
+
NL = /\n/g,
|
494
|
+
LF = /\f/g,
|
495
|
+
SQ = /'/g,
|
496
|
+
DQ = /"/g,
|
497
|
+
TB = /\t/g;
|
498
|
+
|
499
|
+
dust.escapeJs = function(s) {
|
500
|
+
if (typeof s === "string") {
|
501
|
+
return s
|
502
|
+
.replace(BS, '\\\\')
|
503
|
+
.replace(DQ, '\\"')
|
504
|
+
.replace(SQ, "\\'")
|
505
|
+
.replace(CR, '\\r')
|
506
|
+
.replace(LS, '\\u2028')
|
507
|
+
.replace(PS, '\\u2029')
|
508
|
+
.replace(NL, '\\n')
|
509
|
+
.replace(LF, '\\f')
|
510
|
+
.replace(TB, "\\t");
|
511
|
+
}
|
512
|
+
return s;
|
513
|
+
};
|
514
|
+
|
515
|
+
})(dust);
|
516
|
+
|
517
|
+
if (typeof exports !== "undefined") {
|
518
|
+
if (typeof process !== "undefined") {
|
519
|
+
require('./server')(dust);
|
520
|
+
}
|
521
|
+
module.exports = dust;
|
522
|
+
}
|