UNPKG

@lcap/builder

Version:
322 lines (321 loc) 13.9 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.forkComponent = void 0; const fs_extra_1 = __importDefault(require("fs-extra")); const path_1 = __importDefault(require("path")); const fast_glob_1 = __importDefault(require("fast-glob")); const vite_1 = require("vite"); const parser = __importStar(require("@babel/parser")); const traverse_1 = __importDefault(require("@babel/traverse")); const generator_1 = __importDefault(require("@babel/generator")); const constants_1 = require("./constants"); const fs_1 = require("../utils/fs"); const logger_1 = __importDefault(require("../utils/logger")); const suffixes = ['.js', '.jsx', '.ts', '.tsx']; function isExist(filePath) { return ['', ...suffixes].some((suffix) => { const fullPath = filePath + suffix; return fs_extra_1.default.existsSync(fullPath) && !fs_extra_1.default.lstatSync(fullPath).isDirectory(); }); } function changeNodeSource(node, filePath, modules) { if (!node.source) { return; } let sourcePath = node.source.value; if (sourcePath.startsWith('./') && sourcePath.lastIndexOf('/') === 1) { const resolvePath = path_1.default.resolve(filePath.substring(0, filePath.lastIndexOf('/')), sourcePath); if (isExist(resolvePath)) { return; } } if (sourcePath.startsWith('@components')) { sourcePath = sourcePath.replace('@components', '@lcap-ui/src/components'); } else if (sourcePath.startsWith('cloud-ui.vusion/src')) { sourcePath = sourcePath.replace('cloud-ui.vusion/src', '@lcap-ui/cloudui'); } else if (sourcePath.startsWith('@/')) { const srcVusion = fs_extra_1.default.existsSync('.lcap/lcap-ui/src-vusion'); sourcePath = sourcePath.replace('@', srcVusion ? '@lcap-ui/src-vusion' : '@lcap-ui/src'); } else if (sourcePath.startsWith('../') || sourcePath.startsWith('./')) { const lastFolderPath = filePath.substring(0, filePath.lastIndexOf('/')); sourcePath = (0, vite_1.normalizePath)(path_1.default.resolve(lastFolderPath, sourcePath).replace(path_1.default.resolve(process.cwd(), constants_1.LCAP_UI_PACKAGE_PATH), '@lcap-ui')); } else if (modules.indexOf(sourcePath) === -1) { modules.push(sourcePath); } node.source.value = sourcePath; } function transformScriptAst(ast, filePath, modules) { let isJSX = false; (0, traverse_1.default)(ast, { JSXElement(p) { isJSX = true; p.skip(); }, ExportNamedDeclaration(p) { changeNodeSource(p.node, filePath, modules); }, ExportAllDeclaration(p) { changeNodeSource(p.node, filePath, modules); }, ImportDeclaration(p) { changeNodeSource(p.node, filePath, modules); }, }); return { isJSX, }; } function transformCssCode(code, filePath) { const codes = code.split('\n').map((str) => { if (!str || !str.trim().startsWith('@import') || !str.trim().endsWith(';')) { return str; } let startIndex = str.indexOf("'") + 1; let endIndex = str.lastIndexOf("'"); if (startIndex === 0) { startIndex = str.indexOf('"') + 1; endIndex = str.lastIndexOf('"'); } if (startIndex === 0 || startIndex === endIndex) { return str; } const prefixStr = str.substring(0, startIndex); const suffixStr = str.substring(endIndex); let sourcePath = str.substring(startIndex, endIndex); if (sourcePath.startsWith('./') && sourcePath.lastIndexOf('/') === 1) { return str; } if (sourcePath.startsWith('../') || sourcePath.startsWith('./')) { const lastFolderPath = filePath.substring(0, filePath.lastIndexOf('/')); sourcePath = (0, vite_1.normalizePath)(path_1.default.resolve(lastFolderPath, sourcePath).replace(path_1.default.resolve(process.cwd(), constants_1.LCAP_UI_PACKAGE_PATH), '@lcap-ui')); prefixStr.replace('url(', ''); suffixStr.replace(')', ''); } return [prefixStr, sourcePath, suffixStr].join(''); }); return codes.join('\n'); } function saveScriptFile(filePath, context, modules) { const code = fs_extra_1.default.readFileSync(filePath).toString(); const ast = parser.parse(code, { sourceType: 'module', plugins: ['typescript', 'jsx'], }); const ext = path_1.default.extname(filePath); const basename = path_1.default.basename(filePath, ext); const { isJSX } = transformScriptAst(ast, filePath, modules); let resultPath = path_1.default.resolve(context.componentFolderPath, `${basename}${ext}`); // js 转 jsx if (isJSX && !ext.endsWith('sx')) { resultPath = path_1.default.resolve(context.componentFolderPath, `${basename}${ext}x`); } fs_extra_1.default.writeFileSync(resultPath, (0, generator_1.default)(ast, {}).code); } function parseVueFile(code) { const result = { scriptTag: '', styleTag: '', templateCodes: [], scriptCodes: [], styleCodes: [], }; let currentScope = ''; code.split('\n').forEach((line) => { if (line.trim().startsWith('<template') && currentScope !== 'template' && result.templateCodes.length === 0) { currentScope = 'template'; result.templateCodes.push(line); return; } if (line.trim().startsWith('<style') && !result.styleTag) { currentScope = 'style'; result.styleTag = line; return; } if (line.trim().startsWith('<script') && !result.scriptTag) { currentScope = 'script'; result.scriptTag = line; return; } if (line.trim().startsWith('</style>') || line.trim().startsWith('</script>')) { currentScope = ''; return; } switch (currentScope) { case 'template': result.templateCodes.push(line); break; case 'script': result.scriptCodes.push(line); break; case 'style': result.styleCodes.push(line); break; default: break; } }); return result; } function saveVueFile(filePath, context, modules) { const code = fs_extra_1.default.readFileSync(filePath).toString(); const result = parseVueFile(code); let scriptCode = ''; if (result.scriptCodes.length > 0) { const ast = parser.parse(result.scriptCodes.join('\n'), { sourceType: 'module', plugins: ['typescript', 'jsx'], }); transformScriptAst(ast, filePath, modules); scriptCode = (0, generator_1.default)(ast).code; } const resultCodes = []; if (result.templateCodes.length > 0) { resultCodes.push(...result.templateCodes); } if (result.scriptTag) { resultCodes.push(result.scriptTag, scriptCode, '</script>'); } if (result.styleTag) { resultCodes.push(result.styleTag, transformCssCode(result.styleCodes.join('\n'), filePath), result.styleTag.trim().endsWith('</style>') ? '' : '</style>'); } const basename = path_1.default.basename(filePath); const resultPath = path_1.default.resolve(context.componentFolderPath, basename); fs_extra_1.default.writeFileSync(resultPath, resultCodes.join('\n')); } function saveCssFile(filePath, context) { const basename = path_1.default.basename(filePath); const resultPath = path_1.default.resolve(context.componentFolderPath, basename); const code = fs_extra_1.default.readFileSync(filePath, 'utf-8').toString(); fs_extra_1.default.writeFileSync(resultPath, transformCssCode(code, filePath), 'utf-8'); } function addDependices() { const rootPath = process.cwd(); const sourcePkg = fs_extra_1.default.readJSONSync(path_1.default.resolve(rootPath, constants_1.LCAP_UI_PACKAGE_PATH, 'package.json')); const pkgPath = path_1.default.resolve(rootPath, 'package.json'); const pkg = fs_extra_1.default.readJSONSync(pkgPath); if (!pkg.dependencies) { pkg.dependencies = {}; } let changed = false; Object.keys(sourcePkg.dependencies || {}).forEach((name) => { if (pkg.dependencies[name]) { return; } changed = true; pkg.dependencies[name] = sourcePkg.dependencies[name]; }); if (changed) { fs_extra_1.default.writeJSONSync(pkgPath, pkg, { spaces: 2 }); } } function addSubExports(context) { const indexPath = (0, fs_1.getPath)(path_1.default.resolve(context.componentFolderPath, './index')); const needExportNames = context.replaceNames.filter((name) => context.replaceNameMap[name] && context.replaceNameMap[name] !== context.name); if (!indexPath || needExportNames.length === 0) { return; } try { const code = fs_extra_1.default.readFileSync(indexPath, 'utf-8').toString(); const ast = parser.parse(code, { sourceType: 'module', plugins: ['typescript', 'jsx'], }); (0, traverse_1.default)(ast, { ExportSpecifier(p) { if (p.node.exported.type === 'Identifier' && needExportNames.includes(p.node.exported.name)) { // p.node.exported.name = context.replaceNameMap[p.node.exported.name]; const exportPath = p.findParent((n) => n.isExportNamedDeclaration()); // 如果存在 exportPath 且 exportPath 是 ExportNamedDeclaration 类型,则添加新的 ExportSpecifier if (exportPath && exportPath.node.type === 'ExportNamedDeclaration') { exportPath.node.specifiers.push({ type: 'ExportSpecifier', local: p.node.local, exported: Object.assign(Object.assign({}, p.node.exported), { name: context.replaceNameMap[p.node.exported.name] }), }); needExportNames.splice(needExportNames.indexOf(p.node.exported.name), 1); } } }, }); let resultCode = (0, generator_1.default)(ast).code; if (needExportNames.length > 0) { resultCode = `${resultCode}\nexport { ${needExportNames.map((name) => `${name} as ${context.replaceNameMap[name]}`).join(', ')} } from '${constants_1.LCAP_UI_PACKAGE_NAME}';\n`; } fs_extra_1.default.writeFileSync(indexPath, resultCode, 'utf-8'); } catch (e) { logger_1.default.warn(e); } } function forkComponent(context) { return __awaiter(this, void 0, void 0, function* () { if (!context.fork) { return; } addDependices(); const removeFiles = yield (0, fast_glob_1.default)('index.{jsx,js,ts,tsx,vue}', { cwd: context.componentFolderPath, absolute: true }); removeFiles.forEach((filePath) => { fs_extra_1.default.unlinkSync(filePath); }); const files = yield (0, fast_glob_1.default)('*.{vue,jsx,js,ts,tsx,css}', { cwd: context.pkgComponentFolderPath, absolute: true, ignore: ['api.ts'] }); const modules = []; files.forEach((filePath) => { const ext = path_1.default.extname(filePath); switch (ext) { case '.vue': saveVueFile(filePath, context, modules); break; case '.jsx': case '.js': case '.ts': case '.tsx': saveScriptFile(filePath, context, modules); break; case '.css': saveCssFile(filePath, context); break; default: break; } }); addSubExports(context); }); } exports.forkComponent = forkComponent;