forked from fanruan/fineui
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
245 lines
6.3 KiB
245 lines
6.3 KiB
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); |
|
});
|
|
|