gulpfile.js 14.3 KB
Newer Older
C
Catouse 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
var extend = require('extend'),
    runSequence = require('run-sequence'),
    fs = require('fs'),
    moment = require('moment'),
    less = require('gulp-less'),
    cssmin = require('gulp-cssmin'),
    csscomb = require('gulp-csscomb'),
    autoprefixer = require('gulp-autoprefixer'),
    concat = require('gulp-concat'),
    header = require('gulp-header'),
    uglify = require('gulp-uglify'),
    rename = require('gulp-rename'),
    sourcemaps = require('gulp-sourcemaps'),
    prettify = require('gulp-jsbeautifier'),
    lessPluginCleanCSS = require('less-plugin-clean-css'),
    mkdirp = require('mkdirp'),
    del = require('del'),
    format = require('string-format').extend(String.prototype),
    colors = require('colors'),
    gulp = require('gulp'),
    zui = require('./zui.json'),
    pkg = require('./package.json'),
    showFileDetail = true;
C
Catouse 已提交
24 25 26 27 28 29

// Disable the 'possible EventEmitter memory leak detected' warning.
gulp.setMaxListeners(0);

// try load zui.custom.json and merge into zui.
try {
C
Catouse 已提交
30
    var zuicustom = require('./zui.custom.json');
C
Catouse 已提交
31 32 33
    if(zuicustom) extend(true, zui, zuicustom);
} catch(e) {}

C
Catouse 已提交
34
var today = moment();
C
Catouse 已提交
35
var typeSet = ['less', 'js', 'resource'],
C
Catouse 已提交
36 37 38
    lib = zui.lib,
    builds = zui.builds,
    banner = ('/*!\n' +
C
Catouse 已提交
39 40 41 42 43
        ' * {title} - v{version} - {date}\n' +
        ' * {homepage}\n' +
        ' * GitHub: {repo} \n' +
        ' * Copyright (c) {year} {author}; Licensed {license}\n' +
        ' */\n\n').format({
C
Catouse 已提交
44 45 46 47 48 49 50 51 52
        title: pkg.title || pkg.name,
        version: pkg.version,
        date: today.format('YYYY-MM-DD'),
        homepage: pkg.homepage,
        repo: pkg.repository.url,
        year: today.format('YYYY'),
        author: pkg.author,
        license: pkg.license
    }),
C
Catouse 已提交
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
    statement = '/* Some code copy from Bootstrap v3.0.0 by @fat and @mdo. (Copyright 2013 Twitter, Inc. Licensed under http://www.apache.org/licenses/)*/\n\n';

function tryStatSync(path) {
    try {
        return fs.statSync(path);
    } catch(e) {
        return false;
    }
}

function isFileExist(path) {
    var stats = tryStatSync(path);
    return stats && stats.isFile();
}

function getItemList(list, items, ignoreDpds) {
    items = items || [];

C
Catouse 已提交
71
    if(Array.isArray(list)) {
C
Catouse 已提交
72 73 74 75 76
        list.forEach(function(name) {
            getItemList(name, items, ignoreDpds);
        });
    } else {
        var item = lib[list];
C
Catouse 已提交
77 78
        if(item && items.indexOf(list) < 0) {
            if(!ignoreDpds && item.dpds) {
C
Catouse 已提交
79 80
                getItemList(item.dpds, items, ignoreDpds);
            }
C
Catouse 已提交
81
            if(item.src) items.push(list);
C
Catouse 已提交
82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
        }
    }

    return items;
}

function getBuildSource(build) {
    var list = [];

    var sources = {
        less: [],
        js: [],
        resource: []
    };

C
Catouse 已提交
97
    if(!Array.isArray(list)) list = [list];
C
Catouse 已提交
98

C
Catouse 已提交
99
    if(build.basicDpds) list = getItemList(build.basicDpds, list);
C
Catouse 已提交
100 101 102 103
    list = getItemList(build.includes, list, build.ignoreDpds);

    list.forEach(function(item) {
        var libItem = lib[item];
C
Catouse 已提交
104
        if(libItem && libItem.src) {
C
Catouse 已提交
105
            typeSet.forEach(function(type) {
C
Catouse 已提交
106
                if(libItem.src[type]) {
C
Catouse 已提交
107
                    libItem.src[type].forEach(function(file) {
C
Catouse 已提交
108
                        if(sources[type].indexOf(file) < 0) {
C
Catouse 已提交
109 110 111 112 113 114 115 116 117 118 119 120 121
                            sources[type].push(file);
                        }
                    });
                }
            });
        }
    });

    return sources;
}

