dust-sinatra 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/.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
|
+
}
|