-
Notifications
You must be signed in to change notification settings - Fork 10
/
utils.js
298 lines (268 loc) · 9.89 KB
/
utils.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
/**
* A range of utility functions called by the Buildy object.
*
* Synchronous methods throw exceptions on error, async provides the error as a part of the callback.
*
* TODO: normalise destFile/outputFile attributes in tasks.
* TODO: normalise validation of o.source or sourceFile attributes.
*/
var sys = require('sys'),
util = require('util'),
fs = require('fs'),
path = require('path'),
events = require('events'),
cprf = require('buildy/lib/cprf'),
mkdirp = require('mkdirp').mkdirp;
/**
* Concatenate one or more files to a destination file or string.
*
* @method concatSync
* @param dest null|String String will be returned if null, or written to the specified filename.
* @param sourcefiles Array of files to read and concatenate.
* @param encoding source file encoding (default utf8)
*/
exports.concatSync = function(dest, sourcefiles, encoding) {
var content = '',
encoding = encoding || 'utf8';
try {
sourcefiles.forEach(function(f) {
content += fs.readFileSync(f, encoding) || '';
});
} catch(e) {
throw new Error('Could not read the files to be concatenated : ' + sourcefiles.toString() + ' ' + e);
}
try {
if (dest === null) {
return content;
} else {
fs.writeFileSync(dest, content, encoding);
}
} catch(e) {
throw new Error('Could not write the file to be concatenated :' + dest.toString());
}
};
/**
* Apply a template to an object, and write the output to a file, or return the string.
*
* @method applyTemplateSync
* @param dest null|String String will be returned if null, or written to the specified filename.
* @param template String filename of the template file to use.
* @param o Object object for which its properties will be used to generate the output.
* @param format String file encoding (default 'utf8')
*/
exports.applyTemplateSync = function(dest, template, o, format) {
var format = format || 'utf8',
templateContent = fs.readFileSync(template, format),
Handlebars = require('handlebars'),
hTemplate = Handlebars.compile(templateContent);
if (dest === null) {
return hTemplate(o);
} else {
fs.writeFileSync(dest, hTemplate(o));
}
};
/**
* Apply a string or file template using a model object to substitute variables.
*
* @todo change callback method signature to err,data
* @method applyTemplate
* @param o {Object} configuration containing .template (String template) or .templateFile (File template),
* .model (Object), .encoding (Template file Encoding) [Default 'utf8']
* @param callback {Function}
*/
exports.applyTemplate = function applyTemplate(o, callback) {
var Handlebars = require('handlebars'),
encoding = o.encoding || 'utf8',
fnTemplateResult = function fnLoadedTemplate(err, templateString) {
var hTemplate;
if (err) {
callback(err);
} else {
hTemplate = Handlebars.compile(templateString);
// TODO: file output, as specified by o.outputFile
callback(null, hTemplate(o.model));
}
};
// Deal with template file, get a string either way and pass it to fnTemplateResult()
if (o === undefined || ( o.templateFile === undefined && o.template === undefined ) ) {
callback('didnt supply a valid template or template file.');
} else {
if (o.hasOwnProperty('templateFile')) {
fs.readFile(o.templateFile, encoding, function(err, data) {
if (err) {
fnTemplateResult('Could not read specified template file: ' + o.templateFile);
} else {
fnTemplateResult(null, data);
}
});
} else if (o.hasOwnProperty('template')) {
fnTemplateResult(null, o.template);
}
}
};
/**
* Run JSLint|JSHint on a string or file.
*
* @method lint
* @param o {Object} Object containing properties .source | .sourceFile, string or file to lint respectively,
* .options {Object} JSLint options, .encoding {String} Encoding for files [default 'utf8']
* @param callback {Function} Callback function when lint has finished.
*/
exports.lint = function(o, callback) {
var linter = require('jslint/lib/linter.js'),
reporter = require('jslint/lib/reporter.js'),
result;
options = o.options || {};
encoding = o.encoding || 'utf8';
if (o.source && o.source.length > 0) {
result = linter.lint(o.source, options);
callback(false, result);
} else if (o.sourceFile && o.sourceFile.length > 0) {
fs.readFile(o.sourceFile, encoding, function(err, data) {
if (err) {
callback(err);
} else {
result = linter.lint(data.toString(encoding), options);
// TODO: report results in builder output, not here in utils
//reporter.report(o.sourceFile, result);
callback(false, result);
}
});
} else {
callback(true);
}
};
/**
* Minify the input using uglify
*
* @method minify
* @param o {Object} Minify parameters:
* o.source - source code as string
* o.sourceFile - source filename
* o.destFile - destination file to be written, otherwise the first argument to the complete
* o.encoding - file encoding [default 'utf8']
* event will be the output string.
* @param callback {Function} Callback when done
*/
exports.minify = function(o, callback) {
var min = function(o, callback) {
var jsp = require("uglify-js").parser,
pro = require("uglify-js").uglify,
encoding = o.encoding || 'utf8',
ast;
try {
ast = jsp.parse(o.source); // parse into syntax tree
ast = pro.ast_mangle(ast);
ast = pro.ast_squeeze(ast);
} catch (e) {
callback('The minify task failed, most likely the source file was unparseable. Please check your syntax. Error: ' + e.message);
return;
}
if (!o.destFile) {
callback(false, pro.gen_code(ast));
} else {
fs.writeFile(o.destFile, pro.gen_code(ast), encoding, function(err) {
if (err) {
callback(err);
} else {
callback(false, o.destFile);
}
});
}
};
if (o.sourceFile) {
fs.readFile(o.sourceFile, encoding, function(err, data) {
if (err) {
callback(err);
} else {
delete o.sourceFile;
o.source = data;
min(o, callback);
}
});
} else if (o.source) {
min(o, callback);
} else {
callback('No source or sourcefile was specified to be minified.');
}
};
/**
* CSSLint source file using csslint
*
* @todo change callback signature to standard err,data
* @method cssLint
* @param o {Object} Object containing at least one source property:
* { source: 'String' || sourceFile: 'Filename.js', options : { [CSSLint Options] }, encoding: 'utf8' }
* @param callback {Function} Callback function which receives one value, the result of csslint.
*/
exports.cssLint = function(o, callback) {
var csslint = require('csslint').CSSLint,
opts = o.options || {},
encoding = o.encoding || 'utf8',
result;
if (o.source && o.source.length > 0) {
result = csslint.verify(o.source, opts);
callback(false, result);
} else if (o.sourceFile && o.sourceFile.length > 0) {
fs.readFile(o.sourceFile, encoding, function(err, data) {
if (err) {
callback(err);
} else {
data = data.toString(encoding);
result = csslint.verify(data, opts);
callback(false, result);
}
});
} else {
callback('No source or sourcefile was specified to be css linted.');
}
};
/*
* Minify a css source file or string to a destination file or string using less.
*
* TODO: could also employ less in its intended usage, as a new task.
*
* @method cssMinify
* @param o {Object} Object containing at least one source property:
* { source: 'String' || sourceFile: 'Filename.js', destFile: 'Filename.js' || no destination returns string value }
* @param callback {Function}
* @public
*/
exports.cssMinify = function(o, callback) {
var less = require('less'),
encoding = o.encoding || 'utf8',
lessParser = new less.Parser,
fnCssFileResult = function fnCssFileResult(err, data) {
if (err) {
callback(err); // Cant read CSS file
} else {
lessParser.parse(data, function(err, tree) {
if (err) {
callback(err); // Cant parse CSS file
} else {
var cssCompressed = tree.toCSS({compress: true});
if (o.destFile) {
fs.writeFile(o.destFile, cssCompressed, encoding, function(err) {
if (err) {
callback(err); // Cant write CSS file
} else {
callback(false, o.destFile);
}
});
} else {
callback(false, cssCompressed);
}
}
});
}
};
if (!(o.source || o.sourceFile)) {
callback('No source or sourcefile was specified to be css minified.');
} else {
if (o.sourceFile) {
fs.readFile(o.sourceFile, encoding, fnCssFileResult);
} else if (o.source) {
fnCssFileResult(false, o.source);
}
}
};