gulpfile.js 16.6 KB
Newer Older
C
Catouse 已提交
1 2 3 4 5 6 7 8 9 10 11 12
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'),
13
    change = require('gulp-change'),
C
Catouse 已提交
14 15 16 17 18 19 20 21 22 23
    sourcemaps = require('gulp-sourcemaps'),
    prettify = require('gulp-jsbeautifier'),
    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
    }),
53
    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';
C
Catouse 已提交
54 55 56 57 58 59 60 61 62 63 64 65 66 67

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

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

68
function getItemList(list, items, ignoreDpds, ignoreBasic) {
C
Catouse 已提交
69 70
    items = items || [];

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

    return items;
}

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

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

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

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

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

    return sources;
}

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

function getBuildPath(build, type) {
    var path = build.dest;
C
Catouse 已提交
140
    if(build.subdirectories) {
C
Catouse 已提交
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, '/');
}

155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176
function gulpBuildColorsetJS(build, lessSrc, bannerContent) {
    var name = 'build:' + build.name;
    var destPath = getBuildPath(build, 'js');
    return gulp.src(lessSrc)
        .pipe(less())
        .pipe(rename({
            extname: '.js'
        }))
        .pipe(change(function(css, done) {
            css = css.replace(/\/\*\*/g, '').replace(/\*\*\//g, '');
            css = css.replace(/\.color-(\w+) \{\n  color: (#?\w+);\n\}/g, "        $1: '$2',");
            css = css.replace(',\n    };', '\n    };');
            css = css.replace('\n\n', '\n');
            done(null, css);
        }))
        .pipe(header(bannerContent))
        .pipe(gulp.dest(destPath))
        .on('end', function() {
            console.log('     js > '.yellow.bold + (destPath + build.filename + '.js').italic.underline);
        });
}

C
Catouse 已提交
177
function buildBundle(name, callback, type) {
C
Catouse 已提交
178
    name = name || 'all';
C
Catouse 已提交
179
    var build = builds[name];
C
Catouse 已提交
180 181
    var taskList = [],
        depTaskList = [];
C
Catouse 已提交
182 183

    // clean files
184
    if(!type && name === 'dist') {
C
Catouse 已提交
185
        del.sync('./dist/**/*');
186
    } else if(!type && name === 'doc') {
C
Catouse 已提交
187 188 189
        del.sync([
            './docs/js/**/*',
            './docs/css/**/*',
C
Catouse 已提交
190 191
            './docs/fonts/**/*'
        ]);
C
Catouse 已提交
192 193 194 195
    }

    if(!build) {
        if(name === 'all') {
C
Catouse 已提交
196
            console.log('           ========== BUILD ALL =========='.blue.bold);
C
Catouse 已提交
197 198 199 200 201 202 203 204 205 206 207 208
            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 已提交
209
                console.log(('        √  Build ' + 'ALL'.bold + ' success! ').green);
C
Catouse 已提交
210 211 212 213 214
                callback && callback();
            });
            return;
        } else {
            var buildLib = lib[name];
C
Catouse 已提交
215
            if(buildLib) {
C
Catouse 已提交
216 217 218 219 220
                build = {
                    title: buildLib.name,
                    dest: 'dist/lib/' + name + '/',
                    filename: name,
                    includes: [name],
221 222 223
                    thirdpart: buildLib.thirdpart,
                    settingDpds: ['setting'],
                    ignoreBasic: true
C
Catouse 已提交
224 225
                };
            } else {
C
Catouse 已提交
226
                console.log(('           Cannot found the build config: ' + name).red);
C
Catouse 已提交
227 228 229
                return false;
            }
        }
C
Catouse 已提交
230
    } else if(build.bundles) {
C
Catouse 已提交
231 232
        console.log(('           === BUILD BUNDLES ' + name.toUpperCase() + ' [' + build.bundles.join(', ') + '] ===').blue.bold);
        var bundlesTaskList = [];
C
Catouse 已提交
233
        build.bundles.forEach(function(bundleName) {
C
Catouse 已提交
234 235 236
            var bundleBuild = builds[bundleName];
            if(bundleBuild) {
                gulp.task('build:' + bundleName, function(cb) {
C
Catouse 已提交
237 238 239
                    buildBundle(bundleName, cb, type);
                });

C
Catouse 已提交
240
                bundlesTaskList.push('build:' + bundleName);
C
Catouse 已提交
241 242 243
            }
        });

C
Catouse 已提交
244 245 246 247 248
        gulp.task('build:' + name + ':bundles', function(cb) {
            runSequence(bundlesTaskList, function() {
                console.log(('         √ Build BUNDLES ' + name.toUpperCase() + ' [' + build.bundles.join(', ') + '] success! ').green);
                cb();
            });
C
Catouse 已提交
249
        });
C
Catouse 已提交
250 251

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

254 255 256 257 258 259 260 261
    if(build.includes && build.includes.indexOf('colorset.js') > -1) {
        gulp.task('build:colorset.less2js', function(cb) {
            buildBundle('colorset.less2js', cb, 'less');
        });

        depTaskList.push('build:colorset.less2js');
    }

C
Catouse 已提交
262
    console.log(('           --- build ' + name + ' ---').cyan.bold);
C
Catouse 已提交
263 264 265 266

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

    if(source.js && source.js.length && (!type || type === 'js')) {
C
Catouse 已提交
269
        console.log(('         + Ready to process ' + source.js.length + ' javascript files.').bold);
C
Catouse 已提交
270 271 272 273
        source.js.forEach(function(f, idx) {
            if(f.indexOf('~/') === 0) {
                source.js[idx] = f = 'src/js/' + f.substr(2);
            }
C
Catouse 已提交
274
            if(showFileDetail) console.log(('         | ' + f).italic);
C
Catouse 已提交
275 276 277 278 279 280 281 282 283
        });

        //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 已提交
284 285 286 287
                .on('end', function() {
                    console.log('      js > '.yellow.bold + (destPath + build.filename + '.js').italic.underline);
                })
                //.pipe(sourcemaps.init())
C
Catouse 已提交
288
                .pipe(uglify())
C
Catouse 已提交
289 290 291
                .pipe(rename({
                    suffix: '.min'
                }))
C
Catouse 已提交
292
                .pipe(header(bannerContent))
C
Catouse 已提交
293 294 295 296 297
                //.pipe(sourcemaps.write())
                .pipe(gulp.dest(destPath))
                .on('end', function() {
                    console.log('      js > '.yellow.bold + (destPath + build.filename + '.min.js').italic.underline);
                });
C
Catouse 已提交
298 299 300 301 302 303
        });
        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 已提交
304
        console.log(('         + Ready to process ' + source.less.length + ' less files.').bold);
C
Catouse 已提交
305 306 307 308 309 310 311 312 313
        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 已提交
314
                if(showFileDetail) console.log(('         | ' + f).italic);
C
Catouse 已提交
315 316 317 318
            } else {
                lessFileContent += '// @import "';
                lessFileContent += '../../' + f;
                lessFileContent += '" // FILE NOT FOUND;\n';
C
Catouse 已提交
319
                if(showFileDetail) console.log(('         - ' + f + ' [NOT FOUND]').red.italic);
C
Catouse 已提交
320 321 322 323 324 325 326 327 328 329
            }
        });

        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);

