gulpfile.js 18.4 KB
Newer Older
C
Catouse 已提交
1 2 3
var extend = require('extend'),
    runSequence = require('run-sequence'),
    fs = require('fs'),
C
Catouse 已提交
4
    chmod = require('gulp-chmod'),
C
Catouse 已提交
5 6 7 8 9 10 11 12 13
    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'),
14
    change = require('gulp-change'),
C
Catouse 已提交
15 16 17 18 19 20 21
    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'),
C
Catouse 已提交
22
    jsonminify = require('gulp-jsonminify'),
C
Catouse 已提交
23 24 25
    zui = require('./zui.json'),
    pkg = require('./package.json'),
    showFileDetail = true;
C
Catouse 已提交
26 27 28 29 30 31

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

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

C
Catouse 已提交
36
var today = moment();
C
Catouse 已提交
37
var typeSet = ['less', 'js', 'resource'],
C
Catouse 已提交
38 39
    lib = zui.lib,
    builds = zui.builds,
C
Catouse 已提交
40
    BANNER = ('/*!\n' +
C
Catouse 已提交
41 42 43 44
        ' * {title} - v{version} - {date}\n' +
        ' * {homepage}\n' +
        ' * GitHub: {repo} \n' +
        ' * Copyright (c) {year} {author}; Licensed {license}\n' +
C
Catouse 已提交
45 46
        ' */\n\n'),
    BANNER_OPTONS = {
C
Catouse 已提交
47 48 49 50 51 52 53 54
        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 已提交
55 56 57 58 59 60 61 62 63 64
    },
    BOOTSTRAP_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 formatBanner(options) {
    if(options && options.title) {
        options.title = BANNER_OPTONS.title + ': ' + options.title;
    }
    options = Object.assign({}, BANNER_OPTONS, options);
    return BANNER.format(options);
}
C
Catouse 已提交
65 66 67 68 69 70 71 72 73 74 75 76 77 78

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

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

79
function getItemList(list, items, ignoreDpds, ignoreBasic) {
C
Catouse 已提交
80 81
    items = items || [];

C
Catouse 已提交
82
    if(Array.isArray(list)) {
C
Catouse 已提交
83
        list.forEach(function(name) {
84 85
            if(name === 'basic' && ignoreBasic) return;
            getItemList(name, items, ignoreDpds, ignoreBasic);
C
Catouse 已提交
86
        });
87
    } else if(!(list === 'basic' && ignoreBasic)) {
C
Catouse 已提交
88
        var item = lib[list];
C
Catouse 已提交
89 90
        if(item && items.indexOf(list) < 0) {
            if(!ignoreDpds && item.dpds) {
91
                getItemList(item.dpds, items, ignoreDpds, ignoreBasic);
C
Catouse 已提交
92
            }
C
Catouse 已提交
93
            if(item.src) items.push(list);
C
Catouse 已提交
94 95 96 97 98 99 100 101 102 103 104 105 106 107 108
        }
    }

    return items;
}

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

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

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

111 112
    if(build.settingDpds) list = getItemList(build.settingDpds, list);
    list = getItemList(build.includes, list, build.ignoreDpds, build.ignoreBasic);
C
Catouse 已提交
113 114 115

    list.forEach(function(item) {
        var libItem = lib[item];
C
Catouse 已提交
116
        if(libItem && libItem.src) {
C
Catouse 已提交
117
            typeSet.forEach(function(type) {
C
Catouse 已提交
118
                if(libItem.src[type]) {
C
Catouse 已提交
119
                    libItem.src[type].forEach(function(file) {
C
Catouse 已提交
120
                        if(sources[type].indexOf(file) < 0) {
C
Catouse 已提交
121 122 123 124 125 126 127 128 129 130 131 132 133
                            sources[type].push(file);
                        }
                    });
                }
            });
        }
    });

    return sources;
}