function getSourceConfig(src) {
    var idx = src.lastIndexOf('//');
C
Catouse 已提交
122
    if(idx > 0) {
C
Catouse 已提交
123 124
        return {
            base: src.substr(0, idx + 1),
C
Catouse 已提交
125 126
            src: src.replace(/\/\//g, '/'),
            file: src.substr(idx + 2)
C
Catouse 已提交
127 128 129 130 131
        };
    }
    idx = src.lastIndexOf('/');
    return {
        base: src.substr(0, idx + 1),
C
Catouse 已提交
132 133
        src: src,
        file: src.substr(idx + 1)
C
Catouse 已提交
134 135 136 137 138
    }
}

function getBuildPath(build, type) {
    var path = build.dest;
C
Catouse 已提交
139
    if(build.subdirectories) {
C
Catouse 已提交
140 141 142 143 144 145 146 147 148 149 150 151 152 153 154
        path += '/' + type + '/';
    }
    if(path.indexOf('.') !== 0) {
        path = './' + path;
    }
    return path.replace(/\/\//g, '/').replace(/\/\//g, '/');
}

function getBuildDestFilename(build, type, suffix) {
    var file = getBuildPath(build, type);
    file += '/' + build.filename + '.' + (suffix || type);
    return file.replace(/\/\//g, '/');
}

function buildBundle(name, callback, type) {
C
Catouse 已提交
155
    name = name || 'all';
C
Catouse 已提交
156
    var build = builds[name];
C
Catouse 已提交
157 158
    var taskList = [],
        depTaskList = [];
C
Catouse 已提交
159 160

    // clean files
161
    if(!type && name === 'dist') {
C
Catouse 已提交
162
        del.sync('./dist/**/*');
163
    } else if(!type && name === 'doc') {
C
Catouse 已提交
164 165 166
        del.sync([
            './docs/js/**/*',
            './docs/css/**/*',
C
Catouse 已提交
167 168
            './docs/fonts/**/*'
        ]);
C
Catouse 已提交
169 170 171 172
    }

    if(!build) {
        if(name === 'all') {
C
Catouse 已提交
173
            console.log('           ========== BUILD ALL =========='.blue.bold);
C
Catouse 已提交
174 175 176 177 178 179 180 181 182 183 184 185
            var buildList = Object.keys(builds);
            buildList.forEach(function(nm) {
                build = builds[nm];
                if(build && !build.bundles) {
                    var taskName = 'build:' + nm;
                    gulp.task(taskName, function(cb) {
                        buildBundle(nm, cb, type)
                    });
                    taskList.push(taskName);
                }
            });
            if(taskList.length) runSequence(taskList, function() {
C
Catouse 已提交
186
                console.log(('        √  Build ' + 'ALL'.bold + ' success! ').green);
C
Catouse 已提交
187 188 189 190 191
                callback && callback();
            });
            return;
        } else {
            var buildLib = lib[name];
C
Catouse 已提交
192
            if(buildLib) {
C
Catouse 已提交
193 194 195 196 197 198 199 200
                build = {
                    title: buildLib.name,
                    dest: 'dist/lib/' + name + '/',
                    filename: name,
                    includes: [name],
                    thirdpart: buildLib.thirdpart
                };
            } else {
C
Catouse 已提交
201
                console.log(('           Cannot found the build config: ' + name).red);
C
Catouse 已提交
202 203 204
                return false;
            }
        }
C
Catouse 已提交
205
    } else if(build.bundles) {
C
Catouse 已提交
206 207
        console.log(('           === BUILD BUNDLES ' + name.toUpperCase() + ' [' + build.bundles.join(', ') + '] ===').blue.bold);
        var bundlesTaskList = [];
C
Catouse 已提交
208
        build.bundles.forEach(function(bundleName) {
C
Catouse 已提交
209 210 211
            var bundleBuild = builds[bundleName];
            if(bundleBuild) {
                gulp.task('build:' + bundleName, function(cb) {
C
Catouse 已提交
212 213 214
                    buildBundle(bundleName, cb, type);
                });

C
Catouse 已提交
215
                bundlesTaskList.push('build:' + bundleName);
C
Catouse 已提交
216 217 218
            }
        });

C
Catouse 已提交
219 220 221 222 223
        gulp.task('build:' + name + ':bundles', function(cb) {
            runSequence(bundlesTaskList, function() {
                console.log(('         √ Build BUNDLES ' + name.toUpperCase() + ' [' + build.bundles.join(', ') + '] success! ').green);
                cb();
            });
C
Catouse 已提交
224
        });
C
Catouse 已提交
225 226

        depTaskList.push('build:' + name + ':bundles');
C
Catouse 已提交
227 228
    }

C
Catouse 已提交
229
    console.log(('           --- build ' + name + ' ---').cyan.bold);
C
Catouse 已提交
230 231 232 233

    var source = getBuildSource(build),
        bannerContent = build.thirdpart ?
        '' : banner + (build.bootstrapStatement ? statement : '');
C
Catouse 已提交
234 235

    if(source.js && source.js.length && (!type || type === 'js')) {
C
Catouse 已提交
236
        console.log(('         + Ready to process ' + source.js.length + ' javascript files.').bold);
C
Catouse 已提交
237 238 239 240
        source.js.forEach(function(f, idx) {
            if(f.indexOf('~/') === 0) {
                source.js[idx] = f = 'src/js/' + f.substr(2);
            }
C
Catouse 已提交
241
            if(showFileDetail) console.log(('         | ' + f).italic);
C
Catouse 已提交
242 243 244 245 246 247 248 249 250
        });

        //ar taskName = 'build:' + name + ':js';
        gulp.task('build:' + name + ':js', function() {
            var destPath = getBuildPath(build, 'js');
            return gulp.src(source.js)
                .pipe(concat(build.filename + '.js'))
                .pipe(header(bannerContent))
                .pipe(gulp.dest(destPath))
C
Catouse 已提交
251 252 253 254
                .on('end', function() {
                    console.log('      js > '.yellow.bold + (destPath + build.filename + '.js').italic.underline);
                })
                //.pipe(sourcemaps.init())
C
Catouse 已提交
255
                .pipe(uglify())
C
Catouse 已提交
256 257 258
                .pipe(rename({
                    suffix: '.min'
                }))
C
Catouse 已提交
259
                .pipe(header(bannerContent))
C
Catouse 已提交
260 261 262 263 264
                //.pipe(sourcemaps.write())
                .pipe(gulp.dest(destPath))
                .on('end', function() {
                    console.log('      js > '.yellow.bold + (destPath + build.filename + '.min.js').italic.underline);
                });
C
Catouse 已提交
265 266 267 268 269 270
        });
        taskList.push('build:' + name + ':js');
    }

    if(source.less && source.less.length && (!type || type === 'less')) {
        var lessFileContent = '// \n// ' + build.title + '\n// Build config: ' + name + '\n//\n// This file generated by ZUI builder automatically at ' + today.toString() + '.\n//\n\n';
C
Catouse 已提交
271
        console.log(('         + Ready to process ' + source.less.length + ' less files.').bold);
C
Catouse 已提交
272 273 274 275 276 277 278 279 280
        source.less.forEach(function(f, idx) {
            if(f.indexOf('~/') === 0) {
                source.less[idx] = f = 'src/less/' + f.substr(2);
            }

            if(isFileExist(f)) {
                lessFileContent += '@import "';
                lessFileContent += '../../' + f;
                lessFileContent += '";\n';
C
Catouse 已提交
281
                if(showFileDetail) console.log(('         | ' + f).italic);
C
Catouse 已提交
282 283 284 285
            } else {
                lessFileContent += '// @import "';
                lessFileContent += '../../' + f;
                lessFileContent += '" // FILE NOT FOUND;\n';
C
Catouse 已提交
286
                if(showFileDetail) console.log(('         - ' + f + ' [NOT FOUND]').red.italic);
C
Catouse 已提交
287 288 289 290 291 292 293 294 295 296 297 298
            }
        });

        gulp.task('build:' + name + ':less', function() {
            var buildSourceFilePath = './build/less/' + build.filename + '.less';
            var destPath = getBuildPath(build, 'css');

            mkdirp.sync('./build/less/');
            fs.writeFileSync(buildSourceFilePath, lessFileContent);

            return gulp.src(buildSourceFilePath)
                .pipe(less())
C
Catouse 已提交
299 300 301 302
                .pipe(autoprefixer({
                    browsers: ['> 1%'],
                    cascade: true
                }))
C
Catouse 已提交
303 304 305
                .pipe(csscomb())
                .pipe(header(bannerContent))
                .pipe(gulp.dest(destPath))
C
Catouse 已提交
306 307 308 309
                .on('end', function() {
                    console.log('    less > '.yellow.bold + (destPath + build.filename + '.css').italic.underline);
                })
                //.pipe(sourcemaps.init())
C
Catouse 已提交
310
                .pipe(cssmin())
C
Catouse 已提交
311 312 313
                .pipe(rename({
                    suffix: '.min'
                }))
C
Catouse 已提交
314
                .pipe(header(bannerContent))
C
Catouse 已提交
315 316 317 318 319
                //.pipe(sourcemaps.write())
                .pipe(gulp.dest(destPath))
                .on('end', function() {
                    console.log('    less > '.yellow.bold + (destPath + build.filename + '.min.css').italic.underline);
                });
C
Catouse 已提交
320 321 322 323 324
        });
        taskList.push('build:' + name + ':less');
    }

    if(source.resource && source.resource.length && (!type || type === 'resource')) {
C
Catouse 已提交
325
        console.log(('         + Ready to process ' + source.resource.length + ' resource files.').bold);
C
Catouse 已提交
326 327 328 329 330
        var destPath = getBuildPath(build, '');
        source.resource.forEach(function(f, idx) {
            if(f.indexOf('~/') === 0) {
                source.resource[idx] = f = 'src//' + f.substr(2);
            }
C
Catouse 已提交
331
            if(showFileDetail) console.log(('         | [' + idx + '] ' + f).italic);
C
Catouse 已提交
332 333
            gulp.task('build:' + name + ':resource:' + idx, function() {
                var sourceConfig = getSourceConfig(f);
C
Catouse 已提交
334 335 336
                return gulp.src(sourceConfig.src, {
                        base: sourceConfig.base
                    })
C
Catouse 已提交
337 338 339 340
                    .pipe(gulp.dest(destPath))
                    .on('end', function() {
                        console.log('resource > '.yellow.bold + (destPath + sourceConfig.file).italic.underline);
                    });
C
Catouse 已提交
341 342 343 344 345
            });
            taskList.push('build:' + name + ':resource:' + idx);
        });
    }

C
Catouse 已提交
346 347
    if(taskList.length || depTaskList.length) {
        var completeCallback = function() {
C
Catouse 已提交
348
            console.log(('         √ Build ' + name.bold + ' success! ').green);
C
Catouse 已提交
349
            callback && callback();
C
Catouse 已提交
350
        };
C
Catouse 已提交
351

C
Catouse 已提交
352 353 354 355 356 357 358 359 360
        if(taskList.length) {
            if(depTaskList.length) {
                runSequence(depTaskList, taskList, completeCallback);
            } else {
                runSequence(taskList, completeCallback);
            }
        } else {
            runSequence(depTaskList, completeCallback);
        }
C
Catouse 已提交
361

C
Catouse 已提交
362
    } else {
C
Catouse 已提交
363
        console.log(('           No source files for build: ' + name).red);
C
Catouse 已提交
364 365 366 367 368 369 370 371 372
        callback && callback();
    }
}

gulp.task('build', function(callback) {
    var name = process.argv[3] || 'dist';
    if(name && name[0] === '-') name = name.substr(1);
    var type = process.argv.length > 4 ? process.argv[4] : false;
    if(type && type[0] === '-') type = type.substr(1);
C
Catouse 已提交
373 374
    console.log('  BEGIN >> ' + (' Build ' + name.bold + ' ').inverse);
    buildBundle(name, function() {
C
Catouse 已提交
375
        console.log('    END >> ' + (' Build ' + name.bold + ' completed. ').green.inverse);
C
Catouse 已提交
376
    }, type);
C
Catouse 已提交
377 378 379 380
});

['dist', 'doc'].forEach(function(name) {
    gulp.task(name, function(callback) {
C
Catouse 已提交
381
        console.log('  BEGIN >> ' + (' Build ' + name.bold + ' ').inverse);
C
Catouse 已提交
382 383 384 385 386 387
        buildBundle(name, callback);
    });

    gulp.task('watch:' + name, function() {
        gulp.watch(["./src/less/**/*"], function(event) {
            buildBundle(name, function() {
C
Catouse 已提交
388
                console.log(''.green + (' WATCH ' + name.bold + ' COMPLETED. ').yellow.inverse);
C
Catouse 已提交
389 390 391 392 393
            }, 'less');
        });

        gulp.watch(["./src/js/**/*"], function(event) {
            buildBundle(name, function() {
C
Catouse 已提交
394
                console.log(''.green + (' WATCH ' + name.bold + ' COMPLETED. ').yellow.inverse);
C
Catouse 已提交
395 396 397 398 399
            }, 'js');
        });

        gulp.watch(["./src/fonts/**/*"], function(event) {
            buildBundle(name, function() {
C
Catouse 已提交
400
                console.log(''.green + (' WATCH ' + name.bold + ' COMPLETED. ').yellow.inverse);
C
Catouse 已提交
401 402 403 404 405
            }, 'resource');
        });
    });
});

C
Catouse 已提交
406 407 408 409 410 411 412 413 414 415 416 417
gulp.task('prettify:js', function() {
    return gulp.src('./src/js/**/*')
        .pipe(prettify({
            logSuccess: true,
            config: '.jsbeautifyrc',
            mode: 'VERIFY_AND_WRITE'
        }))
        .pipe(gulp.dest('./dist'));
});

gulp.task('prettify', ['prettify:js']);

C
Catouse 已提交
418 419 420
gulp.task('default', function() {
    buildBundle('all');
});
C
Catouse 已提交
421