UNPKG

@lcap/builder

Version:
229 lines (226 loc) 9.81 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 __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.generateBlockFile = void 0; /* eslint-disable quotes */ const parser = __importStar(require("@babel/parser")); const traverse_1 = __importDefault(require("@babel/traverse")); const generator_1 = __importDefault(require("@babel/generator")); const fast_glob_1 = __importDefault(require("fast-glob")); const fs_extra_1 = __importDefault(require("fs-extra")); const path_1 = __importDefault(require("path")); const utils_1 = require("./utils"); const constants_1 = require("./constants"); function getBlockCodeFromData(context) { let blocks = [{ code: `<${context.tagName}></${context.tagName}>`, title: '基本用法', }]; if (context.naslUIConfig.blocks && context.naslUIConfig.blocks.length > 0) { blocks = [...context.naslUIConfig.blocks]; } const blockCodes = blocks.map((block, i) => { let code = (0, utils_1.replaceTagName)(block.code, context.naslUIConfig.kebabName, context.tagName).trim(); if (code.startsWith('<template>') && code.endsWith('</template>')) { code = code.substring('<template>'.length, code.length - '</template>'.length).trim(); } return [ `export const Block${i + 1} = {`, ` name: '${block.title || '基本用法'}',`, ' render: () => ({', ` template: \`${code}\`,`, ' }),', '};', ].join('\n'); }); return `import Component from '../index'; export default { id: '${context.tagName}-blocks', title: '组件列表/${context.name}/内置区块', component: Component, parameters: { // Optional parameter to center the component in the Canvas. More info: https://storybook.js.org/docs/configure/story-layout layout: 'centered', }, }; ${blockCodes.join('\n\n')} `; } function getBlockInfos(code, context) { const ast = parser.parse(code, { sourceType: 'module', plugins: ['typescript', 'jsx'], }); const blocks = []; const waitImports = []; (0, traverse_1.default)(ast, { VariableDeclarator(bpath) { const hasExporedName = bpath.findParent((p) => p.type === 'ExportNamedDeclaration'); if (!hasExporedName || !bpath.node.id || !bpath.node.init || bpath.node.id.type !== 'Identifier' || bpath.node.init.type !== 'ObjectExpression' || !bpath.node.init.properties || bpath.node.init.properties.length === 0) { return; } const block = { name: bpath.node.id.name, ast: null, }; bpath.traverse({ ObjectProperty: (p) => { if (p.node.key && p.node.key.type === 'Identifier' && p.node.key.name === 'name' && p.node.value && p.node.value.type === 'StringLiteral') { block.name = p.node.value.value; p.skip(); } }, JSXElement: (p) => { const inRenderProps = p.findParent((parentPath) => parentPath.type === 'ObjectProperty' && parentPath.node.key && parentPath.node.key.name === 'render'); if (inRenderProps && ['ReturnStatement', 'ArrowFunctionExpression'].indexOf(p.parent.type) === -1) { return; } block.ast = p.node; p.skip(); }, }); blocks.push(block); }, JSXElement(pt) { if (pt.node.openingElement.name.type !== 'JSXIdentifier') { return; } const tagName = pt.node.openingElement.name.name; if (tagName === context.naslUIConfig.name) { pt.node.openingElement.name.name = context.tagName; if (pt.node.closingElement && pt.node.closingElement.name.type === 'JSXIdentifier') { pt.node.closingElement.name.name = context.tagName; } } else if (waitImports.indexOf(tagName) === -1 && context.findNaslUIConfig(tagName)) { waitImports.push(tagName); } }, }); return { blocks, waitImports, }; } function getBlockCodeFromFile(filePath, context) { const tsCode = fs_extra_1.default.readFileSync(filePath, 'utf-8'); const { blocks, waitImports } = getBlockInfos(tsCode, context); const BASE_STORIES_CODE = [ `import React from 'react';${waitImports.length > 0 ? `\nimport { ${waitImports.join(', ')} } from '${constants_1.LCAP_UI_PACKAGE_NAME}';` : ''}`, `import ${context.name} from '../index';`, `export default {`, ` id: '${context.name}-Blocks',`, ` title: '组件列表/${context.name}/内置区块',`, ` component: ${context.name},`, ` parameters: {`, ` layout: 'centered',`, ` },`, `};`, '', ].join('\n'); const baseAST = parser.parse(BASE_STORIES_CODE, { sourceType: 'module', plugins: ['typescript', 'jsx'], }); baseAST.program.body.push(...blocks.map((block, i) => { return { type: 'ExportNamedDeclaration', specifiers: [], declaration: { type: 'VariableDeclaration', kind: 'const', declarations: [{ type: 'VariableDeclarator', id: { type: 'Identifier', name: `Block${i + 1}`, }, init: { type: 'ObjectExpression', properties: [{ type: 'ObjectProperty', key: { type: 'Identifier', name: 'name', }, value: { type: 'StringLiteral', value: block.name, extra: { rawValue: block.name, raw: `'${block.name}'`, }, }, shorthand: false, computed: false, }, { type: 'ObjectProperty', key: { type: 'Identifier', name: 'render', }, value: { type: 'ArrowFunctionExpression', generator: false, async: false, params: [], body: block.ast, }, shorthand: false, computed: false, }], }, }], }, }; })); return (0, generator_1.default)(baseAST).code; } function generateBlockFile(context) { if (['vue2', 'vue3'].includes(context.framework)) { const content = getBlockCodeFromData(context); fs_extra_1.default.writeFileSync(path_1.default.resolve(context.componentFolderPath, 'stories/block.stories.js'), (0, utils_1.replaceAllTagName)(content, context.replaceTagMap), 'utf-8'); return; } const storyFilePath = fast_glob_1.default.sync('stories/block.stories.{tsx,jsx}', { cwd: context.pkgComponentFolderPath, absolute: true })[0]; if (!storyFilePath) { return; } const content = getBlockCodeFromFile(storyFilePath, context); const tsxFilePath = path_1.default.resolve(context.componentFolderPath, 'stories/block.stories.tsx'); if (fs_extra_1.default.existsSync(tsxFilePath)) { fs_extra_1.default.unlinkSync(tsxFilePath); } fs_extra_1.default.writeFileSync(path_1.default.resolve(context.componentFolderPath, 'stories/block.stories.jsx'), content, 'utf-8'); } exports.generateBlockFile = generateBlockFile;