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 ADDED
@@ -0,0 +1,2 @@
1
+ *.DS_Store
2
+ pkg
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in dust-rails.gemspec
4
+ gemspec
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
@@ -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,10 @@
1
+ module Dust
2
+ module Sinatra
3
+ Tilt.register DustTemplate, :dust
4
+
5
+ def self.registered( app )
6
+ app.helpers Dust::Sinatra::Helpers
7
+ Dust.config.template_root ||= "/"
8
+ end
9
+ end
10
+ 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,7 @@
1
+ module Dust
2
+ module Sinatra
3
+ module Helpers
4
+ def dust(*args) render( :dust, *args ) end
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,5 @@
1
+ module Dust
2
+ module Sinatra
3
+ VERSION = "0.1.0"
4
+ end
5
+ end
@@ -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,'&amp;').replace(LT,'&lt;').replace(GT,'&gt;').replace(QUOT,'&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
+ }