Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

issue #4277 Add publish scripts to help developers publish project with nodejs #1655

Merged
merged 1 commit into from

2 participants

@SmallAiTT

issue #4277 Add publish scripts to help developers publish project with nodejs

@dingpinglv dingpinglv merged commit 61d13ef into cocos2d:develop-3.0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
This page is out of date. Refresh to see the latest.
View
245 tools/core4cc.js
@@ -0,0 +1,245 @@
+var fs = require("fs");
+var path = require("path");
+var exec = require('child_process').exec;
+var spawn = require('child_process').spawn;
+var url = require('url');
+
+var core4cc = {};
+module.exports = core4cc;
+
+/**
+ * Desc:merge js code from client to server.
+ * @param src src path
+ * @param targetDir target path
+ * @param requireArr dependencies
+ * @param name
+ */
+core4cc.trans2Module = function(src, targetDir, requireArr, name){
+ if(!fs.existsSync(targetDir)) fs.mkdirSync(targetDir);
+ var srcBaseName = path.basename(src);
+ name = name || path.basename(src, ".js");
+ var content = fs.readFileSync(src).toString();
+ var requireStr = "";
+ for(var i = 0, li = requireArr.length; i < li; ++i){
+ var strs = requireArr[i].split("->");
+ requireStr = requireStr + "var " + strs[0] + " = require('" + strs[1] + "');\r\n";
+ }
+ fs.writeFileSync(targetDir + srcBaseName, requireStr + content + "\r\nmodule.exports = " + name + ";");
+};
+
+/**
+ * Desc:merge js arr to one
+ * @param srcs
+ * @param target
+ * @param requireArr
+ * @param name
+ */
+core4cc.merge2Module = function(srcs, target, requireArr, name){
+ var targetDir = path.dirname(target);
+ if(!fs.existsSync(targetDir)) fs.mkdirSync(targetDir);
+ var content = "";
+ for(var i = 0, li = srcs.length; i < li; ++i){
+ content += fs.readFileSync(srcs[i]).toString() + "\r\n";
+ }
+ var requireStr = "";
+ for(var i = 0, li = requireArr.length; i < li; ++i){
+ var strs = requireArr[i].split("->");
+ requireStr = requireStr + "var " + strs[0] + " = require('" + strs[1] + "');\r\n";
+ }
+ fs.writeFileSync(target, requireStr + content + "\r\nmodule.exports = " + name + ";");
+};
+
+/**
+ * dESC: Get key name by the file name.
+ * @param name
+ * @returns {String}
+ */
+core4cc.getKeyName = function(name){
+ var key = name.replace(/[.]/g, "_");
+ key = key.replace(/[\-\(\)]/g, "_");
+ var r = key.match(/^[0-9]/);
+ if(r != null) key = "_" + key;
+ return key.replace(/\s/g, "");
+};
+/**
+ * Desc: Returns array for dependencies.
+ * @param temp
+ * @returns {Array}
+ * @private
+ */
+core4cc.getDependencies = function(temp){
+ var dependencies = [];
+ for(var key in temp){
+ dependencies.push(key);
+ };
+ return dependencies;
+};
+
+/**
+ * Desc: unzip
+ * @param srcZip
+ * @param targetDir
+ * @param cb
+ */
+core4cc.unzip = function(srcZip, targetDir, cb){
+ var execCode = "unzip " + srcZip + " -d " + targetDir;
+ exec(execCode, function(err, data, info){
+ if(err) return cb(err);
+ else cb(null);
+ });
+};
+
+
+
+/**
+ * Desc: Download resources.
+ * @param downLoadDir
+ * @param fileUrl
+ * @param cb
+ */
+core4cc.download = function(downLoadDir, fileUrl, cb) {
+ // extract the file name
+ var fileName = url.parse(fileUrl).pathname.split('/').pop();
+ // create an instance of writable stream
+ var file = fs.createWriteStream(path.join(downLoadDir, fileName));
+ // execute curl using child_process' spawn function
+ var curl = spawn('curl', [fileUrl]);
+ // add a 'data' event listener for the spawn instance
+ curl.stdout.on('data', function(data) { file.write(data); });
+ // add an 'end' event listener to close the writeable stream
+ curl.stdout.on('end', function(data) {
+ file.end();
+ console.log(fileName + ' downloaded to ' + downLoadDir);
+ cb(null);
+ });
+ // when the spawn child process exits, check if there were any errors and close the writeable stream
+ curl.on('exit', function(code) {
+ if (code != 0) {
+ console.error('Failed: ' + code);
+ cb("error")
+ }
+ });
+};
+
+/**
+ * Desc: Remove dir recursively.
+ * @param filePath
+ * @param ignores
+ */
+core4cc.rmdirSyncRecursive = function(filePath, ignores) {
+ var files = [];
+ if( fs.existsSync(filePath) ) {
+ if(ignores && ignores.length > 0 && ignores.indexOf(filePath) >= 0) return;
+ if(!fs.statSync(filePath).isDirectory()) return fs.unlinkSync(filePath);
+ files = fs.readdirSync(filePath);
+ for(var i = 0, li = files.length; i < li; i++){
+ var curPath = path.join(filePath, files[i]);
+ core4cc.rmdirSyncRecursive(curPath, ignores); // recurse
+ }
+ files = fs.readdirSync(filePath);//read again
+ if(files.length == 0) fs.rmdirSync(filePath);
+ }
+};
+
+/**
+ * Desc: Create dir recursively.
+ * @param arr
+ * @param index
+ * @param cb
+ * @returns {*}
+ */
+core4cc.mkdirRecursive = function(arr, index, cb){
+ if(index >= arr.length) cb();
+ var dir = path.join(process.cwd(), arr.slice(0, index +1).join(path.sep));
+ if(fs.existsSync(dir)) return core4cc.mkdirRecursive(arr, index+1, cb);
+ fs.mkdir(dir, function(){
+ core4cc.mkdirRecursive(arr, index+1, cb);
+ });
+}
+/**
+ * Desc: create dir sync recursively.
+ * @param targetPath
+ */
+core4cc.mkdirSyncRecursive = function(targetPath){
+ if(targetPath == null || targetPath == "") return;
+ targetPath = core4cc.isAbsolute(targetPath) ? path.normalize(targetPath) : path.join(process.cwd(), targetPath);
+ if(fs.existsSync(targetPath)) return;
+
+ var arr = targetPath.split(path.sep);
+ var index = arr.length - 1;
+ var tempStr = arr[index];
+ while(tempStr == "" && arr.length > 0){
+ index--;
+ tempStr = arr[index];
+ }
+ if(tempStr == "") return;
+ var newPath = targetPath.substring(0, targetPath.length - tempStr.length - 1);
+ if(!fs.existsSync(newPath)) core4cc.mkdirSyncRecursive(newPath);
+ fs.mkdirSync(targetPath);
+}
+/**
+ * Desc: Returns true if the filePath is absolute.
+ * @param filePath
+ * @returns {boolean}
+ */
+core4cc.isAbsolute = function(filePath){
+ filePath = path.normalize(filePath);
+ if(filePath.substring(0, 1) == "/") return true;
+ if(filePath.search(/[\w]+:/) == 0) return true;
+ return false;
+};
+
+/**
+ * Desc: Copy files in srcPath to targetPath, then replace info by config.
+ * @param srcPath
+ * @param targetPath
+ * @param handler
+ * @private
+ */
+core4cc.copyFiles = function(srcPath, targetPath, handler){
+ if(!fs.statSync(srcPath).isDirectory()) return fs.writeFileSync(targetPath, fs.readFileSync(srcPath));//copy if it`s a file
+
+ if(!fs.existsSync(targetPath)) fs.mkdirSync(targetPath);
+ var files = fs.readdirSync(srcPath);
+ for(var i = 0, li = files.length; i < li; i++){
+ var file = files[i];
+ if(fs.statSync(path.join(srcPath, file)).isDirectory()){//make dir if it`s a dir
+ var dir = path.join(targetPath, file, "./");
+ if(!fs.existsSync(dir)) fs.mkdirSync(dir);
+ core4cc.copyFiles(path.join(srcPath, file + "/"), dir, handler);//goes on
+ }else{
+ var filePath = path.join(targetPath, file);
+ fs.writeFileSync(filePath, fs.readFileSync(path.join(srcPath, file)));//copy if it`s a file
+ if(handler) {
+ handler.fmt(filePath);
+ }
+ }
+ }
+}
+
+/**
+ * Desc: Get string for command.
+ * e.g. aaaa ---> aaaa
+ * "a a" ---> a a
+ * @param str
+ * @returns {*}
+ */
+core4cc.getStr4Cmd = function(str){
+ if(!str) return null;
+ if(str.length < 2) return str;
+ return str.substring(0, 1) == '"' && str.substring(str.length - 1) == '"' ? str.substring(1, str.length - 1) : str;
+}
+/**
+ * Desc: Merge data by default value
+ * @param data
+ * @param defData default value
+ * @returns {{}|*}
+ */
+core4cc.mergeData = function(data, defData){
+ data = data || {};
+ if(defData == null) return data;;
+ for (var key in defData) {
+ if(data[key] == null && defData[key] != null) data[key] = defData[key];
+ }
+ return data;
+}
View
143 tools/genBuildXml.js
@@ -6,69 +6,104 @@
var fs = require("fs");
var path = require("path");
-var projectJson = require("../project.json");
-var engineDir = projectJson.engineDir;
-var moduleConfig = require(path.join("../", engineDir, "moduleConfig.json"));
-var ccModuleMap = moduleConfig.module;
-var modules = projectJson.modules;
-var ccJsList = ccModuleMap.core;
-var userJsList = projectJson.jsList;
+module.exports = function(projectDir, projectJson, buildOpt){
+ //获取到引擎所在目录,不填默认为frameworks/cocos2d-html5
+ var engineDir = projectJson.engineDir || "frameworks/cocos2d-html5";
+ //获取引擎真实目录
+ var realEngineDir = path.join(projectDir, engineDir);
+ //获取发布地址
+ var realPublishDir = path.join(projectDir, "publish/html5");
+ //tools真实路径
+ var realToolsDir = path.dirname(__filename);
+ //根据引擎所在目录,获取到引擎的模块配置
+ var moduleConfig = require(path.join(realEngineDir, "moduleConfig.json"));
+ //得到引擎的模块配置映射`module`
+ var ccModuleMap = moduleConfig.module;
+ //获取到该项目所需要的模块,不填默认为["core"]
+ var modules = projectJson.modules || ["core"];
+ //获取到引擎的渲染模式,不填默认为0
+ var renderMode = projectJson.renderMode || 0;
+ //入口js文件路径,默认为main.js
+ var mainJs = projectJson.main || "main.js";
-//cache for js and module that has added into jsList to be loaded.
-var _jsAddedCache = {};
-function _getJsListOfModule(moduleMap, moduleName, dir){
- var jsAddedCache = _jsAddedCache;
- if(jsAddedCache[moduleName]) return null;
- dir = dir || "";
- var jsList = [];
- var tempList = moduleMap[moduleName];
- if(!tempList) throw "can not find module [" + moduleName + "]";
- for(var i = 0, li = tempList.length; i < li; i++){
- var item = tempList[i];
- if(jsAddedCache[item]) continue;
- var extname = path.extname(item);
- if(!extname) {
- var arr = _getJsListOfModule(moduleMap, item, dir);
- if(arr) jsList = jsList.concat(arr);
- }else if(extname.toLowerCase() == ".js") jsList.push(path.join(dir, item));
- jsAddedCache[item] = true;
+ //引擎js列表存储数组,需要放入CCBoot.js
+ var ccJsList = [moduleConfig.bootFile];
+ //用户js列表存储数组
+ var userJsList = projectJson.jsList || [];
+
+ //如果renderMode不为1(canvas模式),那么需要加入webgl依赖
+ if(renderMode != 1 && modules.indexOf("base4webgl") < 0){
+ modules.splice(0, 0, "base4webgl");
}
- return jsList;
-};
+
+
+ //cache for js and module that has added into jsList to be loaded.
+ var _jsAddedCache = {};
+ //该方法是为了递归根据模块配置,获取到相应的js列表
+ function _getJsListOfModule(moduleMap, moduleName){
+ var jsAddedCache = _jsAddedCache;
+ if(jsAddedCache[moduleName]) return null;
+ jsAddedCache[moduleName] = true;
+ var jsList = [];
+ var tempList = moduleMap[moduleName];
+ if(!tempList) throw "can not find module [" + moduleName + "]";
+ for(var i = 0, li = tempList.length; i < li; i++){
+ var item = tempList[i];
+ if(jsAddedCache[item]) continue;
+ var extname = path.extname(item);
+ if(!extname) {
+ var arr = _getJsListOfModule(moduleMap, item);
+ if(arr) jsList = jsList.concat(arr);
+ }else if(extname.toLowerCase() == ".js") jsList.push(item);
+ jsAddedCache[item] = true;
+ }
+ return jsList;
+ };
-for(var i = 0, li = modules.length; i < li; i++){
- var item = modules[i];
- if(_jsAddedCache[item]) continue;
- var extname = path.extname(item);
- if(!extname) {
+ for(var i = 0, li = modules.length; i < li; i++){
+ var item = modules[i];
var arr = _getJsListOfModule(ccModuleMap, item, "");
if(arr) ccJsList = ccJsList.concat(arr);
- }else if(extname.toLowerCase() == ".js") ccJsList.push(path.join("", item));
- _jsAddedCache[item] = true;
-}
+ }
+
+ //根据js列表,获取到需要替换到模板中的字符串
+ function getFileArrStr(jsList){
+ var str = "";
+ for(var i = 0, li = jsList.length; i < li; i++){
+ str += ' <file name="' + jsList[i] + '"/>'
+ if(i < li - 1) str += '\r\n';
+ }
+ return str;
+ }
-var ccJsListStr = "";
-for(var i = 0, li = ccJsList.length; i < li; i++){
- var jsPath = ccJsList[i];
- ccJsListStr += ' <file name="' + jsPath + '"/>'
- if(i < li - 1) ccJsListStr += '\r\n';
-}
+ //记得,main.js需要放在最后面,因为其一引入就会调用cc.game.run
+ userJsList.push(mainJs);
-if(fs.existsSync(path.join(__dirname, "../main.js"))) userJsList.push("main.js");
-else if(fs.existsSync(path.join(__dirname, "../src/main.js"))) userJsList.push("src/main.js");
-var userJsListStr = "";
-for(var i = 0, li = userJsList.length; i < li; i++){
- var jsPath = userJsList[i];
- userJsListStr += ' <file name="' + jsPath + '"/>'
- if(i < li - 1) userJsListStr += '\r\n';
-}
+ //获取到build.xml模板内容
+ var buildContent = fs.readFileSync(path.join(realToolsDir, "template/build.xml")).toString();
+ //替换项目路径
+ buildContent = buildContent.replace(/%projectDir%/gi, projectDir);
+ //替换引擎路径
+ buildContent = buildContent.replace(/%engineDir%/gi, realEngineDir);
+ //替换发布路径
+ buildContent = buildContent.replace(/%publishDir%/gi, realPublishDir);
+ //替换发布路径
+ buildContent = buildContent.replace(/%outputFileName%/gi, buildOpt.outputFileName);
+ //替换tools路径
+ buildContent = buildContent.replace(/%toolsDir%/gi, realToolsDir);
+ //替换tools路径
+ buildContent = buildContent.replace(/%compilationLevel%/gi, buildOpt.compilationLevel);
+ //替换sourceMap配置
+ buildContent = buildContent.replace(/%sourceMapCfg%/gi, buildOpt.sourceMapOpened ? 'sourceMapOutputFile="' + path.join(realPublishDir, "sourcemap") + '" sourceMapFormat="V3"' : "");
+ //替换引擎js列表
+ buildContent = buildContent.replace(/%ccJsList%/gi, getFileArrStr(ccJsList));
+ //替换用户js列表
+ buildContent = buildContent.replace(/%userJsList%/gi, getFileArrStr(userJsList));
+ //生成项目的build.xml
+ fs.writeFileSync(path.join(realPublishDir, "build.xml"), buildContent);
-var buildContent = fs.readFileSync(path.join(__dirname, "template/build.xml")).toString();
-buildContent = buildContent.replace(/%engineDir%/g, engineDir);
-buildContent = buildContent.replace(/%ccJsList%/g, ccJsListStr);
-buildContent = buildContent.replace(/%userJsList%/g, userJsListStr);
-fs.writeFileSync(path.join(__dirname, "../build.xml"), buildContent);
+};
View
55 tools/publish.js
@@ -0,0 +1,55 @@
+var exec = require("child_process").exec;
+var fs = require("fs");
+var path = require("path");
+var core4cc = require("./core4cc");
+console.log("Publishing...");
+
+var projectDir = path.join(__dirname, "../");
+
+var projectJson = require(path.join(projectDir, "project.json"));
+var engineDir = path.join(projectJson.engineDir || "frameworks/cocos2d-html5", "/");
+var realEngineDir = path.join(projectDir, engineDir, "/");
+
+var realPublishDir = path.join(projectDir, "publish/html5");
+
+var buildOpt = {
+ outputFileName : "game.min.js",
+// compilationLevel : "simple",
+ compilationLevel : "advanced",
+ sourceMapOpened : true
+};
+
+if(!fs.existsSync(realPublishDir)) core4cc.mkdirSyncRecursive(realPublishDir);
+
+
+require("./genBuildXml")(projectDir, projectJson, buildOpt);
+
+var outputJsPath = path.join(realPublishDir, buildOpt.outputFileName);
+if(fs.existsSync(outputJsPath)) fs.unlinkSync(outputJsPath);
+
+exec("cd " + realPublishDir + " && ant", function(err, data, info){
+ console.log(info);
+ console.log(data);
+ if(err) {
+ console.error(err);
+ console.log(err[0]);
+ return console.log("Failed!")
+ }
+ var sourceMapPath = path.join(realPublishDir, "sourcemap");
+ if(fs.existsSync(sourceMapPath)){
+ var smContent = fs.readFileSync(sourceMapPath).toString();
+ smContent = smContent.replace(new RegExp(path.join(projectDir, "/"), "gi"), "");
+ smContent = smContent.replace(new RegExp(realEngineDir, "gi"), engineDir);
+ fs.writeFileSync(sourceMapPath, smContent);
+ }
+
+ delete projectJson.engineDir;
+ delete projectJson.modules;
+ delete projectJson.jsList;
+ fs.writeFileSync(path.join(realPublishDir, "project.json"), JSON.stringify(projectJson, null, 4));
+
+ var publishResDir = path.join(realPublishDir, "res");
+ core4cc.rmdirSyncRecursive(publishResDir);
+ core4cc.copyFiles(path.join(projectDir, "res"), publishResDir);
+ console.log("Finished!")
+});
View
17 tools/template/build.xml
@@ -1,18 +1,15 @@
<?xml version="1.0"?>
-<project name="Javascript compress project" basedir="." default="compile">
+<project name="Javascript compress project" basedir="%projectDir%" default="compile">
<taskdef name="jscomp" classname="com.google.javascript.jscomp.ant.CompileTask"
- classpath="${basedir}/../tools/compiler/compiler.jar"/>
+ classpath="%toolsDir%/compiler/compiler.jar"/>
<target name="compile">
- <jscomp compilationLevel="simple" warning="quiet"
- debug="false" output="myApp-HelloWorld.js">
- <!--sourceMapOutputFile="sourcemap"
- sourceMapFormat="V3">-->
- <externs dir="${basedir}/%engineDir%">
- <file name="core/cocos2d_externs.js"/>
- </externs>
- <sources dir="${basedir}/%engineDir%">
+ <jscomp compilationLevel="%compilationLevel%" warning="quiet"
+ debug="false" output="%publishDir%/%outputFileName%"
+ %sourceMapCfg%
+ >
+ <sources dir="%engineDir%">
%ccJsList%
</sources>
<sources dir="${basedir}">
Something went wrong with that request. Please try again.