function getSourceConfig(src) {
    var idx = src.lastIndexOf('//');
C
Catouse 已提交
134
    if(idx > 0) {
C
Catouse 已提交
135 136
        return {
            base: src.substr(0, idx + 1),
C
Catouse 已提交
137 138
            src: src.replace(/\/\//g, '/'),
            file: src.substr(idx + 2)
C
Catouse 已提交
139 140 141 142 143
        };
    }
    idx = src.lastIndexOf('/');
    return {
        base: src.substr(0, idx + 1),
C
Catouse 已提交
144 145
        src: src,
        file: src.substr(idx + 1)
C
Catouse 已提交
146 147 148 149 150
    }
}

function getBuildPath(build, type) {
    var path = build.dest;
C
Catouse 已提交
151
    if(build.subdirectories) {
C
Catouse 已提交
152 153 154 155 156 157 158 159 160 161 162 163 164 165
        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, '/');
}

166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187
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 已提交
188
function buildBundle(name, callback, type) {
C
Catouse 已提交
189
    name = name || 'all';
C
Catouse 已提交
190
    var build = builds[name];
C
Catouse 已提交
191 192
    var taskList = [],
        depTaskList = [];
C
Catouse 已提交
193 194

    // clean files
195
    if(!type && name === 'dist') {
C
Catouse 已提交
196
        del.sync('./dist/**/*');
197
    } else if(!type && name === 'doc') {
C
Catouse 已提交
198 199 200
        del.sync([
            './docs/js/**/*',
            './docs/css/**/*',
C
Catouse 已提交
201 202
            './docs/fonts/**/*'
        ]);
C
Catouse 已提交
203 204 205 206
    }

    if(!build) {
        if(name === 'all') {
C
Catouse 已提交
207
            console.log('           ========== BUILD ALL =========='.blue.bold);
C
Catouse 已提交
208 209 210 211 212 213 214 215 216 217 218 219
            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 已提交
220
                console.log(('        √  Build ' + 'ALL'.bold + ' success! ').green);
C
Catouse 已提交
221 222 223 224 225
                callback && callback();
            });
            return;
        } else {
            var buildLib = lib[name];
C
Catouse 已提交
226
            if(buildLib) {
C
Catouse 已提交
227 228 229
                build = {
                    title: buildLib.name,
                    dest: 'dist/lib/' + name + '/',
C
Catouse 已提交
230
                    filename: buildLib.filename || ((buildLib.source && buildLib.source !== 'Bootstrap') ? name : ('zui.' + name)),
C
Catouse 已提交
231
                    includes: [name],
C
Catouse 已提交
232 233 234 235
                    source: buildLib.source,
                    settingDpds: (buildLib.src && buildLib.src.less && buildLib.src.less.length) ? ['setting'] : null,
                    ignoreBasic: true,
                    ignoreDpds: buildLib.ignoreDpds !== undefined ? buildLib.ignoreDpds : true
C
Catouse 已提交
236 237
                };
            } else {
C
Catouse 已提交
238
                console.log(('           Cannot found the build config: ' + name).red);
C
Catouse 已提交
239 240 241
                return false;
            }
        }
C
Catouse 已提交
242
    } else if(build.bundles) {
C
Catouse 已提交
243 244
        console.log(('           === BUILD BUNDLES ' + name.toUpperCase() + ' [' + build.bundles.join(', ') + '] ===').blue.bold);
        var bundlesTaskList = [];
C
Catouse 已提交
245
        build.bundles.forEach(function(bundleName) {
C
Catouse 已提交
246 247 248
            gulp.task('build:' + bundleName, function(cb) {
                buildBundle(bundleName, cb, type);
            });
C
Catouse 已提交
249

C
Catouse 已提交
250
            bundlesTaskList.push('build:' + bundleName);
C
Catouse 已提交
251 252
        });

C
Catouse 已提交
253 254 255 256 257
        gulp.task('build:' + name + ':bundles', function(cb) {
            runSequence(bundlesTaskList, function() {
                console.log(('         √ Build BUNDLES ' + name.toUpperCase() + ' [' + build.bundles.join(', ') + '] success! ').green);
                cb();
            });
C
Catouse 已提交
258
        });
C
Catouse 已提交
259 260

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

263 264 265 266 267 268 269 270
    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 已提交
271
    console.log(('           --- build ' + name + ' ---').cyan.bold);
C
Catouse 已提交
272

C
Catouse 已提交
273
    var banner = formatBanner({title: build.title || name});
C
Catouse 已提交
274
    var source = getBuildSource(build),
C
Catouse 已提交
275 276
        bannerContent = (build.source && build.source !== 'Bootstrap') ?
        '' : banner + (build.bootstrapStatement ? BOOTSTRAP_STATEMENT : '');
C
Catouse 已提交
277 278

    if(source.js && source.js.length && (!type || type === 'js')) {
C
Catouse 已提交
279
        console.log(('         + Ready to process ' + source.js.length + ' javascript files.').bold);
C
Catouse 已提交
280 281 282 283
        source.js.forEach(function(f, idx) {
            if(f.indexOf('~/') === 0) {
                source.js[idx] = f = 'src/js/' + f.substr(2);
            }
C
Catouse 已提交
284
            if(showFileDetail) console.log(('         | ' + f).italic);
C
Catouse 已提交
285 286 287 288 289 290 291 292
        });

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

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

341 342 343 344
            if(name === 'colorset.less2js') {
                return gulpBuildColorsetJS(build, buildSourceFilePath, bannerContent);
            }

C
Catouse 已提交
345 346
            return gulp.src(buildSourceFilePath)
                .pipe(less())
C
Catouse 已提交
347
                .pipe(autoprefixer({
C
Catouse 已提交
348 349 350 351 352 353 354 355
                    browsers: ["Android 2.3",
                        "Android >= 4",
                        "Chrome >= 20",
                        "Firefox >= 24",
                        "Explorer >= 8",
                        "iOS >= 6",
                        "Opera >= 12",
                        "Safari >= 6"],
C
Catouse 已提交
356 357
                    cascade: true
                }))
C
Catouse 已提交
358 359
                .pipe(csscomb())
                .pipe(header(bannerContent))
C
Catouse 已提交
360
                .pipe(chmod(644))
C
Catouse 已提交
361
                .pipe(gulp.dest(destPath))
C
Catouse 已提交
362
                .on('end', function() {
C
Catouse 已提交
363
                    console.log('     css > '.yellow.bold + (destPath + build.filename + '.css').italic.underline);
C
Catouse 已提交
364 365
                })
                //.pipe(sourcemaps.init())
C
Catouse 已提交
366 367 368 369 370 371
                .pipe(cssmin({
                    compatibility: 'ie8',
                    keepSpecialComments: '*',
                    sourceMap: true,
                    advanced: false
                }))
C
Catouse 已提交
372 373 374
                .pipe(rename({
                    suffix: '.min'
                }))
C
Catouse 已提交
375

C
Catouse 已提交
376
                //.pipe(sourcemaps.write())
C
Catouse 已提交
377
                .pipe(chmod(644))
C
Catouse 已提交
378 379
                .pipe(gulp.dest(destPath))
                .on('end', function() {
C
Catouse 已提交
380
                    console.log('     css > '.yellow.bold + (destPath + build.filename + '.min.css').italic.underline);
C
Catouse 已提交
381
                });
C
Catouse 已提交
382 383 384 385 386
        });
        taskList.push('build:' + name + ':less');
    }

    if(source.resource && source.resource.length && (!type || type === 'resource')) {
C
Catouse 已提交
387
        console.log(('         + Ready to process ' + source.resource.length + ' resource files.').bold);
C
Catouse 已提交
388 389 390 391 392
        var destPath = getBuildPath(build, '');
        source.resource.forEach(function(f, idx) {
            if(f.indexOf('~/') === 0) {
                source.resource[idx] = f = 'src//' + f.substr(2);
            }
C
Catouse 已提交
393
            if(showFileDetail) console.log(('         | [' + idx + '] ' + f).italic);
C
Catouse 已提交
394 395
            gulp.task('build:' + name + ':resource:' + idx, function() {
                var sourceConfig = getSourceConfig(f);
C
Catouse 已提交
396 397 398
                return gulp.src(sourceConfig.src, {
                        base: sourceConfig.base
                    })
C
Catouse 已提交
399
                    .pipe(chmod(644))
C
Catouse 已提交
400 401 402 403
                    .pipe(gulp.dest(destPath))
                    .on('end', function() {
                        console.log('resource > '.yellow.bold + (destPath + sourceConfig.file).italic.underline);
                    });
C
Catouse 已提交
404 405 406 407 408
            });
            taskList.push('build:' + name + ':resource:' + idx);
        });
    }

