UNPKG

dragonbones-runtime

Version:

the tools to build dragonbones file for diffrent framework

449 lines (392 loc) 13.6 kB
////////////////////////////////////////////////////////////////////////////////////// // // Copyright (c) 2014-present, Egret Technology. // All rights reserved. // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // * Neither the name of the Egret nor the // names of its contributors may be used to endorse or promote products // derived from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY EGRET AND CONTRIBUTORS "AS IS" AND ANY EXPRESS // OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES // OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. // IN NO EVENT SHALL EGRET AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;LOSS OF USE, DATA, // OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, // EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // ////////////////////////////////////////////////////////////////////////////////////// import cp = require('child_process'); import path = require('path'); import file = require('./FileUtil'); import UglifyJS = require("./uglify-js/uglifyjs"); import net = require('net'); //第三方调用时,可能不支持颜色显示,可通过添加 -nocoloroutput 移除颜色信息 var ColorOutputReplacements = { "{color_green}": "\033[1;32;1m", "{color_red}": "\033[0;31m", "{color_normal}": "\033[0m", "{color_gray}": "\033[0;37m", "{color_underline}": "\033[4;36;1m" }; var NoColorOutputReplacements = { "{color_green}": "", "{color_red}": "", "{color_normal}": "", "{color_gray}": "", "{color_underline}": "", "\n": "\\n", "\r": "" }; function formatStdoutString(message) { var replacements = ColorOutputReplacements; for (var raw in replacements) { let replace = (egret.args && egret.args.ide) ? "" : replacements[raw]; message = message.split(raw).join(replace); } return message; } global["$locale_strings"] = global["$locale_strings"] || {}; var $locale_strings = global["$locale_strings"]; /** * 全局多语言翻译函数 * @param code 要查询的字符串代码 * @param args 替换字符串中{0}标志的参数列表 * @returns 返回拼接后的字符串 */ export function tr(code: number, ...args): string { var text = $locale_strings[code]; if (!text) { return "{" + code + "}"; } text = format.apply(this, [text].concat(args)); return text; } export function format(text: string, ...args): string { var length = args.length; for (var i = 0; i < length || i < 5; i++) { text = text.replace(new RegExp("\\{" + i + "\\}", "ig"), args[i] || ""); } text = formatStdoutString(text); return text; } export function ti(code: number, injector?: any): string { var text = $locale_strings[code]; if (!text) { return "{" + code + "}"; } text = inject.call(this, text, injector); return text; } export function inject(text: string, injector?: any): string { if (injector) { for (var p in injector) { text = text.replace(new RegExp("\\{" + p + "\\}", "ig"), injector[p]); } } return text; } export function exit(code: number, ...args) { if (code) { var text: string = $locale_strings[code]; if (text && text.indexOf("{0}") < 0 || args && args.length > 0) { var message = tr.apply(this, [code].concat(args)); console.error(message); } } process.exit(code); } function _getEnv() { return process.env; } export function getEgretRoot() { var path = require("path"); var obj = _getEnv(); var egretRoot: string; var globalpath = module['paths'].concat(); var existsFlag = false; for (var i = 0; i < globalpath.length; i++) { var prefix = globalpath[i]; var url = file.joinPath(prefix, '../'); if (file.exists(file.joinPath(url, 'tools/bin/egret'))) { existsFlag = true; break; } url = prefix; if (file.exists(file.joinPath(url, 'tools/bin/egret'))) { existsFlag = true; break; } } if (!existsFlag) { throw new Error("can't find Egret"); } egretRoot = url; return file.escapePath(file.joinPath(egretRoot, '/')); } export function open(target, appName?) { var command; switch (process.platform) { case 'darwin': if (appName) { command = 'open -a "' + escape(appName) + '"'; } else { command = 'open'; } break; case 'win32': // if the first parameter to start is quoted, it uses that as the title // so we pass a blank title so we can quote the file we are opening if (appName) { command = 'start "" "' + escape(appName) + '"'; } else { command = 'start ""'; } break; default: if (appName) { command = escape(appName); } else { // use Portlands xdg-open everywhere else command = path.join(__dirname, '../vendor/xdg-open'); } break; } executeCommand(command + ' "' + escape(target) + '"') } export async function executeCommand(command: string) { return new Promise<{ error: Error, stdout: string, stderr: string }>((reslove, reject) => { cp.exec(command, {}, (error, stdout, stderr) => { reslove({ error, stdout, stderr }) }); }) } export function endWith(text: string, match: string) { return text.lastIndexOf(match) == (text.length - match.length); } function escape(s) { return s.replace(/"/, '\\\"'); } export function uglify(sourceFile: any) { const defines = { DEBUG: false, RELEASE: true } const result = UglifyJS.minify(sourceFile, { compress: { global_defs: defines }, fromString: true, output: { beautify: false } }); const code = result.code; return code; } export function minify(sourceFile: string): string export function minify(sourceFile: string, output: string): void export function minify(sourceFile: string, output?: string) { const defines = { DEBUG: false, RELEASE: true } //UglifyJS参数参考这个页面:https://github.com/mishoo/UglifyJS2 const result = UglifyJS.minify(sourceFile, { compress: { global_defs: defines }, output: { beautify: false } }); const code = result.code; if (output) { file.save(output, code); } else { return code; } } export function clean(path: string, excludes?: string[]) { var fileList = file.getDirectoryListing(path); var length = fileList.length; for (var i = 0; i < length; i++) { var path = fileList[i]; if (excludes && excludes.indexOf(path) >= 0) continue; file.remove(path); } } export function getNetworkAddress(): string[] { var os = require('os'); var ifaces = os.networkInterfaces(); var ips: string[] = []; Object.keys(ifaces).forEach(function (ifname) { var alias = 0; ifaces[ifname].forEach(function (iface) { if ('IPv4' !== iface.family || iface.internal !== false) { // skip over internal (i.e. 127.0.0.1) and non-ipv4 addresses return; } ips.push(iface.address); }); }); return ips; } export function measure(target: any, propertyKey: string, descriptor: TypedPropertyDescriptor<any>) { const method = descriptor.value; descriptor.value = function (...arg) { const timeBuildStart = (new Date()).getTime(); let promise = method.apply(this, arg); return promise.then((result) => { const timeBuildEnd = (new Date()).getTime(); const timeBuildUsed = (timeBuildEnd - timeBuildStart) / 1000; console.log(tr(1108, timeBuildUsed)); return result; }) } } export function getAvailablePort(port = 0) { return new Promise<number>((resolve, reject) => { function getPort() { var server = net.createServer(); server.on('listening', function () { port = server.address().port server.close() }) server.on('close', function () { resolve(port) }) server.on('error', function (err) { port++; getPort(); }) server.listen(port, '0.0.0.0') } getPort(); }) } export function checkEgret() { var options = egret.args; if (file.exists(options.srcDir) == false || file.exists(options.templateDir) == false) { exit(10015, options.projectDir); } } export function isFormatString(text: string): boolean { if (text) { if (text.indexOf("\n") != -1) { return true; } } return false; } export function addIndents(times: number, text: string) { if (times == 0) return text; var added = '\t'; for (var i = 0; i < times - 1; i++) { added += added; } //开头 if (text != null) { text = added + text; } //替换\n return text.replace(new RegExp("\\n", "ig"), '\n' + added); } interface MapLike<T> { [index: string]: T; } export interface Map<T> extends MapLike<T> { __mapBrand: any; } export function createMap<T>(template?: MapLike<T>): Map<T> { const map: Map<T> = Object.create(null); // tslint:disable-line:no-null-keyword // Using 'delete' on an object causes V8 to put the object in dictionary mode. // This disables creation of hidden classes, which are expensive when an object is // constantly changing shape. map["__"] = undefined; delete map["__"]; // Copies keys/values from template. Note that for..in will not throw if // template is undefined, and instead will just exit the loop. for (const key in template) if (Object.prototype.hasOwnProperty.call(template, key)) { map[key] = template[key]; } return map; } export function shell(path: string, args: string[], opt?: cp.SpawnOptions, verbase?: boolean): Promise<number> { let stdout = ""; let stderr = ""; var cmd = `${path} ${args.join(" ")}`; if (verbase) { console.log(cmd); } let printStdoutBufferMessage = (message) => { var str = message.toString(); stdout += str; if (verbase) { console.log(str); } }; let printStderrBufferMessage = (message) => { var str = message.toString(); stderr += str; if (verbase) { console.log(str); } }; let callback = (reslove, reject) => { var shell = cp.spawn(path, args, opt); shell.on("error", (message) => { console.log(message); }); shell.stderr.on("data", printStderrBufferMessage); shell.stderr.on("error", printStderrBufferMessage); shell.stdout.on("data", printStdoutBufferMessage); shell.stdout.on("error", printStdoutBufferMessage); shell.on('exit', function (code) { if (code != 0) { if (verbase) { console.log('Failed: ' + code); } reject({ code, stdout, stderr }); } else { reslove({ code, stdout, stderr }); } }); }; return new Promise(callback); }; let error_code_filename = path.join(__dirname, "../error_code.json"); let errorcode = file.readJSONSync(error_code_filename, { "encoding": "utf-8" }); export class CliException extends Error { public message; constructor(public errorId, param?: string) { super(); var message: string = errorcode[this.errorId]; if (message) { message = message.replace('{0}', param); } else { message = `unkown error : ${errorId}`; console.error(message); } this.message = message; } } export function findValidatePathSync(pathStr: string): string { if (!pathStr) { pathStr = process.cwd(); } else { if (!file.existsSync(pathStr)) { pathStr = path.join(process.cwd(), pathStr); } } return pathStr; } export const cache: MethodDecorator = (target, propertyKey, descriptor: TypedPropertyDescriptor<any>) => { const method = descriptor.value; let cacheValue = null; descriptor.value = function (...arg) { if (!cacheValue) { cacheValue = method.apply(this, arg); } return cacheValue; } }