330 331 332 333
            if(name === 'colorset.less2js') {
                return gulpBuildColorsetJS(build, buildSourceFilePath, bannerContent);
            }

C
Catouse 已提交
334 335
            return gulp.src(buildSourceFilePath)
                .pipe(less())
C
Catouse 已提交
336 337 338 339
                .pipe(autoprefixer({
                    browsers: ['> 1%'],
                    cascade: true
                }))
C
Catouse 已提交
340 341 342
                .pipe(csscomb())
                .pipe(header(bannerContent))
                .pipe(gulp.dest(destPath))
C
Catouse 已提交
343
                .on('end', function() {
C
Catouse 已提交
344
                    console.log('     css > '.yellow.bold + (destPath + build.filename + '.css').italic.underline);
C
Catouse 已提交
345 346
                })
                //.pipe(sourcemaps.init())
C
Catouse 已提交
347 348 349 350 351 352
                .pipe(cssmin({
                    compatibility: 'ie8',
                    keepSpecialComments: '*',
                    sourceMap: true,
                    advanced: false
                }))
C
Catouse 已提交
353 354 355
                .pipe(rename({
                    suffix: '.min'
                }))
C
Catouse 已提交
356 357 358
                //.pipe(sourcemaps.write())
                .pipe(gulp.dest(destPath))
                .on('end', function() {
C
Catouse 已提交
359
                    console.log('     css > '.yellow.bold + (destPath + build.filename + '.min.css').italic.underline);
C
Catouse 已提交
360
                });
C
Catouse 已提交
361 362 363 364 365
        });
        taskList.push('build:' + name + ':less');
    }

    if(source.resource && source.resource.length && (!type || type === 'resource')) {
C
Catouse 已提交
366
        console.log(('         + Ready to process ' + source.resource.length + ' resource files.').bold);
C
Catouse 已提交
367 368 369 370 371
        var destPath = getBuildPath(build, '');
        source.resource.forEach(function(f, idx) {
            if(f.indexOf('~/') === 0) {
                source.resource[idx] = f = 'src//' + f.substr(2);
            }
C
Catouse 已提交
372
            if(showFileDetail) console.log(('         | [' + idx + '] ' + f).italic);
C
Catouse 已提交
373 374
            gulp.task('build:' + name + ':resource:' + idx, function() {
                var sourceConfig = getSourceConfig(f);
C
Catouse 已提交
375 376 377
                return gulp.src(sourceConfig.src, {
                        base: sourceConfig.base
                    })
C
Catouse 已提交
378 379 380 381
                    .pipe(gulp.dest(destPath))
                    .on('end', function() {
                        console.log('resource > '.yellow.bold + (destPath + sourceConfig.file).italic.underline);
                    });
C
Catouse 已提交
382 383 384 385 386
            });
            taskList.push('build:' + name + ':resource:' + idx);
        });
    }