C
Catouse 已提交
409 410
    if(taskList.length || depTaskList.length) {
        var completeCallback = function() {
C
Catouse 已提交
411
            console.log(('         √ Build ' + name.bold + ' success! ').green);
C
Catouse 已提交
412
            callback && callback();
C
Catouse 已提交
413
        };
C
Catouse 已提交
414

C
Catouse 已提交
415 416 417 418 419 420 421 422 423
        if(taskList.length) {
            if(depTaskList.length) {
                runSequence(depTaskList, taskList, completeCallback);
            } else {
                runSequence(taskList, completeCallback);
            }
        } else {
            runSequence(depTaskList, completeCallback);
        }
C
Catouse 已提交
424

C
Catouse 已提交
425
    } else {
C
Catouse 已提交
426
        console.log(('           No source files for build: ' + name).red);
C
Catouse 已提交
427 428 429 430 431 432 433
        callback && callback();
    }
}

gulp.task('build', function(callback) {
    var name = process.argv[3] || 'dist';
    if(name && name[0] === '-') name = name.substr(1);
C
Catouse 已提交
434
    if(name === 'lib') name = 'seperate';
C
Catouse 已提交
435 436
    var type = process.argv.length > 4 ? process.argv[4] : false;
    if(type && type[0] === '-') type = type.substr(1);
C
Catouse 已提交
437 438
    console.log('  BEGIN >> ' + (' Build ' + name.bold + ' ').inverse);
    buildBundle(name, function() {
C
Catouse 已提交
439
        console.log('    END >> ' + (' Build ' + name.bold + ' completed. ').green.inverse);
C
Catouse 已提交
440
    }, type);
C
Catouse 已提交
441 442
});

