Treecat
2 years ago
3 changed files with 19 additions and 710 deletions
@ -0,0 +1,19 @@ |
|||||||
|
module.exports = { |
||||||
|
plugins: [ |
||||||
|
[ |
||||||
|
"@babel/plugin-proposal-decorators", |
||||||
|
{ |
||||||
|
legacy: true |
||||||
|
} |
||||||
|
], |
||||||
|
[ |
||||||
|
"module-resolver", |
||||||
|
{ |
||||||
|
root: ["./src"], |
||||||
|
alias: { |
||||||
|
"@": "./src" |
||||||
|
} |
||||||
|
} |
||||||
|
] |
||||||
|
] |
||||||
|
}; |
@ -1,538 +0,0 @@ |
|||||||
const fs = require("fs"); |
|
||||||
const path = require("path"); |
|
||||||
const prettier = require("prettier"); |
|
||||||
const { exec } = require("child_process"); |
|
||||||
const { search, initDepts, depts } = require("./es6.xtype"); |
|
||||||
const lodash = require("lodash"); |
|
||||||
const DEPTS = depts; |
|
||||||
|
|
||||||
// const XTYPE_ONLY = false;
|
|
||||||
// const THIS_REPLACE = false;
|
|
||||||
|
|
||||||
const ConflictImport = []; |
|
||||||
const CircularDependency = []; |
|
||||||
|
|
||||||
function objHaveFunction(obj) { |
|
||||||
if (obj === null) { |
|
||||||
return false; |
|
||||||
} |
|
||||||
|
|
||||||
return Object.keys(obj).some(key => { |
|
||||||
const value = obj[key]; |
|
||||||
if (typeof value === "object") { |
|
||||||
return objHaveFunction(value); |
|
||||||
} else if (typeof value === "function") { |
|
||||||
return true; |
|
||||||
} |
|
||||||
|
|
||||||
return false; |
|
||||||
}); |
|
||||||
} |
|
||||||
|
|
||||||
function parserImport(code) { |
|
||||||
const reg = /import {([\s\S]*?)} from "(.*?)";/g; |
|
||||||
|
|
||||||
const importMap = {}; |
|
||||||
let regResult = reg.exec(code); |
|
||||||
while (regResult) { |
|
||||||
importMap[regResult[2]] = regResult[1] |
|
||||||
.split(",") |
|
||||||
.map(el => el.trim()) |
|
||||||
.filter(el => el); |
|
||||||
regResult = reg.exec(code); |
|
||||||
} |
|
||||||
|
|
||||||
return importMap; |
|
||||||
} |
|
||||||
|
|
||||||
async function saveAndFixCode(path, code) { |
|
||||||
let _code = code; |
|
||||||
if (!code) { |
|
||||||
_code = fs.readFileSync(path).toString(); |
|
||||||
} |
|
||||||
const prettierCode = prettier.format(_code, { |
|
||||||
tabWidth: 4, |
|
||||||
parser: "babel", |
|
||||||
printWidth: 120, |
|
||||||
}); |
|
||||||
fs.writeFileSync(path, prettierCode); |
|
||||||
|
|
||||||
new Promise(res => { |
|
||||||
exec(`yarn eslint --fix ${path}`, () => { |
|
||||||
res(); |
|
||||||
}); |
|
||||||
}); |
|
||||||
} |
|
||||||
|
|
||||||
function divideFile(srcName) { |
|
||||||
const targetPath = srcName.match(/.*\//g); |
|
||||||
const sourceCode = fs.readFileSync(srcName).toString(); |
|
||||||
const splitSourceCode = sourceCode.match(/[\.\s]{1}[^\s\.]+?\s=\sBI\.inherit\([^]*?BI\.shortcut.*\;/g); |
|
||||||
const newFileNames = []; |
|
||||||
for (let i = 0; i < splitSourceCode.length; i++) { |
|
||||||
// 去除开头的 空格 或者 .
|
|
||||||
const newCode = splitSourceCode[i].slice(1); |
|
||||||
// 匹配第一个等号之前的组件名
|
|
||||||
const componentName = /BI\.shortcut\("(.*)"/.exec(newCode)[1]; |
|
||||||
// 文件名转化 ButtonIcon => demo.button.icon.js
|
|
||||||
const demoFileName = componentName + '.js'; |
|
||||||
newFileNames.push(demoFileName); |
|
||||||
// 代码 componentName 前面加上 BI.
|
|
||||||
const fileCode = 'BI.' + newCode; |
|
||||||
|
|
||||||
// 规范最后一行的组件为 BI.Button
|
|
||||||
const targetComponet = /(BI\..*)\s=/.exec(fileCode)[1]; |
|
||||||
// 最后一行的内容
|
|
||||||
const replaceContext = /BI\.shortcut.*;/.exec(fileCode)[0]; |
|
||||||
// 替换
|
|
||||||
const finalCode = fileCode.replace(replaceContext,`BI.shortcut("${componentName}", ${targetComponet});`) |
|
||||||
|
|
||||||
// 创建新文件
|
|
||||||
fs.writeFileSync(targetPath + demoFileName, finalCode); |
|
||||||
} |
|
||||||
return newFileNames; |
|
||||||
} |
|
||||||
|
|
||||||
// const target = [];
|
|
||||||
|
|
||||||
// 加载模块
|
|
||||||
const loader = { |
|
||||||
// G: { "@/core": { shortcut: true } },
|
|
||||||
load(srcName, module) { |
|
||||||
const G = loader.G; |
|
||||||
// if (target.indexOf(module) >= 0) {
|
|
||||||
// G["@/core"][module] = true;
|
|
||||||
|
|
||||||
// return true;
|
|
||||||
// }
|
|
||||||
if (module.startsWith('"bi.')) { |
|
||||||
const key = search(srcName, module); |
|
||||||
if (key) { |
|
||||||
if (!G[key]) { |
|
||||||
G[key] = {}; |
|
||||||
} |
|
||||||
const clzName = depts[module].clzName; |
|
||||||
G[key][clzName] = true; |
|
||||||
} |
|
||||||
|
|
||||||
return !!key; |
|
||||||
} else { |
|
||||||
const key = search(srcName, module); |
|
||||||
if (key) { |
|
||||||
if (!G[key]) { |
|
||||||
G[key] = {}; |
|
||||||
} |
|
||||||
G[key][module] = true; |
|
||||||
} |
|
||||||
|
|
||||||
return !!key; |
|
||||||
} |
|
||||||
}, |
|
||||||
}; |
|
||||||
|
|
||||||
async function handleFile(srcName) { |
|
||||||
await saveAndFixCode(srcName); |
|
||||||
// 全局状态回归
|
|
||||||
let G = (loader.G = {}); |
|
||||||
|
|
||||||
const sourceCode = fs.readFileSync(srcName).toString(); |
|
||||||
if (sourceCode.match(/shortcut/g).length > 1) { |
|
||||||
console.log('该文件存在多处BI.shorcut, 需要拆分...'); |
|
||||||
const newTargets = divideFile(srcName); |
|
||||||
newTargets.forEach(name => console.log(name)); |
|
||||||
return; |
|
||||||
} |
|
||||||
|
|
||||||
const result = /BI\.(.*?)\s=\sBI\.inherit\(/.exec(sourceCode); |
|
||||||
|
|
||||||
if (!result) { |
|
||||||
// console.log(`已经es6过,替换 xtype => ${srcName}`);
|
|
||||||
if (!/export class/.test(sourceCode)) { |
|
||||||
// console.log("忽略文件", srcName);
|
|
||||||
|
|
||||||
return; |
|
||||||
} |
|
||||||
|
|
||||||
// 处理 xtype
|
|
||||||
const noXtypeCode = sourceCode.replace(/type:\s?"bi\.(.*?)"/g, v => { |
|
||||||
const matchedSentence = v.replace(/type:\s?/, ""); |
|
||||||
const loadSuccess = loader.load(srcName, matchedSentence); |
|
||||||
if (loadSuccess) { |
|
||||||
const clzName = depts[matchedSentence].clzName; |
|
||||||
|
|
||||||
return `type: ${clzName}.xtype`; |
|
||||||
} else { |
|
||||||
console.log(`xtype 替换失败 ${matchedSentence} `); |
|
||||||
|
|
||||||
return v; |
|
||||||
} |
|
||||||
}); |
|
||||||
// 识别 import
|
|
||||||
const importMap = parserImport(noXtypeCode); |
|
||||||
|
|
||||||
// 合并原来的 import 到 G
|
|
||||||
lodash.forEach(importMap, (depts, module) => { |
|
||||||
depts.forEach(dept => { |
|
||||||
if (!G[module]) { |
|
||||||
G[module] = {}; |
|
||||||
} |
|
||||||
|
|
||||||
G[module][dept] = true; |
|
||||||
}); |
|
||||||
}); |
|
||||||
|
|
||||||
|
|
||||||
// 合并包
|
|
||||||
const crossPackages = fs.readdirSync("src").map(el => `@/${el}`); |
|
||||||
lodash.forEach(G, (depts, module) => { |
|
||||||
crossPackages.forEach(crosspackage => { |
|
||||||
if (module.indexOf(crosspackage.replace(/^@\//, "")) >= 0) { |
|
||||||
if (!G[crosspackage]) { |
|
||||||
G[crosspackage] = {}; |
|
||||||
} |
|
||||||
Object.assign(G[crosspackage], depts); |
|
||||||
} |
|
||||||
}); |
|
||||||
}); |
|
||||||
const tmpG = {}; |
|
||||||
lodash.forEach(G, (depts, module) => { |
|
||||||
const flag = lodash.some( |
|
||||||
crossPackages, |
|
||||||
crosspackage => |
|
||||||
module.indexOf(crosspackage) >= 0 && !module.startsWith("@"), |
|
||||||
); |
|
||||||
if (!flag) { |
|
||||||
tmpG[module] = depts; |
|
||||||
} |
|
||||||
}); |
|
||||||
|
|
||||||
let circle = false; |
|
||||||
// 处理循环依赖,base: ["@/case", "@/base", "@/widget"] 等于 base 不能直接引数组内的包
|
|
||||||
const forbiddenCrossRules = { |
|
||||||
base: ["@/case", "@/base", "@/widget"], |
|
||||||
"case": ["@/case", "@/widget"], |
|
||||||
widget: ["@/widget"], |
|
||||||
component: ["@/component"], |
|
||||||
core: ["@/core", "@base", "@/widget", "@/case"], |
|
||||||
}; |
|
||||||
|
|
||||||
const forbiddenKeys = []; |
|
||||||
const circleG = {}; |
|
||||||
|
|
||||||
lodash.forEach(G, (depts, module) => { |
|
||||||
// 找出 rule
|
|
||||||
const packages = Object.keys(forbiddenCrossRules); |
|
||||||
|
|
||||||
let key = packages.filter( |
|
||||||
_package => srcName.indexOf(_package) >= 0, |
|
||||||
); |
|
||||||
if (key.length !== 1) { |
|
||||||
throw new Error( |
|
||||||
"理论不可能出现这个问题,需要 treecat 优化下找包逻辑1", |
|
||||||
); |
|
||||||
} |
|
||||||
key = key[0]; |
|
||||||
const rule = forbiddenCrossRules[key]; |
|
||||||
|
|
||||||
if (lodash.includes(rule, module)) { |
|
||||||
circle = true; |
|
||||||
|
|
||||||
const deptsArr = Object.keys(depts); |
|
||||||
if (deptsArr.filter(dept => !DEPTS[dept]).length > 0) { |
|
||||||
throw new Error( |
|
||||||
"理论不可能出现这个问题,需要 treecat 优化下找包逻辑2", |
|
||||||
); |
|
||||||
} |
|
||||||
deptsArr |
|
||||||
.filter(dept => DEPTS[dept]) |
|
||||||
.forEach(dept => { |
|
||||||
const value = `@${DEPTS[dept].replace(path.resolve("src"), "").replace(/\\/g, "/").replace(/\.js$/, "")}`; |
|
||||||
if (!tmpG[value]) { |
|
||||||
tmpG[value] = {}; |
|
||||||
} |
|
||||||
tmpG[value][dept] = true; |
|
||||||
}); |
|
||||||
forbiddenKeys.push(module); |
|
||||||
} |
|
||||||
}); |
|
||||||
Object.assign(tmpG, circleG); |
|
||||||
forbiddenKeys.forEach(key => { |
|
||||||
delete tmpG[key]; |
|
||||||
}); |
|
||||||
|
|
||||||
|
|
||||||
// 较验手工 import 错误
|
|
||||||
const map = {}; |
|
||||||
let conflict = false; |
|
||||||
|
|
||||||
lodash.forEach(tmpG, (depts, module) => { |
|
||||||
lodash.forEach(depts, (_, _import) => { |
|
||||||
if (map[_import] && map[_import] !== module) { |
|
||||||
conflict = true; |
|
||||||
} |
|
||||||
|
|
||||||
map[_import] = module; |
|
||||||
}); |
|
||||||
}); |
|
||||||
|
|
||||||
conflict && ConflictImport.push(srcName); |
|
||||||
circle && CircularDependency.push(srcName); |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
G = tmpG; |
|
||||||
|
|
||||||
const noImportCode = noXtypeCode.replace( |
|
||||||
/import {([\s\S]*?)} from "(.*?)";/g, |
|
||||||
"", |
|
||||||
); |
|
||||||
|
|
||||||
let I = ""; |
|
||||||
Object.keys(G).forEach(key => { |
|
||||||
let moduleKey = key; |
|
||||||
if (moduleKey === path.basename(srcName).replace(/.js$/g, "")) { |
|
||||||
return; |
|
||||||
} |
|
||||||
let i = ""; |
|
||||||
Object.keys(G[moduleKey]).forEach(key => { |
|
||||||
i += `${key}, `; |
|
||||||
}); |
|
||||||
|
|
||||||
// 必须以 . 开头
|
|
||||||
const moduleInValid = /^[^@.]/.test(moduleKey); |
|
||||||
if (moduleInValid) { |
|
||||||
moduleKey = `./${moduleKey}`; |
|
||||||
} |
|
||||||
|
|
||||||
I += `import {${i}} from '${moduleKey}'\n`; |
|
||||||
}); |
|
||||||
const code = `${I}\n${noImportCode}`; |
|
||||||
|
|
||||||
await saveAndFixCode(srcName, code); |
|
||||||
|
|
||||||
return; |
|
||||||
} |
|
||||||
|
|
||||||
G["@/core"] = { shortcut: true }; |
|
||||||
|
|
||||||
const clzName = result[1]; |
|
||||||
|
|
||||||
if (!clzName) { |
|
||||||
console.log(`${srcName} 不需要 es6 化`); |
|
||||||
|
|
||||||
return; |
|
||||||
} |
|
||||||
|
|
||||||
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 = { |
|
||||||
[clzName]: clzName, |
|
||||||
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; |
|
||||||
}, |
|
||||||
extend(targetClz, o) { |
|
||||||
Object.assign(collection.static, o); |
|
||||||
}, |
|
||||||
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 => { |
|
||||||
const value = collection.attr[key]; |
|
||||||
if (typeof value === "function" || typeof value === "number") { |
|
||||||
A += `\t${key} = ${value}\n`; |
|
||||||
} else if (typeof value === "string") { |
|
||||||
A += `\t${key} = "${value}"\n`; |
|
||||||
} else if (typeof value === "object") { |
|
||||||
if (objHaveFunction(value)) { |
|
||||||
throw new Error("G"); |
|
||||||
} else { |
|
||||||
A += `\t${key} = ${JSON.stringify(value)}\n`; |
|
||||||
} |
|
||||||
} |
|
||||||
}); |
|
||||||
|
|
||||||
// 静态方法
|
|
||||||
Object.keys(collection.static).forEach(key => { |
|
||||||
// console.log(key, collection.static[key], typeof collection.static[key])
|
|
||||||
const value = collection.static[key]; |
|
||||||
if (typeof value === "function" || typeof value === "number") { |
|
||||||
E += `\tstatic ${key} = ${value}\n`; |
|
||||||
} else if (typeof value === "string") { |
|
||||||
E += `\tstatic ${key} = "${value}"\n`; |
|
||||||
} else if (typeof value === "object") { |
|
||||||
if (objHaveFunction(value)) { |
|
||||||
throw new Error("G"); |
|
||||||
} else { |
|
||||||
E += `\tstatic ${key} = ${JSON.stringify(value)}\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(`BI 变量替换失败 BI.${target}`); |
|
||||||
|
|
||||||
return matchedSentence; |
|
||||||
} |
|
||||||
}); |
|
||||||
|
|
||||||
// 尝试对 xtype 进行替换
|
|
||||||
f = f.replace(/"bi\.(.*?)"/g, matchedSentence => { |
|
||||||
const loadSuccess = loader.load(srcName, matchedSentence); |
|
||||||
if (loadSuccess) { |
|
||||||
const clzName = depts[matchedSentence].clzName; |
|
||||||
|
|
||||||
return `${clzName}.xtype`; |
|
||||||
} else { |
|
||||||
// console.log(`(没事) xtype 替换失败 ${matchedSentence} `);
|
|
||||||
|
|
||||||
return matchedSentence; |
|
||||||
} |
|
||||||
}); |
|
||||||
|
|
||||||
M += `${f}\n`; |
|
||||||
}); |
|
||||||
|
|
||||||
if (!collection.xtype) { |
|
||||||
delete G["@/core"].shortcut; |
|
||||||
} |
|
||||||
|
|
||||||
Object.keys(G).forEach(key => { |
|
||||||
let moduleKey = key; |
|
||||||
if (moduleKey === path.basename(srcName).replace(/.js$/g, "")) { |
|
||||||
return; |
|
||||||
} |
|
||||||
let i = ""; |
|
||||||
Object.keys(G[moduleKey]).forEach(key => { |
|
||||||
i += `${key}, `; |
|
||||||
}); |
|
||||||
|
|
||||||
// 必须以 . 开头
|
|
||||||
const moduleInValid = /^[^@.]/.test(moduleKey); |
|
||||||
if (moduleInValid) { |
|
||||||
moduleKey = `./${moduleKey}`; |
|
||||||
} |
|
||||||
|
|
||||||
I += `import {${i}} from '${moduleKey}'\n`; |
|
||||||
}); |
|
||||||
|
|
||||||
const outputCode = ` |
|
||||||
${I} |
|
||||||
|
|
||||||
${collection.xtype ? "@shortcut()" : ""} |
|
||||||
export class ${clzName} extends ${superName} { |
|
||||||
${collection.xtype ? `static xtype = "${collection.xtype}"` : ""} |
|
||||||
|
|
||||||
${A} |
|
||||||
|
|
||||||
${E} |
|
||||||
|
|
||||||
${M} |
|
||||||
} |
|
||||||
`;
|
|
||||||
await saveAndFixCode(srcName, outputCode); |
|
||||||
|
|
||||||
return clzName; |
|
||||||
} |
|
||||||
|
|
||||||
async function traverse(srcName) { |
|
||||||
if (srcName.indexOf("__test__") >= 0) return; |
|
||||||
|
|
||||||
if (srcName.endsWith(".js")) { |
|
||||||
try { |
|
||||||
return await handleFile(srcName); |
|
||||||
} catch (error) { |
|
||||||
console.log(`文件处理失败 ${srcName} \n`); |
|
||||||
console.error(error); |
|
||||||
|
|
||||||
return; |
|
||||||
} |
|
||||||
} 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(async () => { |
|
||||||
await traverse(srcName); |
|
||||||
|
|
||||||
// 对数据处理
|
|
||||||
ConflictImport.forEach(el => { |
|
||||||
console.log(`导入冲突 ${el}`); |
|
||||||
}); |
|
||||||
CircularDependency.forEach(el => { |
|
||||||
console.log(`出现循环依赖(已经fixed) ${el}`); |
|
||||||
}); |
|
||||||
}); |
|
@ -1,172 +0,0 @@ |
|||||||
const fs = require("fs"); |
|
||||||
const path = require("path"); |
|
||||||
const lodash = require("lodash"); |
|
||||||
|
|
||||||
const depts = {}; |
|
||||||
|
|
||||||
async function handle(filename) { |
|
||||||
if (path.extname(filename) !== ".js") { |
|
||||||
return; |
|
||||||
} |
|
||||||
const code = fs.readFileSync(filename).toString(); |
|
||||||
|
|
||||||
const inheritRegResult = /BI\.(.*?)\s=\sBI\.inherit\(/.exec(code); |
|
||||||
if (inheritRegResult) { |
|
||||||
const clzName = inheritRegResult[1]; |
|
||||||
depts[clzName] = filename; |
|
||||||
} else { |
|
||||||
// 一个文件夹里面可能有多个 xtype
|
|
||||||
const reg = /export\s+class\s+(.*?)([\s|{])([\w\W]*?)static xtype\s?=\s?((["|'])(.*?)(\5))/g; |
|
||||||
Array.from(code.matchAll(reg)).forEach(res => { |
|
||||||
const xtype = res[4]; |
|
||||||
depts[xtype] = { |
|
||||||
clzName: res[1], |
|
||||||
clzPath: filename, |
|
||||||
}; |
|
||||||
}); |
|
||||||
// 同时找一下 export
|
|
||||||
if (path.basename(filename) !== "index.js") { |
|
||||||
const regs = [ |
|
||||||
/export function (.*?)\(/g, |
|
||||||
/export const (.*?) =/g, |
|
||||||
/export class (.*?) /g, |
|
||||||
/export \{([\w\W]*?)\}/g, |
|
||||||
]; |
|
||||||
regs.forEach((reg, index) => { |
|
||||||
Array.from(code.matchAll(reg)).forEach(el => { |
|
||||||
depts[el[1]] = filename; |
|
||||||
if (index === 3) { |
|
||||||
el[1].split(",").map(el => el.trim()).forEach(key => { |
|
||||||
depts[key] = filename; |
|
||||||
}); |
|
||||||
} |
|
||||||
}); |
|
||||||
}); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
function isExist(filePath) { |
|
||||||
return fs.existsSync(filePath); |
|
||||||
} |
|
||||||
|
|
||||||
async function bfs(filename) { |
|
||||||
const stat = fs.statSync(filename); |
|
||||||
const isDir = stat.isDirectory(); |
|
||||||
if (isDir) { |
|
||||||
const files = fs.readdirSync(filename); |
|
||||||
for (let i = 0; i < files.length; i++) { |
|
||||||
const file = files[i]; |
|
||||||
await bfs(path.resolve(filename, file)); |
|
||||||
} |
|
||||||
} else { |
|
||||||
await handle(filename); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
async function initDepts() { |
|
||||||
// dfs 构建依赖关系
|
|
||||||
await bfs(path.resolve("src")); |
|
||||||
const m = {}; |
|
||||||
lodash.forEach(depts, value => { |
|
||||||
if (typeof value === "object") { |
|
||||||
m[value.clzName] = value.clzPath; |
|
||||||
} |
|
||||||
}); |
|
||||||
Object.assign(depts, m); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
function search(src, module) { |
|
||||||
let clzName = module; |
|
||||||
let clzPath = depts[module]; |
|
||||||
|
|
||||||
if (!depts[clzName]) { |
|
||||||
return ""; |
|
||||||
} |
|
||||||
|
|
||||||
if (clzName.indexOf("\"") >= 0) { |
|
||||||
clzName = depts[module].clzName; |
|
||||||
clzPath = depts[module].clzPath; |
|
||||||
} |
|
||||||
|
|
||||||
const dstName = path.basename(clzPath).replace(/.js$/g, ""); |
|
||||||
const dstPath = path.normalize(clzPath).split("src")[1].split("\\").join("/").split("/"); |
|
||||||
const srcPath = path.normalize(src).split("src")[1].split("\\").join("/").split("/"); |
|
||||||
|
|
||||||
// console.log("src", src);
|
|
||||||
// console.log("dst", depts[clzName]);
|
|
||||||
|
|
||||||
dstPath.shift(); |
|
||||||
dstPath.pop(); |
|
||||||
srcPath.shift(); |
|
||||||
srcPath.pop(); |
|
||||||
|
|
||||||
const findDstIndexPath = (dstArr, startIndex) => { |
|
||||||
let i = startIndex; |
|
||||||
|
|
||||||
while (!isExist(path.resolve("src", dstArr.slice(0, i + 1).join("/"), "index.js")) && i < dstArr.length) { |
|
||||||
i++; |
|
||||||
} |
|
||||||
|
|
||||||
if (i < dstArr.length) { |
|
||||||
return dstArr.slice(startIndex, i + 1).join("/"); |
|
||||||
} else { |
|
||||||
return `${dstArr.slice(startIndex).join("/")}/${dstName}`; |
|
||||||
} |
|
||||||
}; |
|
||||||
|
|
||||||
// 不同包
|
|
||||||
if (dstPath[0] !== srcPath[0]) { |
|
||||||
return `@/${dstPath[0]}`; |
|
||||||
} |
|
||||||
|
|
||||||
// 同包
|
|
||||||
let i = 0; |
|
||||||
while (dstPath[i] === srcPath[i] && i < dstPath.length && i < srcPath.length) { |
|
||||||
i++; |
|
||||||
} |
|
||||||
|
|
||||||
// i 代表同名的位置
|
|
||||||
i--; |
|
||||||
|
|
||||||
// 没有匹配完
|
|
||||||
if (i < srcPath.length) { |
|
||||||
let result = ""; |
|
||||||
|
|
||||||
// 回溯,向上找,回到目录 i
|
|
||||||
for (let j = srcPath.length - 1; j > i; j--) { |
|
||||||
result += "../"; |
|
||||||
} |
|
||||||
|
|
||||||
// 匹配过的下一个位置
|
|
||||||
i++; |
|
||||||
|
|
||||||
if (i >= dstPath.length) { |
|
||||||
// 越界
|
|
||||||
return `${result}${dstName}`; |
|
||||||
} else { |
|
||||||
// 看看这个目录下有没有 index
|
|
||||||
return result + findDstIndexPath(dstPath, i); |
|
||||||
} |
|
||||||
} else if (i === srcPath.length) { |
|
||||||
if (i === dstPath.length) { |
|
||||||
return dstName; |
|
||||||
} else if (i < dstPath.length) { |
|
||||||
return findDstIndexPath(dstPath, i); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
// search(process.argv[2], "Text").then(res => {
|
|
||||||
// console.log(res);
|
|
||||||
// });
|
|
||||||
|
|
||||||
exports.initDepts = initDepts; |
|
||||||
exports.search = search; |
|
||||||
exports.depts = depts; |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in new issue