marionette_dust 0.0.2 → 0.0.3
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.
- 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) {
|