diff --git a/es6.babel.js b/es6.babel.js new file mode 100644 index 000000000..b2f93ed08 --- /dev/null +++ b/es6.babel.js @@ -0,0 +1,19 @@ +module.exports = { + plugins: [ + [ + "@babel/plugin-proposal-decorators", + { + legacy: true + } + ], + [ + "module-resolver", + { + root: ["./src"], + alias: { + "@": "./src" + } + } + ] + ] +}; diff --git a/es6.js b/es6.js deleted file mode 100644 index 82231feec..000000000 --- a/es6.js +++ /dev/null @@ -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}`); - }); -}); diff --git a/es6.xtype.js b/es6.xtype.js deleted file mode 100644 index db1babcbb..000000000 --- a/es6.xtype.js +++ /dev/null @@ -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; - - - - -