UNPKG

8.58 kBJavaScriptView Raw
1'use strict';
2
3var exit = process.exit.bind(process);
4
5var fs = require('fs'),
6 path = require('path'),
7 util = require('gulp-util'),
8 debug = require('gulp-debug'),
9 watch = require('gulp-watch'),
10 filter = require('gulp-filter'),
11 sequence = require('gulp-sequence');
12
13var getData = require('./utils/data');
14
15var mainBowerFiles = require('main-bower-files');
16
17var errorHandler = function(e) {
18 util.log(util.colors.red(e.message || e.toString()));
19 this.emit('end');
20};
21
22function expandVariables(obj, data) {
23 if (typeof obj === 'string') {
24 return obj.replace(/\$\{(\w+)\}/g, function(match, key) {
25 return data[key] || match;
26 });
27 }
28
29 if (typeof obj === 'object') {
30 for (var key in obj) {
31 obj[key] = expandVariables(obj[key], data);
32 }
33 }
34
35 return obj;
36}
37
38function to_array(obj) {
39 return Array.isArray(obj) ? obj : (obj ? [obj] : []);
40}
41
42function is_file(fullpath) {
43 return fs.existsSync(fullpath) && fs.statSync(fullpath).isFile();
44}
45
46function is_dir(fullpath) {
47 return fs.existsSync(fullpath) && fs.statSync(fullpath).isDirectory();
48}
49
50function hook(chain, set) {
51 if (set) {
52 (Array.isArray(set) ? set : [set])
53 .forEach(function(task) {
54 chain = task(chain, errorHandler)
55 .on('error', errorHandler);
56 });
57 }
58
59 return chain;
60}
61
62module.exports = function(options) {
63 options = options || {};
64
65 var gulp = options.gulp;
66
67 if (!gulp) {
68 util.log(util.colors.red('Missing the main `gulp` instance to work'));
69 exit(1);
70 }
71
72 var base = typeof util.env.base === 'string' ? util.env.base : 'default',
73 base_dir = path.join(process.cwd(), 'src', options.cwd || '', (util.env.base || options.base) !== false ? base : '');
74
75 if (!is_dir(base_dir)) {
76 util.log(util.colors.red('The specified base directory `' + base + '` is missing'));
77 exit(1);
78 }
79
80 var isBuild = options.build || util.env.build,
81 sources = options.files || {},
82 params = options.params || {};
83
84 params.base = base;
85 options.build = !!isBuild;
86
87 if (options.bundle === true) {
88 options.bundle = {
89 compact: true
90 };
91 }
92
93 if (typeof options.bundle === 'object') {
94 options.bundle.compact = options.bundle.compact !== false;
95 }
96
97 var _errorHandler = errorHandler;
98
99 errorHandler = function(e) {
100 _errorHandler.call(this, e);
101
102 if (isBuild) {
103 exit(1);
104 }
105 };
106
107 sources.filter = sources.filter || [];
108 sources.vendor = sources.vendor || '';
109 sources.bower = sources.bower || '';
110 sources.env = sources.env || '';
111 sources.dest = sources.dest || '';
112 sources.views = sources.views || {};
113 sources.fonts = sources.fonts || {};
114 sources.styles = sources.styles || {};
115 sources.images = sources.images || {};
116 sources.sprites = sources.sprites || {};
117 sources.scripts = sources.scripts || {};
118
119 var env_file = path.join(base_dir, sources.env || 'env.yml');
120
121 options.paths = expandVariables({
122 fonts: {
123 on: path.join(base_dir, sources.fonts.src || 'fonts', '**/*.{ttf,otf,eot,woff,woff2,svg}'),
124 cwd: path.join(base_dir, sources.fonts.src || 'fonts'),
125 dest: sources.fonts.dest || 'fonts',
126 glob: '**/*.{ttf,otf,eot,woff,woff2,svg}'
127 },
128 images: {
129 on: path.join(base_dir, sources.images.src || 'images', '**/*.{jpg,jpeg,png,svg}'),
130 cwd: path.join(base_dir, sources.images.src || 'images'),
131 dest: sources.images.dest || 'img',
132 glob: '**/*.{jpg,jpeg,png,svg}'
133 },
134 sprites: {
135 on: path.join(base_dir, sources.sprites.src || 'sprites', '**/*.png'),
136 cwd: path.join(base_dir, sources.sprites.src || 'sprites'),
137 dest: sources.sprites.dest || 'img',
138 glob: '**/*.png'
139 },
140 styles: {
141 on: [
142 path.join(path.dirname(env_file), '_site/**/*.{variables,overrides}'),
143 path.join(base_dir, sources.styles.src || 'styles', '**/*.less'),
144 env_file
145 ],
146 cwd: path.join(base_dir, sources.styles.src || 'styles'),
147 dest: sources.styles.dest || 'css',
148 glob: '**/' + (options.bundle ? 'index' : '*') + '.less',
149 filter: sources.styles.filter || []
150 },
151 scripts: {
152 on: path.join(base_dir, sources.scripts.src || 'scripts', '**/*.{coffee,litcoffee}'),
153 cwd: path.join(base_dir, sources.scripts.src || 'scripts'),
154 dest: sources.scripts.dest || 'js',
155 glob: '**/*.{coffee,litcoffee}',
156 filter: sources.scripts.filter || []
157 },
158 views: {
159 on: [
160 path.join(base_dir, sources.views.src || 'views', '**/*.*'),
161 path.join(path.dirname(env_file), 'data/**/*.yml'),
162 path.join(process.cwd(), 'data/**/*.yml')
163 ],
164 ext: sources.views.ext || '.html',
165 cwd: path.join(base_dir, sources.views.src || 'views'),
166 dest: sources.views.dest || '',
167 glob: '**/*.jade',
168 filter: sources.views.filter || []
169 },
170 data: {
171 src: [
172 path.join(path.dirname(env_file), 'data'),
173 path.join(process.cwd(), 'data')
174 ],
175 glob: '**/*.yml'
176 },
177 vendor: sources.vendor || 'vendor',
178 bower: path.join(process.cwd(), sources.bower || ''),
179 dest: path.join(process.cwd(), sources.dest || 'generated'),
180 env: env_file
181 }, params);
182
183 options.env = util.env;
184
185 var copyTask = require('./tasks/copy');
186
187 var rainbow = {
188 clean: require('./tasks/clean')(options),
189 fonts: copyTask(options, 'fonts'),
190 images: copyTask(options, 'images'),
191 sprites: require('./tasks/sprites')(options),
192 scripts: require('./tasks/scripts')(options),
193 install: require('./tasks/install')(options),
194 server: require('./tasks/server')(options),
195 styles: require('./tasks/styles')(options),
196 vendor: require('./tasks/vendor')(options),
197 views: require('./tasks/views')(options)
198 };
199
200 var main = [],
201 tasks = [];
202
203 if (isBuild || options.env.clean === true) {
204 tasks.push('clean');
205 }
206
207 if (is_file(path.join(options.paths.bower, 'bower.json'))) {
208 Array.prototype.push.call(tasks, 'install', 'vendor');
209 }
210
211 ['fonts', 'images', 'sprites', 'styles', 'scripts', 'views']
212 .forEach(function(task) {
213 if (is_dir(options.paths[task].cwd)) {
214 tasks.push(task);
215 }
216 });
217
218 if (options.server === true && !isBuild) {
219 tasks.push('server');
220 }
221
222 tasks
223 .forEach(function(task) {
224 var files = options.paths[task],
225 callback = rainbow[task];
226
227 if (to_array(sources.skip).indexOf(task) > -1) {
228 return;
229 }
230
231 var prefix = options.prefix ? options.prefix + ':' : 'rainbow:';
232
233 if (callback) {
234 main.push(prefix + task);
235
236 if (typeof callback === 'function') {
237 gulp.task(prefix + task, callback);
238 } else {
239 gulp.task(prefix + task, function() {
240 var chain = gulp.src(callback.src);
241
242 chain = chain
243 .pipe(filter(['**', '!**/_*', '!**/_*/**']
244 .concat(to_array(sources.filter))
245 .concat(to_array(files.filter))));
246
247 if (typeof callback.check === 'function' && (options.env.check !== false)) {
248 chain = hook(chain, callback.check);
249 }
250
251 chain = hook(chain, sources[task].before);
252
253 if (typeof callback.pipe === 'function') {
254 chain = hook(chain, callback.pipe);
255 }
256
257 return hook(chain, sources[task].after)
258 .pipe(gulp.dest(callback.dest))
259 .pipe(debug({ title: prefix + task }));
260 });
261 }
262
263 if (files && files.on && !isBuild) {
264 watch(files.on, function() {
265 gulp.start(prefix + task);
266 });
267 }
268 } else {
269 util.log(util.colors.red('Unknown rainbow-task `' + task + '`'));
270 exit(1);
271 }
272 });
273
274 if (options.before) {
275 Array.prototype.unshift.apply(main, to_array(options.before));
276 }
277
278 if (options.after) {
279 Array.prototype.push.apply(main, to_array(options.after));
280 }
281
282 if (options.prefix) {
283 return sequence.use(gulp).apply(null, main);
284 }
285
286 gulp.task('rainbow', sequence.use(gulp).apply(null, main));
287};
288
289module.exports.bowerFiles = function(from) {
290 var bower_dir = path.resolve(from, 'bower_components');
291
292 return mainBowerFiles({
293 paths: {
294 bowerDirectory: path.relative(process.cwd(), bower_dir),
295 bowerJson: path.join(from, 'bower.json')
296 }
297 });
298};
299
300module.exports.server = function(root) {
301 return require('./tasks/server')({
302 paths: { dest: root },
303 env: util.env
304 });
305};
306
307module.exports.data = getData;