之前看冯博写的,自己也想写个试试,学习下先
初级的,来自幕客网
之后再把他写的逐个分析,然后自己写个简单的
var deasync = require('deasync');
var fs = require("fs");
var colors = require("colors");
var gs = require('nodegrass');
var os = require("os");
var currentPath = process.cwd();
var child_process = require("child_process");
var Download = require('download');
var chokidar = require('chokidar');
var md5 = require("md5");
var spawn = require('child_process').spawn;
var templBaseUrl = "http://118.178.231.7:8000/easyme/";//"http://localhost/easyme/";
var lang = ["en-US.lang", "zh-CN.lang", "zh-HK.lang"];
var forever;
var nodeCache = {};
var cheerio = require('cheerio');
var nc = {
readFileSync: function(path) {
return JSON.stringify(nodeCache);
},
writeFileSync: function(path, content) {
nodeCache = JSON.parse(content);
}
}
function stringReplaceAll(str, AFindText, ARepText){
var raRegExp = new RegExp(AFindText.replace(/([\(\)\[\]\{\}\^\$\+\-\*\?\.\"\'\|\/\\])/g,"\\$1"),"ig");
return str.replace(raRegExp,ARepText);
}
function readTemplFileContent(url, isCompile, placeTextConfig) {
var content = "";
var isReturn = false;
gs.get(url, function(data) {
content = data;
isReturn = true;
});
while(!isReturn) {
deasync.runLoopOnce();
}
if(isCompile) {
for(var key in placeTextConfig) {
content = stringReplaceAll(content, key, placeTextConfig[key]);
}
}
console.log(url.green + " 读取成功!".green);
return content;
}
function writeTemplFileContentToApp(content, toDir) {
fs.writeFileSync(toDir, content);
console.log(toDir.green + " 创建成功!".green);
}
function execCmd(cmd) {
if(os.platform() != "darwin") {
cmd = stringReplaceAll(cmd, "/", "\\");
}
var isReturn = false;
child_process.exec(cmd, {
encoding: 'utf8',
timeout: 0,
maxBuffer: 5000 * 1024,
killSignal: 'SIGTERM'
}, function (error, stdout, stderr) {
isReturn = true;
});
while(!isReturn) {
deasync.runLoopOnce();
}
}
function isFileExist(url) {
return fs.existsSync(url);
}
function guid() {
function S4() {
return (((1+Math.random())*0x10000)|0).toString(16).substring(1);
}
return (S4()+S4()+"-"+S4()+"-"+S4()+"-"+S4()+"-"+S4()+S4()+S4());
}
exports.easyMe = {
initApp: function() {
new Download({mode: '755'})
.get(templBaseUrl + "template.tar")
.run(function (err, files) {
execCmd("tar -xvf " + "template.tar");
fs.unlink("template.tar");
console.log("初始化应用".green + "----------[完成]".green);
});
},
addWidget: function(widgetName) {
if(!isFileExist("public/javascripts/widget/" + widgetName)) {
execCmd("mkdir " + "public/javascripts/widget/" + widgetName);
var widgetContent = readTemplFileContent(templBaseUrl + "widget.js", true, {"{$p}":widgetName});
writeTemplFileContentToApp(widgetContent, "public/javascripts/widget/" + widgetName + "/" + widgetName + ".js");
writeTemplFileContentToApp("", "public/javascripts/widget/" + widgetName + "/" + widgetName + ".css");
writeTemplFileContentToApp("<div></div>", "public/javascripts/widget/" + widgetName + "/" + widgetName + ".html");
console.log("组件文件创建成功!".green);
} else {
console.log("组件文件已存在".yellow);
}
},
deleteWidget: function(widgetName) {
if(isFileExist("public/javascripts/widget/" + widgetName)) {
execCmd("rm -rf " + "public/javascripts/widget/" + widgetName);
console.log("删除".green + widgetName.green + "组件文件成功".green);
} else {
console.log("组件文件不存在".yellow);
}
},
createPageHtml: function(pageName) {
if(!isFileExist("views/" + pageName + ".html")) {
var viewsContent = readTemplFileContent(templBaseUrl + "views.html", true, {"{$p}":pageName});
writeTemplFileContentToApp(viewsContent, "views/" + pageName + ".html");
console.log("主页面模板创建成功!".green);
} else {
console.log("主页面模板文件已存在".yellow);
}
},
createTplHtml: function(pageName) {
if(!isFileExist("views/tpl/" + pageName)) {
execCmd("mkdir " + "views/tpl/" + pageName);
writeTemplFileContentToApp("<div></div>", "views/tpl/" + pageName + "/init.html");
console.log("子模板页面创建成功!".green);
} else {
console.log("子模板页面文件已存在".yellow);
}
},
createPageLang: function(pageName) {
if(!isFileExist("public/lang/" + pageName)) {
execCmd("mkdir " + "public/lang/" + pageName);
for(var index = 0; index < lang.length; index++) {
writeTemplFileContentToApp("{}", "public/lang/" + pageName + "/" + lang[index]);
}
console.log("语言包文件创建成功!".green);
} else {
console.log("语言包文件已存在".yellow);
}
},
createApi: function(pageName) {
if(!isFileExist("public/api/" + pageName + ".js")) {
writeTemplFileContentToApp("{}", "public/api/" + pageName + ".js");
console.log("接口文件创建成功!".green);
} else {
console.log("接口文件已存在".yellow);
}
},
createPageCss: function(pageName) {
if(!isFileExist("public/stylesheets/" + pageName)) {
execCmd("mkdir " + "public/stylesheets/" + pageName);
writeTemplFileContentToApp("", "public/stylesheets/" + pageName + "/" + pageName + ".css");
console.log("样式文件创建成功!".green);
} else {
console.log("样式文件已存在".yellow);
}
},
createJs: function(pageName) {
if(!isFileExist("public/javascripts/" + pageName)) {
execCmd("mkdir " + "public/javascripts/" + pageName);
var jsContent = readTemplFileContent(templBaseUrl + "init.js", true, {"{$p}":pageName});
writeTemplFileContentToApp(jsContent, "public/javascripts/" + pageName + "/init.js");
console.log("脚本文件创建成功!".green);
} else {
console.log("脚本文件已存在".yellow);
}
},
createService: function(pageName) {
if(!isFileExist("public/javascripts/service/" + pageName + "Service.js")) {
var serviceContent = readTemplFileContent(templBaseUrl + "service.js", true, {"{$p}":pageName});
writeTemplFileContentToApp(serviceContent, "public/javascripts/service/" + pageName + "Service.js");
console.log("服务文件创建成功!".green);
} else {
console.log("服务文件已存在".yellow);
}
},
createRoute: function(pageName) {
if(!isFileExist("routes/" + pageName)) {
execCmd("mkdir " + "routes/" + pageName);
var routeContent = readTemplFileContent(templBaseUrl + "route.js", true, {"{$p}":pageName});
writeTemplFileContentToApp(routeContent, "routes/" + pageName + "/" + pageName + ".js");
console.log("路由文件创建成功!".green);
} else {
console.log("路由文件已存在".yellow);
}
},
addRoute: function(pageName) {
var routeContent = readTemplFileContent(templBaseUrl + "route.json", true, {"{$p}":pageName});
var routeContentJson = JSON.parse(routeContent);
var watchContent = fs.readFileSync("routes/watch.json");
var watchContentJson = JSON.parse(watchContent);
for(var index = 0; index < watchContentJson["request"].length; index++) {
if(watchContentJson["request"][index]["route"] == routeContentJson["route"]) {
console.log("路由项已存在!".green);
return;
}
}
watchContentJson["request"].push(routeContentJson);
writeTemplFileContentToApp(JSON.stringify(watchContentJson, false, 4), "routes/watch.json");
console.log("路由项添加成功!".green);
},
removePageHtml: function(pageName) {
if(isFileExist("views/" + pageName + ".html")) {
execCmd("rm -rf " + "views/" + pageName + ".html");
console.log("删除".green + pageName.green + "主页面模板成功".green);
} else {
console.log("主页面文件不存在".yellow);
}
},
removeTplHtml: function(pageName) {
if(isFileExist("views/tpl/" + pageName)) {
execCmd("rm -rf " + "views/tpl/" + pageName);
console.log("删除".green + pageName.green + "子页面模板成功".green);
} else {
console.log("子页面模板文件不存在".yellow);
}
},
removePageLang: function(pageName) {
if(isFileExist("public/lang/" + pageName)) {
execCmd("rm -rf " + "public/lang/" + pageName);
console.log("删除".green + pageName.green + "语言文件成功".green);
} else {
console.log("语言文件不存在".yellow);
}
},
removeApi: function(pageName) {
if(isFileExist("public/api/" + pageName + ".js")) {
execCmd("rm -rf " + "public/api/" + pageName + ".js");
console.log("删除".green + pageName.green + "api文件成功".green);
} else {
console.log("api文件不存在".yellow);
}
},
removePageCss: function(pageName) {
if(isFileExist("public/stylesheets/" + pageName)) {
execCmd("rm -rf " + "public/stylesheets/" + pageName);
console.log("删除".green + pageName.green + "样式文件成功".green);
} else {
console.log("样式文件不存在".yellow);
}
},
removeJs: function(pageName) {
if(isFileExist("public/javascripts/" + pageName)) {
execCmd("rm -rf " + "public/javascripts/" + pageName);
console.log("删除".green + pageName.green + "脚本文件成功".green);
} else {
console.log("脚本文件不存在".yellow);
}
},
removeService: function(pageName) {
if(isFileExist("public/javascripts/service/" + pageName + "Service.js")) {
execCmd("rm -rf " + "public/javascripts/service/" + pageName + "Service.js");
console.log("删除".green + pageName.green + "服务文件成功".green);
} else {
console.log("服务文件不存在".yellow);
}
},
removeRoute: function(pageName) {
if(isFileExist("routes/" + pageName)) {
execCmd("rm -rf " + "routes/" + pageName);
console.log("删除".green + pageName.green + "路由文件成功".green);
} else {
console.log("路由文件不存在".yellow);
}
},
updateRoute: function(pageName) {
if(pageName == "index") {
pageName = "";
}
var routeName = "/" + pageName;
var watchContent = fs.readFileSync("routes/watch.json");
var watchContentJson = JSON.parse(watchContent);
for(var index = 0; index < watchContentJson["request"].length; index++) {
if(watchContentJson["request"][index]["route"] == "/index" || watchContentJson["request"][index]["route"] == routeName) {
watchContentJson["request"].splice(index, 1);
writeTemplFileContentToApp(JSON.stringify(watchContentJson, false, 4), "routes/watch.json");
break;
}
}
console.log("更新路由成功".green);
},
trace: function() {
forever = spawn('node', ["debug", "app.js"]);
// 捕获标准输出并将其打印到控制台
forever.stdout.on('data', function (data) {
console.log(data.toString().blue);
});
// 捕获标准错误输出并将其打印到控制台
forever.stderr.on('data', function (data) {
console.log('standard error output:\n'.red + data);
});
process.stdin.on('readable', function() {
var chunk = process.stdin.read();
if (chunk !== null) {
forever.stdin.write(chunk);
}
});
},
watch: function() {
var watcher = chokidar.watch(["views", "routes", "public"], {
persistent: true,
ignored: "/(^|[\/\\])\../",
ignoreInitial: false,
followSymlinks: true,
cwd: '.',
disableGlobbing: false,
usePolling: false,
interval: 10,
alwaysStat: true,
binaryInterval: 10,
alwaysStat: false,
depth: 99,
useFsEvents: true,
awaitWriteFinish: {
stabilityThreshold: 2000,
pollInterval: 50
},
ignorePermissionErrors: false,
atomic: true // or a custom 'atomicity delay', in milliseconds (default 100)
});
function execShell(callback, isFirstStart) {
if(forever) {
forever.kill("SIGTERM");
}
forever = spawn('node', ["app.js"]);
// 捕获标准输出并将其打印到控制台
forever.stdout.on('data', function (data) {
console.log('standard output:\n'.green + data);
callback();
});
// 捕获标准错误输出并将其打印到控制台
forever.stderr.on('data', function (data) {
console.log('standard error output:\n'.red + data);
callback("error");
});
}
execShell(function() {}, true);
function ifwatchKeyExist(path, debugJson) {
for(var key in debugJson) {
if(debugJson[key]) {
return {
md5: debugJson[key]
};
}
}
return false;
}
watcher.on('change', function(path, stats) {
if(path.indexOf("cache") > -1 || path.indexOf("Cache") > -1) {
return;
}
execShell(function(msg) {
if(msg == "error") {
console.log("服务器代码错误!".red);
} else {
console.log(path.green + " has be changed, the server is restarted....!".green);
}
}, false);
}).on('error', function(error) {
execShell(function() {
console.log('Error happened'.red, error);
}, false);
}).on('ready', function() {
console.log('The app is watched under your changed! good luck for your working!'.green);
});
process.on('SIGINT', function() {
console.log("bey bey ....".yellow);
forever.kill("SIGTERM");
process.exit();//退出当前进程
});
process.on("exit", function() {
forever.kill("SIGTERM");
});
},
buildTester: function() {
var rootDir = "views/tpl";
function buildTestFile(path) {
var html = fs.readFileSync(path).toString();
$ = cheerio.load(html, {decodeEntities: false, xmlMode: true, recognizeSelfClosing: true});
var allEles = $("*");
var tagList = {};
var middleHtml = "";
for (var index = 0; index < allEles.length; index++) {
tagList[$(allEles[index]).get(0).tagName] = "";
}
function inferClose(middleHtml) {
var leftMarkCount = 0;
var rightMarkCount = 0;
for (var c = 0; c < middleHtml.length; c++) {
if (middleHtml[c] == "{") {
leftMarkCount++;
} else if (middleHtml[c] == "}") {
rightMarkCount++;
}
}
if (leftMarkCount != rightMarkCount) {
return false;
} else {
return true;
}
}
function inferNameExsist(middleHtml) {
var nodeEle = $("<template " + middleHtml + " />");
var nameAttr = nodeEle.attr("name");
if (typeof nameAttr == "undefined") {
return true;
}
return false;
}
function parseTag(startTag, start, end) {
end = html.indexOf(">", end + 1);
middleHtml = html.substring(start, end);
var isClose = inferClose(middleHtml);
if (!isClose) {
parseTag(startTag, start, end);
} else {//为html节点添加name属性
var nameAttr = "";
if (inferNameExsist(middleHtml)) {//如果没有name属性,添加name属性
var headHtml = html.substring(0, start);
var footHtml = html.substring(start, html.length);
nameAttr = " name=" + "'T_" + guid().split("-")[0].substring(0, 4) + "'" + " ";
html = headHtml + nameAttr + footHtml;
}
if (html.indexOf(startTag, end + nameAttr.length) > -1) {
parseTag(startTag, html.indexOf(startTag, end + nameAttr.length) + startTag.length, html.indexOf(startTag, end + nameAttr.length));
}
}
}
for (var tag in tagList) {
var startTag = "<" + tag;
parseTag(startTag, html.indexOf(startTag) + startTag.length, html.indexOf(startTag));//从零开始寻找
}
fs.writeFileSync(path, html);
console.log(path.green + "-------ok".green);
}
var pa = fs.readdirSync(rootDir);
pa.forEach(function (ele, index) {
var info = fs.statSync(rootDir + "/" + ele);
if (info.isDirectory()) {
var dirPath = rootDir + "/" + ele;
fs.readdir(dirPath, function (err, files) {
files.forEach(function (filename) {
if (filename.indexOf(".html") > -1) {
buildTestFile(dirPath + "/" + filename);
}
});
});
}
});
}
}
index文件
var easyMe = require("./easyme").easyMe;
var program = require("commander");
var fs = require("fs");
program
.version("0.0.1")
.option("-i,--init", "init app")
.option("-c,--create <string>", "create a single page")
.option("-r,--remove <string>", "remove a sigle page")
.option("-a,--addWidget <string>", "add a sigle widget")
.option("-d,--deleteWidget <string>", "delete a sigle widget")
.option("-w,--watch", "watch the app change, restart the server back")
.option("-t,--trace", "trace the code execution environment")
.option("-b,--build", "add test mark on every tag into tester write auto test script easyly")
.parse(process.argv);
if(program.init) {
if(program.init.toString() == "") {
console.log("param is error".red);
return;
}
easyMe.initApp();
}
if(program.create) {//创建单页面
var pageName = program.create.toString();
easyMe.createPageHtml(pageName);//创建html模板
easyMe.createTplHtml(pageName);
easyMe.createPageLang(pageName);//创建语言模板
easyMe.createApi(pageName);//创建api模板
easyMe.createPageCss(pageName);//创建css模板
easyMe.createJs(pageName);//创建javascript文件模板
easyMe.createService(pageName);//创建service文件模板
easyMe.createRoute(pageName);//创建路由文件模板
easyMe.addRoute(pageName);//增加路由表
}
if(program.remove) {//删除单页面
var pageName = program.remove.toString();
easyMe.removePageHtml(pageName);
easyMe.removeTplHtml(pageName);
easyMe.removePageLang(pageName);
easyMe.removeApi(pageName);
easyMe.removePageCss(pageName);
easyMe.removeJs(pageName);
easyMe.removeService(pageName);
easyMe.removeRoute(pageName);
easyMe.updateRoute(pageName);
}
if(program.addWidget) {//创建单组件
var widgetName = program.addWidget.toString();
easyMe.addWidget(widgetName);
}
if(program.deleteWidget) {//删除单组件
var widgetName = program.deleteWidget.toString();
easyMe.deleteWidget(widgetName);
}
if(program.watch) {
easyMe.watch();
}
if(program.trace) {
easyMe.trace();
}
if(program.build) {
easyMe.buildTester();
}