/**
* @author Donii Sergii <doniysa@gmail.com>
*/
/**
* @ignore _
* @ignore rename
* @ignore cleanCSS
* @ignore concat
* @ignore rjs
* @ignore uglify
* @ignore plumber
* @ignore babel
* @ignore autoprefixer
*/
const _ = require('lodash'),
gulp = require('gulp'),
pathBuilder = require("./PathBuild"),
plumber = require('gulp-plumber'),
babel = require('gulp-babel'),
sourcemaps = require('gulp-sourcemaps'),
livereload = require('gulp-livereload'),
rename = require('gulp-rename'),
cleanCSS = require('gulp-clean-css'),
uglify = require('gulp-uglify'),
pathObj = require('path'),
rJS = require('gulp-requirejs'),
autoprefixer = require('gulp-autoprefixer'),
concat = require('gulp-concat');
/**
* @class Concat
* Concatenate files
*
* @property {Object} liveReloadOptions <a target="_blank" href=https://github.com/vohof/gulp-livereload>Livereload</a> options for concat building
* @property {Object|Array} paths Config path. See <a href="global.html#pathConfig">For detail</a>
* @property {String} distDir Distributive folder from config
* @property {String} outDir Output folder from config
* @property {Boolean} useAMD Build amd application flag
* @property {Object} concatOptions Concatenate options
* @property {Boolean} useAMD
*/
class Concat {
/**
* Concat constructor
* @param {Object} options Concat options
* @param {Object} liveReloadOptions <a target="_blank" href=https://github.com/vohof/gulp-livereload>Livereload</a> options for concat building
* @param {{outDir: {String}, distDir: {String}}} defPaths Defined path from config
*/
constructor(options, liveReloadOptions, defPaths) {
defPaths = defPaths || {};
this.liveReloadOptions = liveReloadOptions || {};
this.paths = options.paths;
this.outDir = defPaths.outDir;
this.outFile = options.outFile;
this.distDir = defPaths.distDir;
this.concatOptions = options.concatOptions;
this.useAMD = options.configFile || false;
this.configFile = options.configFile;
this.sourcePath = options.sourcePath;
this.minPath = options.minPath;
this.babelOptions = options.babelOptions || {
presets: ['es2015']
};
this.minifyOptions = options.minifyOptions || {};
this.uglifyOptions = options.uglifyOptions || {};
this.minifySuffix = options.minifySuffix || '.min';
this.baseUrl = options.baseUrl || '';
this.rJSFile = options.file;
this.autoprefixOptions = options.autoprefixOptions || {
browsers: ['last 7 versions'],
cascade : true
};
this.rJSOptions = options.requireJSConfig || {};
if (this.useAMD) {
this.buildRJSConfig();
}
this.processPath();
}
/**
* Build require JS config
*/
buildRJSConfig() {
if (!this.useAMD) {
return;
}
this.rJSOptions = _.extend({
baseUrl: this.baseUrl,
name : this.configFile,
out : this.outFile
}, this.rJSOptions);
}
/**
* Process parse paths
*/
processPath() {
let paths = [];
_.each(this.paths, (path, dest) => {
paths.push({
dest: dest,
src : path
});
});
this.paths = (new pathBuilder(paths, this.outDir, {
distDir: this.distDir,
outDir : this.outDir
}, true)).processFullPath(true);
if (!_.isArray(this.paths)) {
this.paths = [this.paths];
}
if (this.useAMD) {
this.paths.push({
src: this.rJSOptions.baseUrl + '/' + this.rJSOptions.name,
dest: this.rJSOptions.baseUrl + '/' + this.rJSOptions.out
})
}
}
/**
* Add to task
*
* @param {String|Array} path Source path
* @param {String|RegExp} regex Regexp object
* @param {Function} callback Callable function
* @param {undefined|Array} callbackParams Options for callback
*
* @return {Boolean}
*/
addToTasks(path, regex, callback, callbackParams) {
regex = _.isString(regex) ? regex : new RegExp(regex);
if (_.isArray(path)) {
let answer;
for (let i in path) {
if (!path.hasOwnProperty(i)) {
continue;
}
if (answer = this.addToTasks(path[i], regex, callback, callbackParams)) {
return answer;
}
}
} else {
if (path.match(regex)) {
return callback.apply(this, callbackParams || []);
}
}
return false;
}
/**
* Run concatenate files
*/
build() {
if (!_.size(this.paths)) {
return;
}
let _self = this;
_.each(this.paths, (path, index) => {
_self.concatOptions = _self.concatOptions || {};
_self.concatOptions.path = path.src;
let _gulp = gulp.src(path.src)
.pipe(sourcemaps.init()),
answer = undefined;
if (answer = _self.addToTasks.apply(_self, [path.src, /\.css$/, (path, gulp) => {
return gulp.pipe(autoprefixer(_self.autoprefixOptions));
}, [path, _gulp]])) {
_gulp = answer;
}
if (answer = _self.addToTasks.apply(_self, [path.src, /\.js$/, (path, gulp) => {
return gulp.pipe(babel(_self.babelOptions));
}, [path, _gulp]])) {
_gulp = answer;
}
_gulp = _gulp.pipe(plumber())
.pipe(concat(pathObj.basename(path.dest), _self.concatOptions || {}))
.pipe(livereload(_self.liveReloadOptions));
_gulp.pipe(sourcemaps.write('.'))
.pipe(gulp.dest(pathObj.dirname(path.dest)));
});
}
/**
* Run minify files
*/
minify() {
if (!_.size(this.paths)) {
return;
}
let _self = this;
_.each(this.paths, (path, index) => {
let _answer = undefined,
answer = undefined;
if (_answer = _self.addToTasks.apply(_self, [path.dest, /\.css$/, (path, gulp) => {
return [uglify, _self.uglifyOptions]
}, [path]])) {
answer = _answer;
}
if (_answer = _self.addToTasks.apply(_self, [path.dest, /\.js$/, (path, gulp) => {
return [uglify, _self.uglifyOptions]
}, [path]])) {
answer = _answer;
}
gulp.src(path.dest)
.pipe(sourcemaps.init())
.pipe(plumber())
.pipe(livereload(_self.liveReloadOptions))
.pipe(rename({
suffix: _self.minifySuffix || '.min'
}))
.pipe(answer ? answer[0](answer[1]).on('error', console.log) : livereload())
.pipe(sourcemaps.write('.').on('error', console.log))
.pipe(livereload())
.pipe(gulp.dest(pathObj.dirname(path.dest)));
});
}
rJS() {
rJS(this.rJSOptions)
.pipe(gulp.dest(__dirname + "/../tests/data/concat/js/amd/out"));
}
/**
* Run watch files changed
*/
buildWatch(gulp) {
let files = [];
this.paths.forEach((arr, index) => {
for (let i in arr.src) {
if (!arr.src.hasOwnProperty(i)) {
continue;
}
files.push(arr.src[i]);
}
});
gulp.watch(files, ['concat']);
}
/**
* Watch changed source files for minified
*/
minifyWatch() {
let files = [];
this.paths.forEach((arr, index) => {
files.push(arr.dest);
});
gulp.watch(files, ['concat-minify']);
}
}
module.exports = Concat;