marionette_dust 0.0.2 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +24 -5
- data/Rakefile +9 -2
- data/lib/dust_engine/dust.rb +4 -4
- data/lib/generators/{marionette_dust → md}/common/templates/app.js +5 -2
- data/lib/generators/md/common/templates/app.js.coffee +8 -0
- data/lib/generators/{marionette_dust → md}/common/templates/controller.js +0 -0
- data/lib/generators/md/common/templates/controller.js.coffee +2 -0
- data/lib/generators/{marionette_dust → md}/common/templates/entity.js +0 -0
- data/lib/generators/md/common/templates/entity.js.coffee +7 -0
- data/lib/generators/{marionette_dust → md}/common/templates/template.jst.dust +0 -0
- data/lib/generators/{marionette_dust → md}/common/templates/view.js +0 -0
- data/lib/generators/md/common/templates/view.js.coffee +3 -0
- data/lib/generators/{marionette_dust → md}/helpers.rb +0 -0
- data/lib/generators/{marionette_dust → md}/install/install_generator.rb +2 -2
- data/lib/generators/{marionette_dust → md}/install/templates/app.js +5 -0
- data/lib/generators/{marionette_dust → md}/install/templates/app.js.coffee +0 -0
- data/lib/generators/{marionette_dust → md}/scaffold/scaffold_generator.rb +5 -5
- data/lib/generators/{marionette_dust → md}/submodule/submodule_generator.rb +4 -5
- data/lib/marionette_dust/version.rb +1 -1
- data/marionette_dust.gemspec +1 -0
- data/test/lib/generators/marionette_dust/install/install_generator_test.rb +47 -0
- data/test/lib/generators/marionette_dust/install/templates/app/assets/javascripts/app.js +25 -0
- data/test/lib/generators/marionette_dust/install/templates/app/assets/javascripts/app.js.coffee +16 -0
- data/test/lib/generators/marionette_dust/install/templates/app/assets/javascripts/application.js +5 -0
- data/test/lib/generators/marionette_dust/scaffold_and_submodule/scaffold_generator_test.rb +36 -0
- data/test/lib/generators/marionette_dust/scaffold_and_submodule/submodule_generator_test.rb +28 -0
- data/test/lib/generators/marionette_dust/scaffold_and_submodule/templates/app/assets/javascripts/app.js +25 -0
- data/test/lib/generators/marionette_dust/scaffold_and_submodule/templates/app/assets/javascripts/app.js.coffee +16 -0
- data/test/lib/generators/marionette_dust/scaffold_and_submodule/templates/app/assets/javascripts/application.js +5 -0
- data/test/lib/generators/marionette_dust/scaffold_and_submodule/templates/app/assets/javascripts/apps/foo/bar/bar_controller.js +3 -0
- data/test/lib/generators/marionette_dust/scaffold_and_submodule/templates/app/assets/javascripts/apps/foo/bar/bar_controller.js.coffee +2 -0
- data/test/lib/generators/marionette_dust/scaffold_and_submodule/templates/app/assets/javascripts/apps/foo/bar/bar_view.js +5 -0
- data/test/lib/generators/marionette_dust/scaffold_and_submodule/templates/app/assets/javascripts/apps/foo/bar/bar_view.js.coffee +3 -0
- data/test/lib/generators/marionette_dust/scaffold_and_submodule/templates/app/assets/javascripts/apps/test/test_app.js +13 -0
- data/test/lib/generators/marionette_dust/scaffold_and_submodule/templates/app/assets/javascripts/apps/test/test_app.js.coffee +8 -0
- data/test/lib/generators/marionette_dust/scaffold_and_submodule/templates/app/assets/javascripts/entities/test.js +9 -0
- data/test/lib/generators/marionette_dust/scaffold_and_submodule/templates/app/assets/javascripts/entities/test.js.coffee +7 -0
- data/test/lib/generators/marionette_dust/scaffold_and_submodule/templates/app/assets/templates/foo/bar/bar.jst.dust +1 -0
- data/test/test_helper.rb +23 -0
- data/vendor/assets/javascripts/marionette_dust/{dust-full-2.1.0.js → dust-full-2.2.2.js} +742 -673
- data/vendor/assets/javascripts/marionette_dust/index.js +1 -1
- metadata +57 -15
@@ -1,12 +1,13 @@
|
|
1
1
|
//
|
2
|
-
// Dust - Asynchronous Templating v2.
|
2
|
+
// Dust - Asynchronous Templating v2.2.2
|
3
3
|
// http://akdubya.github.com/dustjs
|
4
4
|
//
|
5
5
|
// Copyright (c) 2010, Aleksander Williams
|
6
6
|
// Released under the MIT License.
|
7
7
|
//
|
8
8
|
|
9
|
-
|
9
|
+
/*global console */
|
10
|
+
dust = {};
|
10
11
|
|
11
12
|
function getGlobal(){
|
12
13
|
return (function(){
|
@@ -16,768 +17,817 @@ function getGlobal(){
|
|
16
17
|
|
17
18
|
(function(dust) {
|
18
19
|
|
19
|
-
if(!dust) {
|
20
|
-
|
21
|
-
}
|
22
|
-
var ERROR = 'ERROR',
|
23
|
-
WARN = 'WARN',
|
24
|
-
INFO = 'INFO',
|
25
|
-
DEBUG = 'DEBUG',
|
26
|
-
levels = [DEBUG, INFO, WARN, ERROR],
|
27
|
-
logger = function() {};
|
28
|
-
|
29
|
-
dust.isDebug = false;
|
30
|
-
dust.debugLevel = INFO;
|
31
|
-
|
32
|
-
// Try to find the console logger in window scope (browsers) or top level scope (node.js)
|
33
|
-
if (typeof window !== 'undefined' && window && window.console && window.console.log) {
|
34
|
-
logger = window.console.log;
|
35
|
-
} else if (typeof console !== 'undefined' && console && console.log) {
|
36
|
-
logger = console.log;
|
37
|
-
}
|
38
|
-
|
39
|
-
/**
|
40
|
-
* If dust.isDebug is true, Log dust debug statements, info statements, warning statements, and errors.
|
41
|
-
* This default implementation will print to the console if it exists.
|
42
|
-
* @param {String} message the message to print
|
43
|
-
* @param {String} type the severity of the message(ERROR, WARN, INFO, or DEBUG)
|
44
|
-
* @public
|
45
|
-
*/
|
46
|
-
dust.log = function(message, type) {
|
47
|
-
var type = type || INFO;
|
48
|
-
if(dust.isDebug && levels.indexOf(type) >= levels.indexOf(dust.debugLevel)) {
|
49
|
-
if(!dust.logQueue) {
|
50
|
-
dust.logQueue = [];
|
51
|
-
}
|
52
|
-
dust.logQueue.push({message: message, type: type});
|
53
|
-
logger.call(console || window.console, "[DUST " + type + "]: " + message);
|
20
|
+
if(!dust) {
|
21
|
+
return;
|
54
22
|
}
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
if(
|
67
|
-
|
68
|
-
} else {
|
69
|
-
|
23
|
+
var ERROR = 'ERROR',
|
24
|
+
WARN = 'WARN',
|
25
|
+
INFO = 'INFO',
|
26
|
+
DEBUG = 'DEBUG',
|
27
|
+
levels = [DEBUG, INFO, WARN, ERROR],
|
28
|
+
logger = function() {};
|
29
|
+
|
30
|
+
dust.isDebug = false;
|
31
|
+
dust.debugLevel = INFO;
|
32
|
+
|
33
|
+
// Try to find the console logger in window scope (browsers) or top level scope (node.js)
|
34
|
+
if (typeof window !== 'undefined' && window && window.console && window.console.log) {
|
35
|
+
logger = window.console.log;
|
36
|
+
} else if (typeof console !== 'undefined' && console && console.log) {
|
37
|
+
logger = console.log;
|
70
38
|
}
|
71
|
-
};
|
72
39
|
|
73
|
-
|
40
|
+
/**
|
41
|
+
* If dust.isDebug is true, Log dust debug statements, info statements, warning statements, and errors.
|
42
|
+
* This default implementation will print to the console if it exists.
|
43
|
+
* @param {String} message the message to print
|
44
|
+
* @param {String} type the severity of the message(ERROR, WARN, INFO, or DEBUG)
|
45
|
+
* @public
|
46
|
+
*/
|
47
|
+
dust.log = function(message, type) {
|
48
|
+
var type = type || INFO;
|
49
|
+
if(dust.isDebug && levels.indexOf(type) >= levels.indexOf(dust.debugLevel)) {
|
50
|
+
if(!dust.logQueue) {
|
51
|
+
dust.logQueue = [];
|
52
|
+
}
|
53
|
+
dust.logQueue.push({message: message, type: type});
|
54
|
+
logger.call(console || window.console, '[DUST ' + type + ']: ' + message);
|
55
|
+
}
|
56
|
+
};
|
74
57
|
|
75
|
-
|
58
|
+
/**
|
59
|
+
* If debugging is turned on(dust.isDebug=true) log the error message and throw it.
|
60
|
+
* Otherwise try to keep rendering. This is useful to fail hard in dev mode, but keep rendering in production.
|
61
|
+
* @param {Error} error the error message to throw
|
62
|
+
* @param {Object} chunk the chunk the error was thrown from
|
63
|
+
* @public
|
64
|
+
*/
|
65
|
+
dust.onError = function(error, chunk) {
|
66
|
+
dust.log(error.message || error, ERROR);
|
67
|
+
if(dust.isDebug) {
|
68
|
+
throw error;
|
69
|
+
} else {
|
70
|
+
return chunk;
|
71
|
+
}
|
72
|
+
};
|
76
73
|
|
77
|
-
dust.
|
78
|
-
if (!name) return;
|
79
|
-
dust.cache[name] = tmpl;
|
80
|
-
};
|
74
|
+
dust.helpers = {};
|
81
75
|
|
82
|
-
dust.
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
};
|
76
|
+
dust.cache = {};
|
77
|
+
|
78
|
+
dust.register = function(name, tmpl) {
|
79
|
+
if (!name) {
|
80
|
+
return;
|
81
|
+
}
|
82
|
+
dust.cache[name] = tmpl;
|
83
|
+
};
|
90
84
|
|
91
|
-
dust.
|
92
|
-
|
93
|
-
dust.nextTick(function() {
|
85
|
+
dust.render = function(name, context, callback) {
|
86
|
+
var chunk = new Stub(callback).head;
|
94
87
|
try {
|
95
|
-
dust.load(name,
|
88
|
+
dust.load(name, chunk, Context.wrap(context, name)).end();
|
96
89
|
} catch (err) {
|
97
|
-
dust.onError(err,
|
90
|
+
dust.onError(err, chunk);
|
98
91
|
}
|
99
|
-
}
|
100
|
-
return stream;
|
101
|
-
};
|
102
|
-
|
103
|
-
dust.renderSource = function(source, context, callback) {
|
104
|
-
return dust.compileFn(source)(context, callback);
|
105
|
-
};
|
92
|
+
};
|
106
93
|
|
107
|
-
dust.
|
108
|
-
|
109
|
-
return function(context, callback) {
|
110
|
-
var master = callback ? new Stub(callback) : new Stream();
|
94
|
+
dust.stream = function(name, context) {
|
95
|
+
var stream = new Stream();
|
111
96
|
dust.nextTick(function() {
|
112
|
-
|
113
|
-
|
114
|
-
}
|
115
|
-
|
116
|
-
dust.onError(new Error('Template [' + name + '] cannot be resolved to a Dust function'));
|
97
|
+
try {
|
98
|
+
dust.load(name, stream.head, Context.wrap(context, name)).end();
|
99
|
+
} catch (err) {
|
100
|
+
dust.onError(err, stream.head);
|
117
101
|
}
|
118
102
|
});
|
119
|
-
return
|
103
|
+
return stream;
|
120
104
|
};
|
121
|
-
};
|
122
105
|
|
123
|
-
dust.
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
}
|
106
|
+
dust.renderSource = function(source, context, callback) {
|
107
|
+
return dust.compileFn(source)(context, callback);
|
108
|
+
};
|
109
|
+
|
110
|
+
dust.compileFn = function(source, name) {
|
111
|
+
var tmpl = dust.loadSource(dust.compile(source, name));
|
112
|
+
return function(context, callback) {
|
113
|
+
var master = callback ? new Stub(callback) : new Stream();
|
114
|
+
dust.nextTick(function() {
|
115
|
+
if(typeof tmpl === 'function') {
|
116
|
+
tmpl(master.head, Context.wrap(context, name)).end();
|
117
|
+
}
|
118
|
+
else {
|
119
|
+
dust.onError(new Error('Template [' + name + '] cannot be resolved to a Dust function'));
|
120
|
+
}
|
135
121
|
});
|
136
|
-
|
137
|
-
|
138
|
-
}
|
139
|
-
};
|
122
|
+
return master;
|
123
|
+
};
|
124
|
+
};
|
140
125
|
|
141
|
-
dust.
|
142
|
-
|
143
|
-
|
126
|
+
dust.load = function(name, chunk, context) {
|
127
|
+
var tmpl = dust.cache[name];
|
128
|
+
if (tmpl) {
|
129
|
+
return tmpl(chunk, context);
|
130
|
+
} else {
|
131
|
+
if (dust.onLoad) {
|
132
|
+
return chunk.map(function(chunk) {
|
133
|
+
dust.onLoad(name, function(err, src) {
|
134
|
+
if (err) {
|
135
|
+
return chunk.setError(err);
|
136
|
+
}
|
137
|
+
if (!dust.cache[name]) {
|
138
|
+
dust.loadSource(dust.compile(src, name));
|
139
|
+
}
|
140
|
+
dust.cache[name](chunk, context).end();
|
141
|
+
});
|
142
|
+
});
|
143
|
+
}
|
144
|
+
return chunk.setError(new Error('Template Not Found: ' + name));
|
145
|
+
}
|
146
|
+
};
|
144
147
|
|
145
|
-
|
146
|
-
|
147
|
-
} else {
|
148
|
-
dust.isArray = function(arr) {
|
149
|
-
return Object.prototype.toString.call(arr) === "[object Array]";
|
148
|
+
dust.loadSource = function(source, path) {
|
149
|
+
return eval(source);
|
150
150
|
};
|
151
|
-
}
|
152
151
|
|
153
|
-
|
154
|
-
|
155
|
-
return process.nextTick;
|
152
|
+
if (Array.isArray) {
|
153
|
+
dust.isArray = Array.isArray;
|
156
154
|
} else {
|
157
|
-
|
158
|
-
|
155
|
+
dust.isArray = function(arr) {
|
156
|
+
return Object.prototype.toString.call(arr) === '[object Array]';
|
159
157
|
};
|
160
158
|
}
|
161
|
-
} )();
|
162
159
|
|
163
|
-
dust.
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
160
|
+
dust.nextTick = (function() {
|
161
|
+
if (typeof process !== 'undefined') {
|
162
|
+
return process.nextTick;
|
163
|
+
} else {
|
164
|
+
return function(callback) {
|
165
|
+
setTimeout(callback,0);
|
166
|
+
};
|
167
|
+
}
|
168
|
+
} )();
|
169
|
+
|
170
|
+
dust.isEmpty = function(value) {
|
171
|
+
if (dust.isArray(value) && !value.length) {
|
172
|
+
return true;
|
173
|
+
}
|
174
|
+
if (value === 0) {
|
175
|
+
return false;
|
176
|
+
}
|
177
|
+
return (!value);
|
178
|
+
};
|
168
179
|
|
169
|
-
// apply the filter chain and return the output string
|
170
|
-
dust.filter = function(string, auto, filters) {
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
180
|
+
// apply the filter chain and return the output string
|
181
|
+
dust.filter = function(string, auto, filters) {
|
182
|
+
if (filters) {
|
183
|
+
for (var i=0, len=filters.length; i<len; i++) {
|
184
|
+
var name = filters[i];
|
185
|
+
if (name === 's') {
|
186
|
+
auto = null;
|
187
|
+
dust.log('Using unescape filter on [' + string + ']', DEBUG);
|
188
|
+
}
|
189
|
+
else if (typeof dust.filters[name] === 'function') {
|
190
|
+
string = dust.filters[name](string);
|
191
|
+
}
|
192
|
+
else {
|
193
|
+
dust.onError(new Error('Invalid filter [' + name + ']'));
|
194
|
+
}
|
177
195
|
}
|
178
|
-
|
179
|
-
|
196
|
+
}
|
197
|
+
// by default always apply the h filter, unless asked to unescape with |s
|
198
|
+
if (auto) {
|
199
|
+
string = dust.filters[auto](string);
|
200
|
+
}
|
201
|
+
return string;
|
202
|
+
};
|
203
|
+
|
204
|
+
dust.filters = {
|
205
|
+
h: function(value) { return dust.escapeHtml(value); },
|
206
|
+
j: function(value) { return dust.escapeJs(value); },
|
207
|
+
u: encodeURI,
|
208
|
+
uc: encodeURIComponent,
|
209
|
+
js: function(value) {
|
210
|
+
if (!JSON) {
|
211
|
+
dust.log('JSON is undefined. JSON stringify has not been used on [' + value + ']', WARN);
|
212
|
+
return value;
|
213
|
+
} else {
|
214
|
+
return JSON.stringify(value);
|
180
215
|
}
|
181
|
-
|
182
|
-
|
216
|
+
},
|
217
|
+
jp: function(value) {
|
218
|
+
if (!JSON) {dust.log('JSON is undefined. JSON parse has not been used on [' + value + ']', WARN);
|
219
|
+
return value;
|
220
|
+
} else {
|
221
|
+
return JSON.parse(value);
|
183
222
|
}
|
184
223
|
}
|
224
|
+
};
|
225
|
+
|
226
|
+
function Context(stack, global, blocks, templateName) {
|
227
|
+
this.stack = stack;
|
228
|
+
this.global = global;
|
229
|
+
this.blocks = blocks;
|
230
|
+
this.templateName = templateName;
|
185
231
|
}
|
186
|
-
// by default always apply the h filter, unless asked to unescape with |s
|
187
|
-
if (auto) {
|
188
|
-
string = dust.filters[auto](string);
|
189
|
-
}
|
190
|
-
return string;
|
191
|
-
};
|
192
232
|
|
193
|
-
dust.
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
dust.log('JSON is undefined. JSON stringify has not been used on [' + value + ']', WARN);
|
201
|
-
return value;
|
202
|
-
} else {
|
203
|
-
return JSON.stringify(value);
|
204
|
-
}
|
205
|
-
},
|
206
|
-
jp: function(value) {
|
207
|
-
if (!JSON) {dust.log('JSON is undefined. JSON parse has not been used on [' + value + ']', WARN);
|
208
|
-
return value;
|
209
|
-
} else {
|
210
|
-
return JSON.parse(value);
|
233
|
+
dust.makeBase = function(global) {
|
234
|
+
return new Context(new Stack(), global);
|
235
|
+
};
|
236
|
+
|
237
|
+
Context.wrap = function(context, name) {
|
238
|
+
if (context instanceof Context) {
|
239
|
+
return context;
|
211
240
|
}
|
212
|
-
|
213
|
-
};
|
241
|
+
return new Context(new Stack(context), {}, null, name);
|
242
|
+
};
|
214
243
|
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
244
|
+
/**
|
245
|
+
* Public API for getting a value from the context.
|
246
|
+
* @method get
|
247
|
+
* @param {string|array} path The path to the value. Supported formats are:
|
248
|
+
* 'key'
|
249
|
+
* 'path.to.key'
|
250
|
+
* '.path.to.key'
|
251
|
+
* ['path', 'to', 'key']
|
252
|
+
* ['key']
|
253
|
+
* @param {boolean} [cur=false] Boolean which determines if the search should be limited to the
|
254
|
+
* current context (true), or if get should search in parent contexts as well (false).
|
255
|
+
* @public
|
256
|
+
* @returns {string|object}
|
257
|
+
*/
|
258
|
+
Context.prototype.get = function(path, cur) {
|
259
|
+
if (typeof path === 'string') {
|
260
|
+
if (path[0] === '.') {
|
261
|
+
cur = true;
|
262
|
+
path = path.substr(1);
|
263
|
+
}
|
264
|
+
path = path.split('.');
|
265
|
+
}
|
266
|
+
return this._get(cur, path);
|
267
|
+
};
|
221
268
|
|
222
|
-
|
223
|
-
|
224
|
-
|
269
|
+
/**
|
270
|
+
* Get a value from the context
|
271
|
+
* @method _get
|
272
|
+
* @param {boolean} cur Get only from the current context
|
273
|
+
* @param {array} down An array of each step in the path
|
274
|
+
* @private
|
275
|
+
* @return {string | object}
|
276
|
+
*/
|
277
|
+
Context.prototype._get = function(cur, down) {
|
278
|
+
var ctx = this.stack,
|
279
|
+
i = 1,
|
280
|
+
value, first, len, ctxThis;
|
281
|
+
dust.log('Searching for reference [{' + down.join('.') + '}] in template [' + this.getTemplateName() + ']', DEBUG);
|
282
|
+
first = down[0];
|
283
|
+
len = down.length;
|
284
|
+
|
285
|
+
if (cur && len === 0) {
|
286
|
+
ctxThis = ctx;
|
287
|
+
ctx = ctx.head;
|
288
|
+
} else {
|
289
|
+
if (!cur) {
|
290
|
+
// Search up the stack for the first value
|
291
|
+
while (ctx) {
|
292
|
+
if (ctx.isObject) {
|
293
|
+
ctxThis = ctx.head;
|
294
|
+
value = ctx.head[first];
|
295
|
+
if (value !== undefined) {
|
296
|
+
break;
|
297
|
+
}
|
298
|
+
}
|
299
|
+
ctx = ctx.tail;
|
300
|
+
}
|
225
301
|
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
}
|
302
|
+
if (value !== undefined) {
|
303
|
+
ctx = value;
|
304
|
+
} else {
|
305
|
+
ctx = this.global ? this.global[first] : undefined;
|
306
|
+
}
|
307
|
+
} else {
|
308
|
+
// if scope is limited by a leading dot, don't search up the tree
|
309
|
+
ctx = ctx.head[first];
|
310
|
+
}
|
232
311
|
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
if (ctx.isObject) {
|
238
|
-
value = ctx.head[key];
|
239
|
-
if (!(value === undefined)) {
|
240
|
-
return value;
|
312
|
+
while (ctx && i < len) {
|
313
|
+
ctxThis = ctx;
|
314
|
+
ctx = ctx[down[i]];
|
315
|
+
i++;
|
241
316
|
}
|
242
317
|
}
|
243
|
-
ctx = ctx.tail;
|
244
|
-
}
|
245
|
-
globalValue = this.global ? this.global[key] : undefined;
|
246
|
-
if(typeof globalValue === 'undefined') {
|
247
|
-
dust.log('Cannot find the value for reference [{' + key + '}] in template [' + this.templateName + ']');
|
248
|
-
}
|
249
|
-
return globalValue;
|
250
|
-
};
|
251
318
|
|
252
|
-
//
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
ctx = ctx[down[i]];
|
265
|
-
i++;
|
266
|
-
while (!ctx && !cur){
|
267
|
-
// i is the count of number of path elements matched. If > 1 then we have a partial match
|
268
|
-
// and do not continue to search for the rest of the path.
|
269
|
-
// Note: a falsey value at the end of a matched path also comes here.
|
270
|
-
// This returns the value or undefined if we just have a partial match.
|
271
|
-
if (i > 1) return ctx;
|
272
|
-
if (tail){
|
273
|
-
ctx = tail.head;
|
274
|
-
tail = tail.tail;
|
275
|
-
i=0;
|
276
|
-
} else if (!cur) {
|
277
|
-
//finally search this.global. we set cur to true to halt after
|
278
|
-
ctx = this.global;
|
279
|
-
cur = true;
|
280
|
-
i=0;
|
281
|
-
}
|
319
|
+
// Return the ctx or a function wrapping the application of the context.
|
320
|
+
if (typeof ctx === 'function') {
|
321
|
+
var fn = function() {
|
322
|
+
return ctx.apply(ctxThis, arguments);
|
323
|
+
};
|
324
|
+
fn.isFunction = true;
|
325
|
+
return fn;
|
326
|
+
} else {
|
327
|
+
if (ctx === undefined) {
|
328
|
+
dust.log('Cannot find the value for reference [{' + down.join('.') + '}] in template [' + this.getTemplateName() + ']');
|
329
|
+
}
|
330
|
+
return ctx;
|
282
331
|
}
|
283
|
-
}
|
284
|
-
if (typeof ctx == 'function'){
|
285
|
-
//wrap to preserve context 'this' see #174
|
286
|
-
return function(){
|
287
|
-
return ctx.apply(ctxThis,arguments);
|
288
|
-
};
|
289
|
-
}
|
290
|
-
else {
|
291
|
-
return ctx;
|
292
|
-
}
|
293
|
-
};
|
294
|
-
|
295
|
-
Context.prototype.push = function(head, idx, len) {
|
296
|
-
return new Context(new Stack(head, this.stack, idx, len), this.global, this.blocks, this.templateName);
|
297
|
-
};
|
332
|
+
};
|
298
333
|
|
299
|
-
Context.prototype.
|
300
|
-
|
301
|
-
};
|
334
|
+
Context.prototype.getPath = function(cur, down) {
|
335
|
+
return this._get(cur, down);
|
336
|
+
};
|
302
337
|
|
303
|
-
Context.prototype.
|
304
|
-
|
305
|
-
};
|
338
|
+
Context.prototype.push = function(head, idx, len) {
|
339
|
+
return new Context(new Stack(head, this.stack, idx, len), this.global, this.blocks, this.getTemplateName());
|
340
|
+
};
|
306
341
|
|
307
|
-
Context.prototype.
|
308
|
-
|
309
|
-
|
310
|
-
key = key(tempChk, this).data.join("");
|
311
|
-
}
|
342
|
+
Context.prototype.rebase = function(head) {
|
343
|
+
return new Context(new Stack(head), this.global, this.blocks, this.getTemplateName());
|
344
|
+
};
|
312
345
|
|
313
|
-
|
346
|
+
Context.prototype.current = function() {
|
347
|
+
return this.stack.head;
|
348
|
+
};
|
314
349
|
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
while (len--) {
|
321
|
-
fn = blocks[len][key];
|
322
|
-
if (fn) return fn;
|
323
|
-
}
|
324
|
-
};
|
350
|
+
Context.prototype.getBlock = function(key, chk, ctx) {
|
351
|
+
if (typeof key === 'function') {
|
352
|
+
var tempChk = new Chunk();
|
353
|
+
key = key(tempChk, this).data.join('');
|
354
|
+
}
|
325
355
|
|
326
|
-
|
327
|
-
var blocks = this.blocks,
|
328
|
-
newBlocks;
|
356
|
+
var blocks = this.blocks;
|
329
357
|
|
330
|
-
if (locals) {
|
331
358
|
if (!blocks) {
|
332
|
-
|
333
|
-
|
334
|
-
newBlocks = blocks.concat([locals]);
|
359
|
+
dust.log('No blocks for context[{' + key + '}] in template [' + this.getTemplateName() + ']', DEBUG);
|
360
|
+
return;
|
335
361
|
}
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
this.head = head;
|
345
|
-
this.index = idx;
|
346
|
-
this.of = len;
|
347
|
-
}
|
348
|
-
|
349
|
-
function Stub(callback) {
|
350
|
-
this.head = new Chunk(this);
|
351
|
-
this.callback = callback;
|
352
|
-
this.out = '';
|
353
|
-
}
|
362
|
+
var len = blocks.length, fn;
|
363
|
+
while (len--) {
|
364
|
+
fn = blocks[len][key];
|
365
|
+
if (fn) {
|
366
|
+
return fn;
|
367
|
+
}
|
368
|
+
}
|
369
|
+
};
|
354
370
|
|
355
|
-
|
356
|
-
|
371
|
+
Context.prototype.shiftBlocks = function(locals) {
|
372
|
+
var blocks = this.blocks,
|
373
|
+
newBlocks;
|
357
374
|
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
this.
|
365
|
-
return;
|
366
|
-
} else {
|
367
|
-
return;
|
375
|
+
if (locals) {
|
376
|
+
if (!blocks) {
|
377
|
+
newBlocks = [locals];
|
378
|
+
} else {
|
379
|
+
newBlocks = blocks.concat([locals]);
|
380
|
+
}
|
381
|
+
return new Context(this.stack, this.global, newBlocks, this.getTemplateName());
|
368
382
|
}
|
369
|
-
|
370
|
-
|
383
|
+
return this;
|
384
|
+
};
|
385
|
+
|
386
|
+
Context.prototype.getTemplateName = function() {
|
387
|
+
return this.templateName;
|
371
388
|
}
|
372
|
-
this.callback(null, this.out);
|
373
|
-
};
|
374
389
|
|
375
|
-
function
|
376
|
-
|
377
|
-
|
390
|
+
function Stack(head, tail, idx, len) {
|
391
|
+
this.tail = tail;
|
392
|
+
this.isObject = !dust.isArray(head) && head && typeof head === 'object';
|
393
|
+
this.head = head;
|
394
|
+
this.index = idx;
|
395
|
+
this.of = len;
|
396
|
+
}
|
378
397
|
|
379
|
-
|
380
|
-
|
398
|
+
function Stub(callback) {
|
399
|
+
this.head = new Chunk(this);
|
400
|
+
this.callback = callback;
|
401
|
+
this.out = '';
|
402
|
+
}
|
381
403
|
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
404
|
+
Stub.prototype.flush = function() {
|
405
|
+
var chunk = this.head;
|
406
|
+
|
407
|
+
while (chunk) {
|
408
|
+
if (chunk.flushable) {
|
409
|
+
this.out += chunk.data.join(''); //ie7 perf
|
410
|
+
} else if (chunk.error) {
|
411
|
+
this.callback(chunk.error);
|
412
|
+
dust.onError(new Error('Chunk error [' + chunk.error + '] thrown. Ceasing to render this template.'));
|
413
|
+
this.flush = function() {};
|
414
|
+
return;
|
415
|
+
} else {
|
416
|
+
return;
|
417
|
+
}
|
418
|
+
chunk = chunk.next;
|
419
|
+
this.head = chunk;
|
392
420
|
}
|
393
|
-
|
394
|
-
|
395
|
-
}
|
396
|
-
this.emit('end');
|
397
|
-
};
|
421
|
+
this.callback(null, this.out);
|
422
|
+
};
|
398
423
|
|
399
|
-
Stream
|
400
|
-
|
401
|
-
dust.log('No events to emit', INFO);
|
402
|
-
return false;
|
424
|
+
function Stream() {
|
425
|
+
this.head = new Chunk(this);
|
403
426
|
}
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
427
|
+
|
428
|
+
Stream.prototype.flush = function() {
|
429
|
+
var chunk = this.head;
|
430
|
+
|
431
|
+
while(chunk) {
|
432
|
+
if (chunk.flushable) {
|
433
|
+
this.emit('data', chunk.data.join('')); //ie7 perf
|
434
|
+
} else if (chunk.error) {
|
435
|
+
this.emit('error', chunk.error);
|
436
|
+
dust.onError(new Error('Chunk error [' + chunk.error + '] thrown. Ceasing to render this template.'));
|
437
|
+
this.flush = function() {};
|
438
|
+
return;
|
439
|
+
} else {
|
440
|
+
return;
|
441
|
+
}
|
442
|
+
chunk = chunk.next;
|
443
|
+
this.head = chunk;
|
415
444
|
}
|
416
|
-
|
417
|
-
|
418
|
-
}
|
419
|
-
};
|
445
|
+
this.emit('end');
|
446
|
+
};
|
420
447
|
|
421
|
-
Stream.prototype.
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
if(
|
428
|
-
|
448
|
+
Stream.prototype.emit = function(type, data) {
|
449
|
+
if (!this.events) {
|
450
|
+
dust.log('No events to emit', INFO);
|
451
|
+
return false;
|
452
|
+
}
|
453
|
+
var handler = this.events[type];
|
454
|
+
if (!handler) {
|
455
|
+
dust.log('Event type [' + type + '] does not exist', WARN);
|
456
|
+
return false;
|
457
|
+
}
|
458
|
+
if (typeof handler === 'function') {
|
459
|
+
handler(data);
|
460
|
+
} else if (dust.isArray(handler)) {
|
461
|
+
var listeners = handler.slice(0);
|
462
|
+
for (var i = 0, l = listeners.length; i < l; i++) {
|
463
|
+
listeners[i](data);
|
464
|
+
}
|
429
465
|
} else {
|
430
|
-
dust.
|
466
|
+
dust.onError(new Error('Event Handler [' + handler + '] is not of a type that is handled by emit'));
|
431
467
|
}
|
432
|
-
}
|
433
|
-
this.events[type] = [this.events[type], callback];
|
434
|
-
} else {
|
435
|
-
this.events[type].push(callback);
|
436
|
-
}
|
437
|
-
return this;
|
438
|
-
};
|
468
|
+
};
|
439
469
|
|
440
|
-
Stream.prototype.
|
441
|
-
|
442
|
-
|
443
|
-
stream.write(data, "utf8");
|
444
|
-
} catch (err) {
|
445
|
-
dust.onError(err, stream.head);
|
470
|
+
Stream.prototype.on = function(type, callback) {
|
471
|
+
if (!this.events) {
|
472
|
+
this.events = {};
|
446
473
|
}
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
|
474
|
+
if (!this.events[type]) {
|
475
|
+
dust.log('Event type [' + type + '] does not exist. Using just the specified callback.', WARN);
|
476
|
+
if(callback) {
|
477
|
+
this.events[type] = callback;
|
478
|
+
} else {
|
479
|
+
dust.log('Callback for type [' + type + '] does not exist. Listener not registered.', WARN);
|
480
|
+
}
|
481
|
+
} else if(typeof this.events[type] === 'function') {
|
482
|
+
this.events[type] = [this.events[type], callback];
|
483
|
+
} else {
|
484
|
+
this.events[type].push(callback);
|
452
485
|
}
|
453
|
-
|
454
|
-
|
455
|
-
});
|
456
|
-
return this;
|
457
|
-
};
|
458
|
-
|
459
|
-
function Chunk(root, next, taps) {
|
460
|
-
this.root = root;
|
461
|
-
this.next = next;
|
462
|
-
this.data = []; //ie7 perf
|
463
|
-
this.flushable = false;
|
464
|
-
this.taps = taps;
|
465
|
-
}
|
466
|
-
|
467
|
-
Chunk.prototype.write = function(data) {
|
468
|
-
var taps = this.taps;
|
486
|
+
return this;
|
487
|
+
};
|
469
488
|
|
470
|
-
|
471
|
-
data
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
489
|
+
Stream.prototype.pipe = function(stream) {
|
490
|
+
this.on('data', function(data) {
|
491
|
+
try {
|
492
|
+
stream.write(data, 'utf8');
|
493
|
+
} catch (err) {
|
494
|
+
dust.onError(err, stream.head);
|
495
|
+
}
|
496
|
+
}).on('end', function() {
|
497
|
+
try {
|
498
|
+
return stream.end();
|
499
|
+
} catch (err) {
|
500
|
+
dust.onError(err, stream.head);
|
501
|
+
}
|
502
|
+
}).on('error', function(err) {
|
503
|
+
stream.error(err);
|
504
|
+
});
|
505
|
+
return this;
|
506
|
+
};
|
476
507
|
|
477
|
-
Chunk
|
478
|
-
|
479
|
-
this.
|
508
|
+
function Chunk(root, next, taps) {
|
509
|
+
this.root = root;
|
510
|
+
this.next = next;
|
511
|
+
this.data = []; //ie7 perf
|
512
|
+
this.flushable = false;
|
513
|
+
this.taps = taps;
|
480
514
|
}
|
481
|
-
this.flushable = true;
|
482
|
-
this.root.flush();
|
483
|
-
return this;
|
484
|
-
};
|
485
515
|
|
486
|
-
Chunk.prototype.
|
487
|
-
|
488
|
-
branch = new Chunk(this.root, cursor, this.taps);
|
516
|
+
Chunk.prototype.write = function(data) {
|
517
|
+
var taps = this.taps;
|
489
518
|
|
490
|
-
|
491
|
-
|
492
|
-
|
493
|
-
|
494
|
-
|
519
|
+
if (taps) {
|
520
|
+
data = taps.go(data);
|
521
|
+
}
|
522
|
+
this.data.push(data);
|
523
|
+
return this;
|
524
|
+
};
|
495
525
|
|
496
|
-
Chunk.prototype.
|
497
|
-
|
526
|
+
Chunk.prototype.end = function(data) {
|
527
|
+
if (data) {
|
528
|
+
this.write(data);
|
529
|
+
}
|
530
|
+
this.flushable = true;
|
531
|
+
this.root.flush();
|
532
|
+
return this;
|
533
|
+
};
|
498
534
|
|
499
|
-
|
500
|
-
this.
|
501
|
-
|
502
|
-
this.taps = new Tap(tap);
|
503
|
-
}
|
504
|
-
return this;
|
505
|
-
};
|
535
|
+
Chunk.prototype.map = function(callback) {
|
536
|
+
var cursor = new Chunk(this.root, this.next, this.taps),
|
537
|
+
branch = new Chunk(this.root, cursor, this.taps);
|
506
538
|
|
507
|
-
|
508
|
-
|
509
|
-
|
510
|
-
|
539
|
+
this.next = branch;
|
540
|
+
this.flushable = true;
|
541
|
+
callback(branch);
|
542
|
+
return cursor;
|
543
|
+
};
|
511
544
|
|
512
|
-
Chunk.prototype.
|
513
|
-
|
514
|
-
};
|
545
|
+
Chunk.prototype.tap = function(tap) {
|
546
|
+
var taps = this.taps;
|
515
547
|
|
516
|
-
|
517
|
-
|
518
|
-
|
519
|
-
|
520
|
-
// that "this" is wat we expect it to be inside the function
|
521
|
-
elem = elem.apply(context.current(), [this, context, null, {auto: auto, filters: filters}]);
|
522
|
-
if (elem instanceof Chunk) {
|
523
|
-
return elem;
|
548
|
+
if (taps) {
|
549
|
+
this.taps = taps.push(tap);
|
550
|
+
} else {
|
551
|
+
this.taps = new Tap(tap);
|
524
552
|
}
|
525
|
-
}
|
526
|
-
if (!dust.isEmpty(elem)) {
|
527
|
-
return this.write(dust.filter(elem, auto, filters));
|
528
|
-
} else {
|
529
553
|
return this;
|
530
|
-
}
|
531
|
-
|
554
|
+
};
|
555
|
+
|
556
|
+
Chunk.prototype.untap = function() {
|
557
|
+
this.taps = this.taps.tail;
|
558
|
+
return this;
|
559
|
+
};
|
560
|
+
|
561
|
+
Chunk.prototype.render = function(body, context) {
|
562
|
+
return body(this, context);
|
563
|
+
};
|
532
564
|
|
533
|
-
Chunk.prototype.
|
534
|
-
|
535
|
-
|
536
|
-
|
537
|
-
|
538
|
-
|
539
|
-
|
540
|
-
|
565
|
+
Chunk.prototype.reference = function(elem, context, auto, filters) {
|
566
|
+
if (typeof elem === 'function') {
|
567
|
+
elem.isFunction = true;
|
568
|
+
// Changed the function calling to use apply with the current context to make sure
|
569
|
+
// that "this" is wat we expect it to be inside the function
|
570
|
+
elem = elem.apply(context.current(), [this, context, null, {auto: auto, filters: filters}]);
|
571
|
+
if (elem instanceof Chunk) {
|
572
|
+
return elem;
|
573
|
+
}
|
541
574
|
}
|
542
|
-
|
543
|
-
|
544
|
-
|
575
|
+
if (!dust.isEmpty(elem)) {
|
576
|
+
return this.write(dust.filter(elem, auto, filters));
|
577
|
+
} else {
|
578
|
+
return this;
|
579
|
+
}
|
580
|
+
};
|
545
581
|
|
546
|
-
|
547
|
-
|
548
|
-
|
549
|
-
|
582
|
+
Chunk.prototype.section = function(elem, context, bodies, params) {
|
583
|
+
// anonymous functions
|
584
|
+
if (typeof elem === 'function') {
|
585
|
+
elem = elem.apply(context.current(), [this, context, bodies, params]);
|
586
|
+
// functions that return chunks are assumed to have handled the body and/or have modified the chunk
|
587
|
+
// use that return value as the current chunk and go to the next method in the chain
|
588
|
+
if (elem instanceof Chunk) {
|
589
|
+
return elem;
|
590
|
+
}
|
591
|
+
}
|
592
|
+
var body = bodies.block,
|
593
|
+
skip = bodies['else'];
|
550
594
|
|
551
|
-
|
552
|
-
|
553
|
-
|
554
|
-
|
555
|
-
|
556
|
-
|
557
|
-
|
558
|
-
|
559
|
-
|
560
|
-
|
561
|
-
|
562
|
-
|
563
|
-
|
564
|
-
|
565
|
-
|
566
|
-
|
595
|
+
// a.k.a Inline parameters in the Dust documentations
|
596
|
+
if (params) {
|
597
|
+
context = context.push(params);
|
598
|
+
}
|
599
|
+
|
600
|
+
/*
|
601
|
+
Dust's default behavior is to enumerate over the array elem, passing each object in the array to the block.
|
602
|
+
When elem resolves to a value or object instead of an array, Dust sets the current context to the value
|
603
|
+
and renders the block one time.
|
604
|
+
*/
|
605
|
+
//non empty array is truthy, empty array is falsy
|
606
|
+
if (dust.isArray(elem)) {
|
607
|
+
if (body) {
|
608
|
+
var len = elem.length, chunk = this;
|
609
|
+
if (len > 0) {
|
610
|
+
// any custom helper can blow up the stack
|
611
|
+
// and store a flattened context, guard defensively
|
612
|
+
if(context.stack.head) {
|
613
|
+
context.stack.head['$len'] = len;
|
614
|
+
}
|
615
|
+
for (var i=0; i<len; i++) {
|
616
|
+
if(context.stack.head) {
|
617
|
+
context.stack.head['$idx'] = i;
|
618
|
+
}
|
619
|
+
chunk = body(chunk, context.push(elem[i], i, len));
|
620
|
+
}
|
567
621
|
if(context.stack.head) {
|
568
|
-
|
622
|
+
context.stack.head['$idx'] = undefined;
|
623
|
+
context.stack.head['$len'] = undefined;
|
569
624
|
}
|
570
|
-
|
625
|
+
return chunk;
|
571
626
|
}
|
572
|
-
if(
|
573
|
-
|
574
|
-
context.stack.head['$len'] = undefined;
|
627
|
+
else if (skip) {
|
628
|
+
return skip(this, context);
|
575
629
|
}
|
576
|
-
return chunk;
|
577
630
|
}
|
578
|
-
|
579
|
-
|
580
|
-
|
581
|
-
}
|
582
|
-
}
|
583
|
-
// true is truthy but does not change context
|
584
|
-
else if (elem === true) {
|
585
|
-
if (body) {
|
631
|
+
} else if (elem === true) {
|
632
|
+
// true is truthy but does not change context
|
633
|
+
if (body) {
|
586
634
|
return body(this, context);
|
587
|
-
|
588
|
-
|
589
|
-
|
590
|
-
|
591
|
-
|
592
|
-
|
593
|
-
|
594
|
-
|
595
|
-
|
596
|
-
|
597
|
-
|
598
|
-
|
599
|
-
|
600
|
-
|
601
|
-
|
602
|
-
};
|
635
|
+
}
|
636
|
+
} else if (elem || elem === 0) {
|
637
|
+
// everything that evaluates to true are truthy ( e.g. Non-empty strings and Empty objects are truthy. )
|
638
|
+
// zero is truthy
|
639
|
+
// for anonymous functions that did not returns a chunk, truthiness is evaluated based on the return value
|
640
|
+
if (body) {
|
641
|
+
return body(this, context.push(elem));
|
642
|
+
}
|
643
|
+
// nonexistent, scalar false value, scalar empty string, null,
|
644
|
+
// undefined are all falsy
|
645
|
+
} else if (skip) {
|
646
|
+
return skip(this, context);
|
647
|
+
}
|
648
|
+
dust.log('Not rendering section (#) block in template [' + context.getTemplateName() + '], because above key was not found', DEBUG);
|
649
|
+
return this;
|
650
|
+
};
|
603
651
|
|
604
|
-
Chunk.prototype.exists = function(elem, context, bodies) {
|
605
|
-
|
606
|
-
|
652
|
+
Chunk.prototype.exists = function(elem, context, bodies) {
|
653
|
+
var body = bodies.block,
|
654
|
+
skip = bodies['else'];
|
607
655
|
|
608
|
-
|
609
|
-
|
610
|
-
|
611
|
-
|
612
|
-
|
613
|
-
|
614
|
-
|
615
|
-
|
656
|
+
if (!dust.isEmpty(elem)) {
|
657
|
+
if (body) {
|
658
|
+
return body(this, context);
|
659
|
+
}
|
660
|
+
} else if (skip) {
|
661
|
+
return skip(this, context);
|
662
|
+
}
|
663
|
+
dust.log('Not rendering exists (?) block in template [' + context.getTemplateName() + '], because above key was not found', DEBUG);
|
664
|
+
return this;
|
665
|
+
};
|
616
666
|
|
617
|
-
Chunk.prototype.notexists = function(elem, context, bodies) {
|
618
|
-
|
619
|
-
|
667
|
+
Chunk.prototype.notexists = function(elem, context, bodies) {
|
668
|
+
var body = bodies.block,
|
669
|
+
skip = bodies['else'];
|
620
670
|
|
621
|
-
|
622
|
-
|
623
|
-
|
624
|
-
|
625
|
-
|
626
|
-
|
627
|
-
|
628
|
-
|
671
|
+
if (dust.isEmpty(elem)) {
|
672
|
+
if (body) {
|
673
|
+
return body(this, context);
|
674
|
+
}
|
675
|
+
} else if (skip) {
|
676
|
+
return skip(this, context);
|
677
|
+
}
|
678
|
+
dust.log('Not rendering not exists (^) block check in template [' + context.getTemplateName() + '], because above key was found', DEBUG);
|
679
|
+
return this;
|
680
|
+
};
|
629
681
|
|
630
|
-
Chunk.prototype.block = function(elem, context, bodies) {
|
631
|
-
|
682
|
+
Chunk.prototype.block = function(elem, context, bodies) {
|
683
|
+
var body = bodies.block;
|
632
684
|
|
633
|
-
|
634
|
-
|
635
|
-
|
685
|
+
if (elem) {
|
686
|
+
body = elem;
|
687
|
+
}
|
636
688
|
|
637
|
-
|
638
|
-
|
639
|
-
|
640
|
-
|
641
|
-
};
|
689
|
+
if (body) {
|
690
|
+
return body(this, context);
|
691
|
+
}
|
692
|
+
return this;
|
693
|
+
};
|
642
694
|
|
643
|
-
Chunk.prototype.partial = function(elem, context, params) {
|
644
|
-
|
645
|
-
|
646
|
-
|
647
|
-
|
648
|
-
|
649
|
-
|
650
|
-
|
651
|
-
|
652
|
-
|
653
|
-
|
654
|
-
|
655
|
-
|
656
|
-
|
657
|
-
// templateName can be static (string) or dynamic (function)
|
658
|
-
// e.g. {>"static_template"/}
|
659
|
-
// {>"{dynamic_template}"/}
|
660
|
-
if (elem) {
|
661
|
-
partialContext.templateName = elem;
|
662
|
-
}
|
695
|
+
Chunk.prototype.partial = function(elem, context, params) {
|
696
|
+
var partialContext;
|
697
|
+
//put the params context second to match what section does. {.} matches the current context without parameters
|
698
|
+
// start with an empty context
|
699
|
+
partialContext = dust.makeBase(context.global);
|
700
|
+
partialContext.blocks = context.blocks;
|
701
|
+
if (context.stack && context.stack.tail){
|
702
|
+
// grab the stack(tail) off of the previous context if we have it
|
703
|
+
partialContext.stack = context.stack.tail;
|
704
|
+
}
|
705
|
+
if (params){
|
706
|
+
//put params on
|
707
|
+
partialContext = partialContext.push(params);
|
708
|
+
}
|
663
709
|
|
664
|
-
|
665
|
-
|
666
|
-
|
667
|
-
var partialChunk;
|
668
|
-
if (typeof elem === "function") {
|
669
|
-
partialChunk = this.capture(elem, partialContext, function(name, chunk) {
|
670
|
-
dust.load(name, chunk, partialContext).end();
|
671
|
-
});
|
672
|
-
}
|
673
|
-
else {
|
674
|
-
partialChunk = dust.load(elem, this, partialContext);
|
675
|
-
}
|
676
|
-
return partialChunk;
|
677
|
-
};
|
710
|
+
if(typeof elem === 'string') {
|
711
|
+
partialContext.templateName = elem;
|
712
|
+
}
|
678
713
|
|
679
|
-
|
680
|
-
|
681
|
-
|
682
|
-
|
683
|
-
if(
|
684
|
-
|
714
|
+
//reattach the head
|
715
|
+
partialContext = partialContext.push(context.stack.head);
|
716
|
+
|
717
|
+
var partialChunk;
|
718
|
+
if (typeof elem === 'function') {
|
719
|
+
partialChunk = this.capture(elem, partialContext, function(name, chunk) {
|
720
|
+
partialContext.templateName = partialContext.templateName || name;
|
721
|
+
dust.load(name, chunk, partialContext).end();
|
722
|
+
});
|
685
723
|
} else {
|
686
|
-
|
724
|
+
partialChunk = dust.load(elem, this, partialContext);
|
687
725
|
}
|
688
|
-
|
689
|
-
|
690
|
-
}
|
691
|
-
};
|
726
|
+
return partialChunk;
|
727
|
+
};
|
692
728
|
|
693
|
-
Chunk.prototype.
|
694
|
-
|
695
|
-
|
696
|
-
|
697
|
-
|
729
|
+
Chunk.prototype.helper = function(name, context, bodies, params) {
|
730
|
+
var chunk = this;
|
731
|
+
// handle invalid helpers, similar to invalid filters
|
732
|
+
try {
|
733
|
+
if(dust.helpers[name]) {
|
734
|
+
return dust.helpers[name](chunk, context, bodies, params);
|
698
735
|
} else {
|
699
|
-
|
736
|
+
return dust.onError(new Error('Invalid helper [' + name + ']'), chunk);
|
700
737
|
}
|
738
|
+
} catch (err) {
|
739
|
+
return dust.onError(err, chunk);
|
740
|
+
}
|
741
|
+
};
|
742
|
+
|
743
|
+
Chunk.prototype.capture = function(body, context, callback) {
|
744
|
+
return this.map(function(chunk) {
|
745
|
+
var stub = new Stub(function(err, out) {
|
746
|
+
if (err) {
|
747
|
+
chunk.setError(err);
|
748
|
+
} else {
|
749
|
+
callback(out, chunk);
|
750
|
+
}
|
751
|
+
});
|
752
|
+
body(stub.head, context).end();
|
701
753
|
});
|
702
|
-
|
703
|
-
});
|
704
|
-
};
|
754
|
+
};
|
705
755
|
|
706
|
-
Chunk.prototype.setError = function(err) {
|
707
|
-
|
708
|
-
|
709
|
-
|
710
|
-
};
|
756
|
+
Chunk.prototype.setError = function(err) {
|
757
|
+
this.error = err;
|
758
|
+
this.root.flush();
|
759
|
+
return this;
|
760
|
+
};
|
711
761
|
|
712
|
-
function Tap(head, tail) {
|
713
|
-
|
714
|
-
|
715
|
-
}
|
762
|
+
function Tap(head, tail) {
|
763
|
+
this.head = head;
|
764
|
+
this.tail = tail;
|
765
|
+
}
|
716
766
|
|
717
|
-
Tap.prototype.push = function(tap) {
|
718
|
-
|
719
|
-
};
|
767
|
+
Tap.prototype.push = function(tap) {
|
768
|
+
return new Tap(tap, this);
|
769
|
+
};
|
720
770
|
|
721
|
-
Tap.prototype.go = function(value) {
|
722
|
-
|
771
|
+
Tap.prototype.go = function(value) {
|
772
|
+
var tap = this;
|
723
773
|
|
724
|
-
|
725
|
-
|
726
|
-
|
727
|
-
|
728
|
-
|
729
|
-
};
|
774
|
+
while(tap) {
|
775
|
+
value = tap.head(value);
|
776
|
+
tap = tap.tail;
|
777
|
+
}
|
778
|
+
return value;
|
779
|
+
};
|
730
780
|
|
731
|
-
var HCHARS = new RegExp(/[&<>\"\']/),
|
732
|
-
|
733
|
-
|
734
|
-
|
735
|
-
|
736
|
-
|
737
|
-
|
738
|
-
dust.escapeHtml = function(s) {
|
739
|
-
|
740
|
-
|
741
|
-
|
781
|
+
var HCHARS = new RegExp(/[&<>\"\']/),
|
782
|
+
AMP = /&/g,
|
783
|
+
LT = /</g,
|
784
|
+
GT = />/g,
|
785
|
+
QUOT = /\"/g,
|
786
|
+
SQUOT = /\'/g;
|
787
|
+
|
788
|
+
dust.escapeHtml = function(s) {
|
789
|
+
if (typeof s === 'string') {
|
790
|
+
if (!HCHARS.test(s)) {
|
791
|
+
return s;
|
792
|
+
}
|
793
|
+
return s.replace(AMP,'&').replace(LT,'<').replace(GT,'>').replace(QUOT,'"').replace(SQUOT, ''');
|
742
794
|
}
|
743
|
-
return s
|
744
|
-
}
|
745
|
-
return s;
|
746
|
-
};
|
795
|
+
return s;
|
796
|
+
};
|
747
797
|
|
748
|
-
var BS = /\\/g,
|
749
|
-
|
750
|
-
|
751
|
-
|
752
|
-
|
753
|
-
|
754
|
-
|
755
|
-
|
756
|
-
|
757
|
-
|
758
|
-
|
759
|
-
dust.escapeJs = function(s) {
|
760
|
-
|
761
|
-
|
762
|
-
|
763
|
-
|
764
|
-
|
765
|
-
|
766
|
-
|
767
|
-
|
768
|
-
|
769
|
-
|
770
|
-
|
771
|
-
|
772
|
-
|
773
|
-
|
774
|
-
};
|
798
|
+
var BS = /\\/g,
|
799
|
+
FS = /\//g,
|
800
|
+
CR = /\r/g,
|
801
|
+
LS = /\u2028/g,
|
802
|
+
PS = /\u2029/g,
|
803
|
+
NL = /\n/g,
|
804
|
+
LF = /\f/g,
|
805
|
+
SQ = /'/g,
|
806
|
+
DQ = /"/g,
|
807
|
+
TB = /\t/g;
|
808
|
+
|
809
|
+
dust.escapeJs = function(s) {
|
810
|
+
if (typeof s === 'string') {
|
811
|
+
return s
|
812
|
+
.replace(BS, '\\\\')
|
813
|
+
.replace(FS, '\\/')
|
814
|
+
.replace(DQ, '\\"')
|
815
|
+
.replace(SQ, '\\\'')
|
816
|
+
.replace(CR, '\\r')
|
817
|
+
.replace(LS, '\\u2028')
|
818
|
+
.replace(PS, '\\u2029')
|
819
|
+
.replace(NL, '\\n')
|
820
|
+
.replace(LF, '\\f')
|
821
|
+
.replace(TB, '\\t');
|
822
|
+
}
|
823
|
+
return s;
|
824
|
+
};
|
775
825
|
|
776
826
|
})(dust);
|
777
827
|
|
778
|
-
if (typeof exports !==
|
779
|
-
if (typeof process !==
|
780
|
-
|
828
|
+
if (typeof exports !== 'undefined') {
|
829
|
+
if (typeof process !== 'undefined') {
|
830
|
+
require('./server')(dust);
|
781
831
|
}
|
782
832
|
module.exports = dust;
|
783
833
|
}
|
@@ -788,9 +838,11 @@ dust.compile = function(source, name) {
|
|
788
838
|
var ast = filterAST(dust.parse(source));
|
789
839
|
return compile(ast, name);
|
790
840
|
}
|
791
|
-
catch(err)
|
841
|
+
catch (err)
|
792
842
|
{
|
793
|
-
if(!err.line || !err.column)
|
843
|
+
if (!err.line || !err.column) {
|
844
|
+
throw err;
|
845
|
+
}
|
794
846
|
throw new SyntaxError(err.message + " At line : " + err.line + ", column : " + err.column);
|
795
847
|
}
|
796
848
|
};
|
@@ -827,35 +879,42 @@ dust.optimizers = {
|
|
827
879
|
path: noop,
|
828
880
|
literal: noop,
|
829
881
|
comment: nullify,
|
830
|
-
line:
|
831
|
-
col:
|
882
|
+
line: nullify,
|
883
|
+
col: nullify
|
832
884
|
};
|
833
885
|
|
834
886
|
dust.pragmas = {
|
835
887
|
esc: function(compiler, context, bodies, params) {
|
836
|
-
var old = compiler.auto
|
837
|
-
|
888
|
+
var old = compiler.auto,
|
889
|
+
out;
|
890
|
+
if (!context) {
|
891
|
+
context = 'h';
|
892
|
+
}
|
838
893
|
compiler.auto = (context === 's') ? '' : context;
|
839
|
-
|
894
|
+
out = compileParts(compiler, bodies.block);
|
840
895
|
compiler.auto = old;
|
841
896
|
return out;
|
842
897
|
}
|
843
898
|
};
|
844
899
|
|
845
900
|
function visit(context, node) {
|
846
|
-
var out = [node[0]]
|
847
|
-
|
848
|
-
|
849
|
-
|
901
|
+
var out = [node[0]],
|
902
|
+
i, len, res;
|
903
|
+
for (i=1, len=node.length; i<len; i++) {
|
904
|
+
res = dust.filterNode(context, node[i]);
|
905
|
+
if (res) {
|
906
|
+
out.push(res);
|
907
|
+
}
|
850
908
|
}
|
851
909
|
return out;
|
852
910
|
};
|
853
911
|
|
854
912
|
// Compacts consecutive buffer nodes into a single node
|
855
913
|
function compactBuffers(context, node) {
|
856
|
-
var out = [node[0]],
|
857
|
-
|
858
|
-
|
914
|
+
var out = [node[0]],
|
915
|
+
memo, i, len, res;
|
916
|
+
for (i=1, len=node.length; i<len; i++) {
|
917
|
+
res = dust.filterNode(context, node[i]);
|
859
918
|
if (res) {
|
860
919
|
if (res[0] === 'buffer') {
|
861
920
|
if (memo) {
|
@@ -881,8 +940,14 @@ var specialChars = {
|
|
881
940
|
"rb": "}"
|
882
941
|
};
|
883
942
|
|
884
|
-
function convertSpecial(context, node) {
|
885
|
-
|
943
|
+
function convertSpecial(context, node) {
|
944
|
+
return ['buffer', specialChars[node[1]]]
|
945
|
+
};
|
946
|
+
|
947
|
+
function noop(context, node) {
|
948
|
+
return node
|
949
|
+
};
|
950
|
+
|
886
951
|
function nullify(){};
|
887
952
|
|
888
953
|
function compile(ast, name) {
|
@@ -906,9 +971,10 @@ function compile(ast, name) {
|
|
906
971
|
|
907
972
|
function compileBlocks(context) {
|
908
973
|
var out = [],
|
909
|
-
blocks = context.blocks
|
974
|
+
blocks = context.blocks,
|
975
|
+
name;
|
910
976
|
|
911
|
-
for (
|
977
|
+
for (name in blocks) {
|
912
978
|
out.push("'" + name + "':" + blocks[name]);
|
913
979
|
}
|
914
980
|
if (out.length) {
|
@@ -921,9 +987,10 @@ function compileBlocks(context) {
|
|
921
987
|
function compileBodies(context) {
|
922
988
|
var out = [],
|
923
989
|
bodies = context.bodies,
|
924
|
-
blx = context.blocks
|
990
|
+
blx = context.blocks,
|
991
|
+
i, len;
|
925
992
|
|
926
|
-
for (
|
993
|
+
for (i=0, len=bodies.length; i<len; i++) {
|
927
994
|
out[i] = "function body_" + i + "(chk,ctx){"
|
928
995
|
+ blx + "return chk" + bodies[i] + ";}";
|
929
996
|
}
|
@@ -931,8 +998,9 @@ function compileBodies(context) {
|
|
931
998
|
};
|
932
999
|
|
933
1000
|
function compileParts(context, body) {
|
934
|
-
var parts = ''
|
935
|
-
|
1001
|
+
var parts = '',
|
1002
|
+
i, len;
|
1003
|
+
for (i=1, len=body.length; i<len; i++) {
|
936
1004
|
parts += dust.compileNode(context, body[i]);
|
937
1005
|
}
|
938
1006
|
return parts;
|
@@ -944,7 +1012,8 @@ dust.compileNode = function(context, node) {
|
|
944
1012
|
|
945
1013
|
dust.nodes = {
|
946
1014
|
body: function(context, node) {
|
947
|
-
var id = context.index++,
|
1015
|
+
var id = context.index++,
|
1016
|
+
name = "body_" + id;
|
948
1017
|
context.bodies[id] = compileParts(context, node);
|
949
1018
|
return name;
|
950
1019
|
},
|
@@ -1085,7 +1154,7 @@ dust.nodes = {
|
|
1085
1154
|
},
|
1086
1155
|
|
1087
1156
|
key: function(context, node) {
|
1088
|
-
return "ctx.
|
1157
|
+
return "ctx._get(false, [\"" + node[1] + "\"])";
|
1089
1158
|
},
|
1090
1159
|
|
1091
1160
|
path: function(context, node) {
|
@@ -1099,7 +1168,7 @@ dust.nodes = {
|
|
1099
1168
|
else
|
1100
1169
|
list.push("\"" + keys[i] + "\"");
|
1101
1170
|
}
|
1102
|
-
return "ctx.
|
1171
|
+
return "ctx._get(" + current + ",[" + list.join(',') + "])";
|
1103
1172
|
},
|
1104
1173
|
|
1105
1174
|
literal: function(context, node) {
|