const fs = require("fs"); const path = require("path"); const prettier = require("prettier"); const { exec } = require("child_process"); const { search, initDepts } = require("./es6.xtype"); async function fix(path) { new Promise(res => { exec(`yarn eslint --fix ${path}`, () => { res(); }); }); } const target = [ "isNull", "toPix", "isKey", "isObject", "map", "extend", "isFunction", "isEmptyArray", "isArray", "Controller", "createWidget", "Events", "emptyFn", "nextTick", "bind", "i18nText", "isNotNull", "isString", "isNumber", "isEmpty", "isEmptyString", "any", "deepContains", "isNotEmptyString", "each", "contains", "remove", "createItems", "makeArrayByArray", ]; // 加载模块 const loader = { G: { "@/core": { shortcut: true } }, async load(srcName, module) { const G = loader.G; if (target.indexOf(module) >= 0) { G["@/core"][module] = true; return true; } const key = search(srcName, module); if (key) { if (!G[key]) { G[key] = {}; } G[key][module] = true; } return !!key; }, }; async function handleFile(srcName) { const G = loader.G; const sourceCode = fs.readFileSync(srcName).toString(); const result = /BI\.(.*?)\s\=\sBI\.inherit\(/.exec(sourceCode); if (!result) { console.log(`可能是已经es6过了 ${srcName}`); return; } const clzName = result[1]; const superName = /inherit\(BI\.(.*?),/.exec(sourceCode)[1]; // const xtype = /BI.shortcut\(\"(.*?)\"/.exec(sourceCode)[1]; const collection = { "static": {}, attr: {}, }; // eslint-disable-next-line no-unused-vars const BI = { inherit(_, options) { collection.methods = Object.keys(options) .filter(key => typeof options[key] === "function") .map(key => options[key]); Object.keys(options) .filter(key => typeof options[key] !== "function") .forEach(key => { collection.attr[key] = options[key]; }); return collection.static; }, shortcut(xtype) { collection.xtype = xtype; }, }; // eslint-disable-next-line no-eval eval(sourceCode); let M = ""; let E = ""; let I = ""; let A = ""; loader.load(srcName, superName); Object.keys(collection.attr).forEach(key => { A = `${key} = ${JSON.stringify(collection.attr[key])};`; }); // 静态方法 Object.keys(collection.static).forEach(key => { E += `\tstatic ${key} = "${collection.static[key]}"\n`; }); // 对函数进行替换 collection.methods.forEach(el => { let f = `${el.toString().replace(/^function/, el.name)}\n`; // 换 BI.Button.superclass,就说能不能跑吧 for (let i = 0; i < 100; i++) { f = f.replace(`BI.${clzName}.superclass`, "super"); } // 换 super._defaultConfig f = f.replace( /super\._defaultConfig\.apply\(this,\sarguments\)/g, "super._defaultConfig(...arguments)" ); // 换 super.xxx.apply f = f.replace(/super\.(.*?)\.apply\(this,\sarguments\)/g, a => { const f = /super\.(.*?)\.apply\(this,\sarguments\)/.exec(a); return `super.${f[1]}(...arguments)`; }); // 尝试换掉所有的 BI.xxx. BI.xxx( BI.xxx[空白] f = f.replace(/BI\.(.*?)(\.|\(|\s|,)/g, matchedSentence => { const match = /BI\.(.*?)(\.|\(|\s|,)/.exec(matchedSentence); const target = match[1]; const end = match[2]; // 尝试加载 target const loadSuccess = loader.load(srcName, target); if (loadSuccess) { return target + end; } else { console.log(`加载 ${target}失败`); return matchedSentence; } }); M += `${f}\n`; }); Object.keys(G).forEach(moduleKey => { if (moduleKey === path.basename(srcName).replace(/.js$/g, "")) { return; } let i = ""; Object.keys(G[moduleKey]).forEach(key => { i += `${key}, `; }); I += `import {${i}} from '${moduleKey}'\n`; }); const outputCode = ` ${I} @shortcut() export class ${clzName} extends ${superName} { \tstatic xtype = "${collection.xtype}" ${A} ${E} ${M} } `; const prettierCode = prettier.format(outputCode, { tabWidth: 4, }); fs.writeFileSync(srcName, prettierCode); await fix(srcName); return clzName; } async function traverse(srcName) { if (srcName.indexOf("__test__") >= 0) return; if (srcName.endsWith(".js")) { return await handleFile(srcName); } else { const stat = fs.statSync(srcName); const flag = stat.isDirectory(); if (flag) { const files = fs.readdirSync(srcName); // let indexContent = ""; for (let i = 0; i < files.length; i++) { const file = files[i]; await traverse(path.resolve(srcName, file)); // const clzName = await traverse(path.resolve(srcName, file)); // const moduleName = path.basename(srcName).replace(/.js$/, ""); // if (clzName) { // indexContent += `export { ${clzName} } from '${moduleName}'\n`; // } } } } } const srcName = process.argv[2]; initDepts().then(() => { const content = fs.readFileSync("src/core/2.base.js").toString(); let result = content.match(/export function (.*?)\(/g); target.push( ...result.map(el => el.replace("export function ", "").replace("(", "") ) ); result = content.match(/export const (.*?) =/g); target.push( ...result.map(el => el.replace("export const ", "").replace(" =", "")) ); traverse(srcName); });