v-kitty
Version:
hello kitty
347 lines (311 loc) • 10.6 kB
JavaScript
var path = require('path');
var util = require('util');
var strip = require('strip-comments');
var fs = require('fs');
var fse = require('fs-extra');
var Loader = require('./loader.js');
var ParseFile = require('./parseFile.js');
var gulpWatch = require('gulp-watch');
var moment = require('moment');
var nowTime = function (format) {
return moment().format(format || "HH:mm:ss");
};
global.config = {
cache: true,//是否开启缓存,默认开启,加速编译
watch: false,//开启监听模式
tag: '_include',//引入tag
baseDir: __dirname.replace(/\/node_modules.*$/, ''),//项目根目录
cdnUrl: "",//cdn地址路径
resourceDir: "./build/static",//资源文件存放地址,必须有cdn调用才能生效
buildDir: "./build",//资源文件存放地址,必须有cdn调用才能生效
varTag: {
open: '@@',//变量开始符
close: "@@"//变量结束符
}
};
global.bufferFiles = {};
var Build = {
init: function (file, content) {
var destfile = path.resolve(config.baseDir,config.buildDir,file.replace(config.baseDir,'.'));
ParseFile.beforeCompile = Loader.beforeCompile;
this._reset();
this._build(file,content,destfile);
this._setIsActive();
return content;
},
_createBind:function(bufferFile){
//更新compile
bufferFile.bindings.change = function(content){
var file = bufferFile.file;
Object.keys(bufferFiles).forEach(function(key){
var bufferFile = bufferFiles[key];
var check=false;
bufferFile.depends.forEach(function(depend){
if(depend.file === file){
Build._compileLoaders(bufferFile,depend,content);
check=true;
}
});
if(check){
bufferFile._compileDep();
}
});
};
//更新content
bufferFile.bindings.update = function(){
Build._buildBack();
Build._setIsActive();
};
//删除文件
bufferFile.bindings.del = function(){
//判断有没有依赖
var result = [];
Object.keys(bufferFiles).forEach(function(key){
var buffer = bufferFiles[key];
buffer.depends.forEach(function(depend){
if(depend.file===bufferFile.file){
result.push(buffer.file);
}
})
});
if(result.length){
throw 'Error source(05): '+result.join('\nError source: ');
}
//删除changes
bufferFiles[bufferFile.file].depends.forEach(function(depend){
if(depend.file){
var changeSubs = bufferFiles[depend.file].bindings.changeSubs;
delete changeSubs[bufferFile.file];
}
});
delete bufferFiles[bufferFile.file];
};
},
/**
* 开始构建
* @param file
* @param content
* @returns {*}
* @private
*/
_build: function (file, content,destfile) {
try{
new ParseFile({file: file, content: content,destfile:destfile});
Build._buildBack();
}catch (err){
console.log('Error source(04): '+file);
console.log(err);
process.exit();
}
return content;
},
/**
* 构建回调
* @private
*/
_buildBack:function(){
Object.keys(bufferFiles).forEach(function (key) {
var bufferFile = bufferFiles[key];
//isnew判断是不是已经监听
if(bufferFile.isNew){
Build._observe(bufferFile);
Build._createBind(bufferFile);
Build._compile(bufferFile);
Build._watch(bufferFile);
bufferFile.isNew = false;
}else{
Build._compile(bufferFile);
}
});
},
/**
* 充值构建文件
* @private
*/
_reset:function(){
//fse.removeSync(config.buildDir);
//fse.removeSync(config.resourceDir);
this._reset =function(){};
},
/**
* compile
* @private
*/
_compile: function (bufferFile) {
var self = this;
var timeout;
bufferFile._compileDep = function () {
clearTimeout(timeout);
timeout = setTimeout(function () {
var result = '';
bufferFile.depends.forEach(function (dep) {
result += dep.content;
});
bufferFile.compile = Loader.afterCompile(result,bufferFile);
self._createCompileFile(bufferFile);
})
};
},
/**
* loaders compile
* @private
*/
_compileLoaders:function(bufferFile,depend,newValue){
var compileContent = newValue;
//loaders处理
depend.loaders.forEach(function(key){
try {
compileContent = Loader[key](compileContent,bufferFiles[depend.file],depend);
}catch (err){
console.log('Error source(03): '+bufferFile.file);
console.log('Error on execute loader.'+key);
throw err;
}
});
if(depend.options){
compileContent = Build._handleOptions(compileContent,depend.options);
}
//如果是js文件,引入后要使用单引号引入,但是require需要除外
if(bufferFile.type==='js' && depend.loaders.indexOf('_require')===-1){
compileContent = compileContent.replace(/\n\/\/.*?\n/g, '').replace(/\n/g, '').replace(/'/g, "\\'").replace(/\//g,'\\/');
compileContent = "'" + compileContent + "'";
}
depend.content = compileContent;
},
/**
* 生成所需要的文件
* @param bufferFile
* @private
*/
_createCompileFile:function(bufferFile){
var destfile = bufferFile.destfile;
if(destfile){
fse.ensureFileSync(destfile);
fs.writeFile(destfile,bufferFile.compile);
console.log(nowTime() + ' compiled '+bufferFile.file);
}
},
_handleOptions: function(content,options){
var openTag = config.varTag.open;
var closeTag = config.varTag.close;
var regexp = new RegExp(openTag + '(.+?)' + closeTag, 'g');
content = content.replace(regexp, function () {
var key = arguments[1] || '';
var val = options;
key.split('.').forEach(function (k) {
val = val[k];
});
return val || '';
});
return content;
},
/**
* 设置末尾isactive有效
* @private
*/
_setIsActive: function () {
var self = this;
clearTimeout(this._setIsActiveTimeout);
this._setIsActiveTimeout = setTimeout(function(){
console.log('compiling');
var len = Object.keys(bufferFiles).length;
Object.keys(bufferFiles).forEach(function(key){
var bufferFile = bufferFiles[key];
if(bufferFile.isActive){
bufferFile.depends.forEach(function(dep){
//如果修改的是中间文件,此时dep.content为空
//!bufferFiles[dep.file].isActive 是在反推的时候就可以编译 如果这里编译会变成多此一举
if(!dep.content && dep.file && !bufferFiles[dep.file].isActive){
Build._compileLoaders(bufferFile,dep,bufferFiles[dep.file].compile);
}
if(dep.file && bufferFiles[dep.file].isActive){
setTimeout(function(){
bufferFile.isActive=false;
})
}
})
}
len--;
if(len===0){
setTimeout(function(){
self._doIsActive();
})
}
})
},22);
},
/**
* active 操作
* @private
*/
_doIsActive: function () {
var self = this;
Object.keys(bufferFiles).forEach(function (key) {
var bufferFile = bufferFiles[key];
if (bufferFile.isActive) {
var result = '',hasDepFile=false;
bufferFile.depends.forEach(function (dep) {
result += dep.content;
});
bufferFile.compile = result;
bufferFile.isActive=false;
self._createCompileFile(bufferFile);
}
})
},
/**
* 监听bufferfiles文件
* @private
*/
_watch: function (bufferFile) {
if(!config.watch){
return;
}
var file = bufferFile.file;
bufferFiles[file]._watch=gulpWatch(file, function (vinyl) {
var event = vinyl.event;
if (event === 'unlink') {
bufferFiles[file]._watch.close();
bufferFiles[file].emitter.emit('del');
} else if(event==='change') {
var content = vinyl.contents.toString();
content = Loader.beforeCompile(content);
bufferFiles[file].emitter.emit('update',content);
}
});
},
/**
* 观察compile
* @param data
* @private
*/
_observe: function (data) {
var oldValue = data.compile;
Object.defineProperty(data, 'compile', {
get: function () {
return oldValue;
},
set: function (newValue) {
//不能使用oldvalue===newvalue进行判断 因为编译后字符串很大可能相同
//if (oldValue === newValue) {
// return;
//}
oldValue = newValue;
data.emitter.emit('change',newValue);
}
});
}
};
var include = function (file, content) {
if(!bufferFiles[file]){
try{
Build.init(file, content);
}catch (err){
throw err;
}
}
return content;
};
include.config = config;
include.loader = Loader;
module.exports = include;