C
Catouse 已提交
443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470
function startWatchSrc(name) {
    if(name === 'lib') name = 'seperate';
    gulp.watch(["./src/less/**/*"], function(event) {
        buildBundle(name, function() {
            console.log(''.green + (' WATCH ' + name.bold + ' COMPLETED. ').yellow.inverse);
        }, 'less');
    });

    gulp.watch(["./src/js/**/*"], function(event) {
        if(event.path && (event.path.lastIndexOf('src/js/colorset.js') > -1) || event.path.lastIndexOf('src\\js\\colorset.js') > -1) return;
        buildBundle(name, function() {
            console.log(''.green + (' WATCH ' + name.bold + ' COMPLETED. ').yellow.inverse);
        }, 'js');
    });

    gulp.watch(["./src/fonts/**/*"], function(event) {
        buildBundle(name, function() {
            console.log(''.green + (' WATCH ' + name.bold + ' COMPLETED. ').yellow.inverse);
        }, 'resource');
    });
}

gulp.task('watch', function(callback) {
    var name = process.argv[3] || 'dist';
    if(name && name[0] === '-') name = name.substr(1);
    startWatchSrc(name);
});

C
Catouse 已提交
471
['dist', 'doc', 'theme', 'lib'].forEach(function(name) {
C
Catouse 已提交
472 473
    var depsTasks = (name == 'dist' || name == 'doc') ? ['minJSON'] : [];
    gulp.task(name, depsTasks, function(callback) {
C
Catouse 已提交
474
        console.log('  BEGIN >> ' + (' Build ' + name.bold + ' ').inverse);
C
Catouse 已提交
475
        buildBundle(name == 'lib' ? 'seperate' : name, function() {
476 477 478
            console.log('    END >> ' + (' Build ' + name.bold + ' completed. ').green.inverse);
            callback();
        });
C
Catouse 已提交
479 480 481
    });

    gulp.task('watch:' + name, function() {
C
Catouse 已提交
482
        startWatchSrc(name);
C
Catouse 已提交
483 484 485
    });
});

C
Catouse 已提交
486 487 488 489 490 491 492 493 494 495 496 497
gulp.task('minJSON', function(cb) {
    gulp.src(['./docs/index.json', './docs/icons.json'])
        .pipe(jsonminify())
        .pipe(rename({suffix: '.min'}))
        .pipe(gulp.dest('./docs/'));
    gulp.src(['zui.json'])
        .pipe(jsonminify())
        .pipe(rename({suffix: '.min'}))
        .pipe(gulp.dest('./docs/'));
    cb();
});

C
Catouse 已提交
498 499 500 501
gulp.task('prettify:js', function() {
    return gulp.src('./src/js/**/*')
        .pipe(prettify({
            logSuccess: true,
C
Catouse 已提交
502
            config: './.jsbeautifyrc',
C
Catouse 已提交
503 504
            mode: 'VERIFY_AND_WRITE'
        }))
C
Catouse 已提交
505
        .pipe(gulp.dest('./src/js/'));
C
Catouse 已提交
506 507 508 509
});

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

C
Catouse 已提交
510 511 512
gulp.task('default', function() {
    buildBundle('all');
});
C
Catouse 已提交
513

514 515 516
// Init custom gulp tasks
if(isFileExist("gulpfile.custom.js")) {
    require("./gulpfile.custom.js")(gulp, {
C
Catouse 已提交
517
        chmod: chmod,
518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536
        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
    });
}