C
Catouse 已提交
387 388
    if(taskList.length || depTaskList.length) {
        var completeCallback = function() {
C
Catouse 已提交
389
            console.log(('         √ Build ' + name.bold + ' success! ').green);
C
Catouse 已提交
390
            callback && callback();
C
Catouse 已提交
391
        };
C
Catouse 已提交
392

C
Catouse 已提交
393 394 395 396 397 398 399 400 401
        if(taskList.length) {
            if(depTaskList.length) {
                runSequence(depTaskList, taskList, completeCallback);
            } else {
                runSequence(taskList, completeCallback);
            }
        } else {
            runSequence(depTaskList, completeCallback);
        }
C
Catouse 已提交
402

C
Catouse 已提交
403
    } else {
C
Catouse 已提交
404
        console.log(('           No source files for build: ' + name).red);
C
Catouse 已提交
405 406 407 408 409 410 411 412 413
        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 已提交
414 415
    console.log('  BEGIN >> ' + (' Build ' + name.bold + ' ').inverse);
    buildBundle(name, function() {
C
Catouse 已提交
416
        console.log('    END >> ' + (' Build ' + name.bold + ' completed. ').green.inverse);
C
Catouse 已提交
417
    }, type);
C
Catouse 已提交
418 419
});

C
Catouse 已提交
420
['dist', 'doc', 'theme'].forEach(function(name) {
C
Catouse 已提交
421
    gulp.task(name, function(callback) {
C
Catouse 已提交
422
        console.log('  BEGIN >> ' + (' Build ' + name.bold + ' ').inverse);
423 424 425 426
        buildBundle(name, function() {
            console.log('    END >> ' + (' Build ' + name.bold + ' completed. ').green.inverse);
            callback();
        });
C
Catouse 已提交
427 428 429 430 431
    });

    gulp.task('watch:' + name, function() {
        gulp.watch(["./src/less/**/*"], function(event) {
            buildBundle(name, function() {
C
Catouse 已提交
432
                console.log(''.green + (' WATCH ' + name.bold + ' COMPLETED. ').yellow.inverse);
C
Catouse 已提交
433 434 435 436
            }, 'less');
        });

        gulp.watch(["./src/js/**/*"], function(event) {
C
Catouse 已提交
437
            if(event.path && event.path.lastIndexOf('src/js/colorset.js') > -1) return;
C
Catouse 已提交
438
            buildBundle(name, function() {
C
Catouse 已提交
439
                console.log(''.green + (' WATCH ' + name.bold + ' COMPLETED. ').yellow.inverse);
C
Catouse 已提交
440 441 442 443 444
            }, 'js');
        });

        gulp.watch(["./src/fonts/**/*"], function(event) {
            buildBundle(name, function() {
C
Catouse 已提交
445
                console.log(''.green + (' WATCH ' + name.bold + ' COMPLETED. ').yellow.inverse);
C
Catouse 已提交
446 447 448 449 450
            }, 'resource');
        });
    });
});

C
Catouse 已提交
451 452 453 454
gulp.task('prettify:js', function() {
    return gulp.src('./src/js/**/*')
        .pipe(prettify({
            logSuccess: true,
C
Catouse 已提交
455
            config: './.jsbeautifyrc',
C
Catouse 已提交
456 457
            mode: 'VERIFY_AND_WRITE'
        }))
C
Catouse 已提交
458
        .pipe(gulp.dest('./src/js/'));
C
Catouse 已提交
459 460 461 462
});

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

C
Catouse 已提交
463 464 465
gulp.task('default', function() {
    buildBundle('all');
});
C
Catouse 已提交
466

467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488
// Init custom gulp tasks
if(isFileExist("gulpfile.custom.js")) {
    require("./gulpfile.custom.js")(gulp, {
        less: less,
        cssmin: cssmin,
        csscomb: csscomb,
        autoprefixer: autoprefixer,
        concat: concat,
        header: header,
        uglify: uglify,
        rename: rename,
        change: change,
        sourcemaps: sourcemaps,
        prettify: prettify,
        buildBundle: buildBundle,
        zui: zui,
        pkg: pkg,
        del: del,
        mkdirp: mkdirp,
        runSequence: runSequence
    });
}