From 6cf7c3d3371620390ecf3700ee0cbc351e902107 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=98=A5=E5=B8=8C?= Date: Wed, 1 Jul 2020 10:03:39 +0800 Subject: [PATCH] feat: rewrite demo & export plugins and utils --- packages/code-generator/demo/demo.js | 53 ++ .../code-generator/demo/sampleSchema.json | 243 ++++++ packages/code-generator/package.json | 3 +- .../code-generator/src/demo/expressionTest.ts | 22 - packages/code-generator/src/demo/main.ts | 59 -- .../code-generator/src/demo/recoreDemo.ts | 815 ------------------ .../code-generator/src/demo/recoreDemo1.ts | 165 ---- .../code-generator/src/demo/simpleDemo.ts | 243 ------ .../src/generator/ModuleBuilder.ts | 21 + .../src/generator/ProjectBuilder.ts | 4 +- packages/code-generator/src/index.ts | 59 ++ .../code-generator/src/parser/SchemaParser.ts | 13 +- .../src/plugins/common/esmodule.ts | 2 +- .../component/react/containerDataSource.ts | 2 +- .../component/react/containerInitState.ts | 2 +- .../component/react/containerInjectUtils.ts | 2 +- .../component/react/containerLifeCycle.ts | 2 +- .../component/react/containerMethod.ts | 2 +- .../src/plugins/component/react/jsx.ts | 2 +- .../component/recore/pageDataSource.ts | 8 +- .../src/plugins/component/style/css.ts | 2 +- packages/code-generator/src/types/core.ts | 19 +- packages/code-generator/src/types/schema.ts | 40 +- .../code-generator/src/utils/nodeToJSX.ts | 32 +- 24 files changed, 421 insertions(+), 1394 deletions(-) create mode 100644 packages/code-generator/demo/demo.js create mode 100644 packages/code-generator/demo/sampleSchema.json delete mode 100644 packages/code-generator/src/demo/expressionTest.ts delete mode 100644 packages/code-generator/src/demo/main.ts delete mode 100644 packages/code-generator/src/demo/recoreDemo.ts delete mode 100644 packages/code-generator/src/demo/recoreDemo1.ts delete mode 100644 packages/code-generator/src/demo/simpleDemo.ts diff --git a/packages/code-generator/demo/demo.js b/packages/code-generator/demo/demo.js new file mode 100644 index 000000000..91e145de9 --- /dev/null +++ b/packages/code-generator/demo/demo.js @@ -0,0 +1,53 @@ +const fs = require('fs'); +const CodeGenerator = require('../lib').default; + +function flatFiles(rootName, dir) { + const dirRoot = rootName ? `${rootName}/${dir.name}` : dir.name; + const files = dir.files.map(file => ({ + name: `${dirRoot}/${file.name}.${file.ext}`, + content: file.content, + ext: '', + })); + const filesInSub = dir.dirs.map(subDir => flatFiles(`${dirRoot}`, subDir)); + const result = files.concat.apply(files, filesInSub); + + return result; +} + +function displayResultInConsole(root, fileName) { + const files = flatFiles('.', root); + files.forEach(file => { + if (!fileName || fileName === file.name) { + console.log(`========== ${file.name} Start ==========`); + console.log(file.content); + console.log(`========== ${file.name} End ==========`); + } + }); +} + +async function writeResultToDisk(root, path) { + const publisher = CodeGenerator.publishers.disk(); + + return publisher.publish({ + project: root, + outputPath: path, + projectSlug: 'demo-project', + createProjectFolder: true, + }); +} + +function main() { + const schemaJson = fs.readFileSync('./demo/sampleSchema.json', { encoding: 'utf8' }); + const createIceJsProjectBuilder = CodeGenerator.solutions.icejs; + const builder = createIceJsProjectBuilder(); + + builder.generateProject(schemaJson).then(result => { + displayResultInConsole(result); + writeResultToDisk(result, 'output/lowcodeDemo').then(response => + console.log('Write to disk: ', JSON.stringify(response)), + ); + return result; + }); +} + +main(); diff --git a/packages/code-generator/demo/sampleSchema.json b/packages/code-generator/demo/sampleSchema.json new file mode 100644 index 000000000..079289fac --- /dev/null +++ b/packages/code-generator/demo/sampleSchema.json @@ -0,0 +1,243 @@ +{ + "version": "1.0.0", + "componentsMap": [ + { + "componentName": "Button", + "package": "@alifd/next", + "version": "1.19.18", + "destructuring": true, + "exportName": "Button" + }, + { + "componentName": "Button.Group", + "package": "@alifd/next", + "version": "1.19.18", + "destructuring": true, + "exportName": "Button", + "subName": "Group" + }, + { + "componentName": "Input", + "package": "@alifd/next", + "version": "1.19.18", + "destructuring": true, + "exportName": "Input" + }, + { + "componentName": "Form", + "package": "@alifd/next", + "version": "1.19.18", + "destructuring": true, + "exportName": "Form" + }, + { + "componentName": "Form.Item", + "package": "@alifd/next", + "version": "1.19.18", + "destructuring": true, + "exportName": "Form", + "subName": "Item" + }, + { + "componentName": "NumberPicker", + "package": "@alifd/next", + "version": "1.19.18", + "destructuring": true, + "exportName": "NumberPicker" + }, + { + "componentName": "Select", + "package": "@alifd/next", + "version": "1.19.18", + "destructuring": true, + "exportName": "Select" + } + ], + "componentsTree": [ + { + "componentName": "Page", + "id": "node$1", + "meta": { + "title": "测试", + "router": "/" + }, + "props": { + "ref": "outterView", + "autoLoading": true + }, + "fileName": "test", + "state": { + "text": "outter" + }, + "lifeCycles": { + "componentDidMount": { + "type": "JSExpression", + "value": "function() { this.utils.request(this.props.url); }" + } + }, + "children": [ + { + "componentName": "Form", + "id": "node$2", + "props": { + "labelCol": { + "type": "JSExpression", + "value": "this.state.colNum" + }, + "style": {}, + "ref": "testForm" + }, + "children": [ + { + "componentName": "Form.Item", + "id": "node$3", + "props": { + "label": "姓名:", + "name": "name", + "initValue": "李雷" + }, + "children": [ + { + "componentName": "Input", + "id": "node$4", + "props": { + "placeholder": "请输入", + "size": "medium", + "style": { + "width": 320 + } + } + } + ] + }, + { + "componentName": "Form.Item", + "id": "node$5", + "props": { + "label": "年龄:", + "name": "age", + "initValue": "22" + }, + "children": [ + { + "componentName": "NumberPicker", + "id": "node$6", + "props": { + "size": "medium", + "type": "normal" + } + } + ] + }, + { + "componentName": "Form.Item", + "id": "node$7", + "props": { + "label": "职业:", + "name": "profession" + }, + "children": [ + { + "componentName": "Select", + "id": "node$8", + "props": { + "dataSource": [ + { + "label": "教师", + "value": "t" + }, + { + "label": "医生", + "value": "d" + }, + { + "label": "歌手", + "value": "s" + } + ] + } + } + ] + }, + { + "componentName": "Div", + "id": "node$9", + "props": { + "style": { + "textAlign": "center" + } + }, + "children": [ + { + "componentName": "Button.Group", + "id": "node$a", + "props": {}, + "children": [ + { + "componentName": "Button", + "id": "node$b", + "props": { + "type": "primary", + "style": { + "margin": "0 5px 0 5px" + }, + "htmlType": "submit" + }, + "children": [ + "提交" + ] + }, + { + "componentName": "Button", + "id": "node$d", + "props": { + "type": "normal", + "style": { + "margin": "0 5px 0 5px" + }, + "htmlType": "reset" + }, + "children": [ + "重置" + ] + } + ] + } + ] + } + ] + } + ] + } + ], + "constants": { + "ENV": "prod", + "DOMAIN": "xxx.alibaba-inc.com" + }, + "css": "body {font-size: 12px;} .table { width: 100px;}", + "config": { + "sdkVersion": "1.0.3", + "historyMode": "hash", + "targetRootID": "J_Container", + "layout": { + "componentName": "BasicLayout", + "props": { + "logo": "...", + "name": "测试网站" + } + }, + "theme": { + "package": "@alife/theme-fusion", + "version": "^0.1.0", + "primary": "#ff9966" + } + }, + "meta": { + "name": "demo应用", + "git_group": "appGroup", + "project_name": "app_demo", + "description": "这是一个测试应用", + "spma": "spa23d", + "creator": "月飞" + } +} diff --git a/packages/code-generator/package.json b/packages/code-generator/package.json index 808cf1ced..b450e4de6 100644 --- a/packages/code-generator/package.json +++ b/packages/code-generator/package.json @@ -8,8 +8,7 @@ ], "scripts": { "build": "rimraf lib && tsc", - "demo": "ts-node -r tsconfig-paths/register ./src/demo/main.ts", - "demo:exp": "ts-node -r tsconfig-paths/register ./src/demo/expressionTest.ts", + "demo": "node ./demo/demo.js", "test": "ava", "template": "node ./tools/createTemplate.js" }, diff --git a/packages/code-generator/src/demo/expressionTest.ts b/packages/code-generator/src/demo/expressionTest.ts deleted file mode 100644 index e6d8831ad..000000000 --- a/packages/code-generator/src/demo/expressionTest.ts +++ /dev/null @@ -1,22 +0,0 @@ -import traverse from '@babel/traverse'; -import * as parser from '@babel/parser'; - -function test(functionBody: string) { - console.log(functionBody); - console.log('---->'); - try { - const parseResult = parser.parse(functionBody); - console.log(JSON.stringify(parseResult)); - traverse(parseResult, { - enter(path) { - console.log('path: ', path.type, path); - } - }); - } catch (error) { - console.log('Error'); - console.log(error.message); - } - console.log('====================='); -} - -test('function main() { state.fff = 1; }'); diff --git a/packages/code-generator/src/demo/main.ts b/packages/code-generator/src/demo/main.ts deleted file mode 100644 index a0705970b..000000000 --- a/packages/code-generator/src/demo/main.ts +++ /dev/null @@ -1,59 +0,0 @@ -import { IResultDir, IResultFile } from '../types'; - -import codeGenerator from '../index'; -import { createDiskPublisher } from '../publisher/disk'; -// import demoSchema from './simpleDemo'; -import demoSchema from './recoreDemo'; - -function flatFiles(rootName: string | null, dir: IResultDir): IResultFile[] { - const dirRoot: string = rootName ? `${rootName}/${dir.name}` : dir.name; - const files: IResultFile[] = dir.files.map(file => ({ - name: `${dirRoot}/${file.name}.${file.ext}`, - content: file.content, - ext: '', - })); - const filesInSub = dir.dirs.map(subDir => flatFiles(`${dirRoot}`, subDir)); - const result: IResultFile[] = files.concat.apply(files, filesInSub); - - return result; -} - -function displayResultInConsole(root: IResultDir, fileName?: string): void { - const files = flatFiles('.', root); - files.forEach(file => { - if (!fileName || fileName === file.name) { - console.log(`========== ${file.name} Start ==========`); - console.log(file.content); - console.log(`========== ${file.name} End ==========`); - } - }); -} - -async function writeResultToDisk(root: IResultDir, path: string): Promise { - const publisher = createDiskPublisher(); - - return publisher.publish({ - project: root, - outputPath: path, - projectSlug: 'demo-project', - createProjectFolder: true, - }); -} - -function main() { - // const createIceJsProjectBuilder = codeGenerator.solutions.icejs; - // const builder = createIceJsProjectBuilder(); - - const createRecoreProjectBuilder = codeGenerator.solutions.recore; - const builder = createRecoreProjectBuilder(); - - builder.generateProject(demoSchema).then(result => { - displayResultInConsole(result); - // writeResultToDisk(result, '/Users/armslave/lowcodeDemo').then(response => - // console.log('Write to disk: ', JSON.stringify(response)), - // ); - return result; - }); -} - -main(); diff --git a/packages/code-generator/src/demo/recoreDemo.ts b/packages/code-generator/src/demo/recoreDemo.ts deleted file mode 100644 index 29e16a12b..000000000 --- a/packages/code-generator/src/demo/recoreDemo.ts +++ /dev/null @@ -1,815 +0,0 @@ -import { IProjectSchema } from '../types'; - -const demoData: IProjectSchema = { - version: '1.0.0', - componentsMap: [ - { - componentName: 'Button', - 'package': 'alife/next', - version: '1.0.0', - destructuring: true, - exportName: 'Select', - subName: 'Button', - }, - ], - componentsTree: [ - { - condition: true, - css: 'body{background-color:#f2f3f5}', - children: [ - { - condition: true, - children: [ - { - condition: true, - children: [ - { - condition: true, - componentName: 'TextField', - id: 'node_k1nd576k', - props: { - fieldName: 'name', - hasClear: false, - autoFocus: false, - tips: { - en_US: '', - zh_CN: '', - type: 'JSExpression', - value: 'this.utils.getLocale() === \'en_US\' ? \'\' : \'\'', - extType: 'i18n', - }, - trim: false, - labelTextAlign: 'right', - placeholder: { - use: 'zh_CN', - en_US: 'please input', - zh_CN: '请输入', - type: 'JSExpression', - value: '"请输入"', - extType: 'i18n', - }, - state: '', - behavior: 'NORMAL', - value: { - use: 'zh_CN', - zh_CN: '', - type: 'JSExpression', - value: '""', - extType: 'i18n', - }, - addonBefore: { - use: 'zh_CN', - zh_CN: '', - type: 'JSExpression', - value: '""', - extType: 'i18n', - }, - validation: [ - { - type: 'required', - }, - ], - hasLimitHint: false, - cutString: false, - __style__: {}, - fieldId: 'textField_k1nd576w', - htmlType: 'input', - autoHeight: false, - labelColOffset: 0, - label: { - use: 'zh_CN', - en_US: 'TextField', - zh_CN: '活动名称', - type: 'JSExpression', - value: '"活动名称"', - extType: 'i18n', - }, - __category__: 'form', - labelColSpan: 4, - wrapperColSpan: 0, - rows: 4, - addonAfter: { - use: 'zh_CN', - zh_CN: '', - type: 'JSExpression', - value: '""', - extType: 'i18n', - }, - wrapperColOffset: 0, - size: 'medium', - labelAlign: 'top', - }, - }, - { - condition: true, - componentName: 'SelectField', - id: 'node_k1nd576l', - props: { - fieldName: 'type', - hasClear: false, - tips: { - en_US: '', - zh_CN: '', - type: 'JSExpression', - value: 'this.utils.getLocale() === \'en_US\' ? \'\' : \'\'', - extType: 'i18n', - }, - mode: 'single', - showSearch: false, - autoWidth: true, - labelTextAlign: 'right', - placeholder: { - use: 'zh_CN', - en_US: 'please select', - zh_CN: '请选择', - type: 'JSExpression', - value: '"请选择"', - extType: 'i18n', - }, - hasBorder: true, - behavior: 'NORMAL', - value: '', - validation: [ - { - type: 'required', - }, - ], - __style__: {}, - fieldId: 'select_k1nd576x', - notFoundContent: { - use: 'zh_CN', - type: 'JSExpression', - value: 'null', - extType: 'i18n', - }, - labelColOffset: 0, - label: { - use: 'zh_CN', - en_US: 'SelectField', - zh_CN: '活动类型', - type: 'JSExpression', - value: '"活动类型"', - extType: 'i18n', - }, - __category__: 'form', - labelColSpan: 4, - wrapperColSpan: 0, - wrapperColOffset: 0, - hasSelectAll: false, - hasArrow: true, - size: 'medium', - labelAlign: 'top', - filterLocal: true, - dataSource: [ - { - defaultChecked: false, - text: { - en_US: 'Option 1', - zh_CN: '虚拟', - type: 'JSExpression', - __sid__: 'param_k1nd5lrz', - value: 'this.utils.getLocale() === \'en_US\' ? \'Option 1\' : \'虚拟\'', - extType: 'i18n', - }, - __sid__: 'serial_k1nd576v', - value: '虚拟', - sid: 'opt_k1ofrjfz', - }, - { - defaultChecked: false, - text: { - en_US: 'Option 2', - zh_CN: '营销', - type: 'JSExpression', - __sid__: 'param_k1nd5ls3', - value: 'this.utils.getLocale() === \'en_US\' ? \'Option 2\' : \'营销\'', - extType: 'i18n', - }, - __sid__: 'serial_k1nd576w', - value: '营销', - sid: 'opt_k1ofrjg0', - }, - { - defaultChecked: false, - text: { - en_US: 'Option 3', - zh_CN: '线下', - type: 'JSExpression', - __sid__: 'param_k1nd5ls7', - value: 'this.utils.getLocale() === \'en_US\' ? \'Option 3\' : \'线下\'', - extType: 'i18n', - }, - __sid__: 'serial_k1nd576x', - value: '线下', - sid: 'opt_k1ofrjg1', - }, - ], - }, - }, - ], - componentName: 'Form', - id: 'node_k1nd576j', - props: { - size: 'medium', - labelAlign: 'top', - autoValidate: true, - scrollToFirstError: true, - autoUnmount: true, - behavior: 'NORMAL', - dataSource: { - type: 'JSExpression', - value: 'state.formData', - extType: 'variable', - }, - __style__: {}, - fieldId: 'form', - }, - }, - ], - componentName: 'Dialog', - id: 'node_k1nd576i', - props: { - hasMask: true, - closeable: 'esc', - visible: false, - footer: true, - footerActions: 'ok,cancel', - footerAlign: 'right', - title: { - rawValue: { - use: 'zh_CN', - zh_CN: '新增活动', - type: 'JSExpression', - value: '"新增活动"', - extType: 'i18n', - }, - type: 'JSExpression', - value: '(state.formData ? \'编辑\' : \'新增\') + \'活动\'', - extType: 'variable', - }, - fieldId: 'dialog', - onOk: { - rawType: 'events', - type: 'JSExpression', - value: 'this.utils.legaoBuiltin.execEventFlow.bind(this, [this.submit])', - events: [ - { - name: 'submit', - id: 'submit', - params: {}, - type: 'actionRef', - uuid: '1570937968144_0', - }, - ], - }, - }, - }, - { - condition: true, - children: [ - { - condition: true, - children: [], - componentName: 'PageHeader', - id: 'node_k1nd576c', - props: { - __slot__title: true, - extraContent: '', - __slot__extraContent: false, - __slot__action: false, - title: { - type: 'JSBlock', - value: { - condition: true, - children: [ - { - condition: true, - componentName: 'Text', - id: 'node_k1nd576e', - props: { - showTitle: false, - behavior: 'NORMAL', - content: { - use: 'zh_CN', - en_US: 'Title', - zh_CN: '基础表格', - type: 'JSExpression', - value: '"基础表格"', - extType: 'i18n', - }, - __style__: {}, - fieldId: 'text_k1nd576t', - }, - }, - ], - componentName: 'Slot', - id: 'node_k1nd576d', - props: { - slotName: 'title', - slotTitle: '标题区域', - }, - }, - }, - content: '', - __slot__logo: false, - __slot__crumb: false, - crumb: '', - tab: '', - logo: '', - action: '', - __slot__tab: false, - __style__: {}, - __slot__content: false, - fieldId: 'pageHeader_k1nd576s', - }, - }, - ], - componentName: 'RootHeader', - id: 'node_k1hjb043', - props: {}, - }, - { - condition: true, - children: [ - { - condition: true, - componentName: 'TablePc', - id: 'node_k1hjb046', - props: { - actionWidth: 0, - isTree: false, - showJump: true, - data: { - rawValue: { - data: [ - { - contractDate: { - start: 1534942658570, - end: 1534944858570, - }, - entryDate: 1534942658570, - name: '小王', - id: '1', - salary: 35000, - email: 'xw@abc.com', - moneyRange: { - lower: 108, - upper: 944, - }, - }, - { - contractDate: { - start: 1534942658570, - end: 1534944858570, - }, - entryDate: 1534942658570, - name: '小李', - id: '2', - salary: 25000, - email: 'xl@abc.com', - moneyRange: { - lower: 214, - upper: 1077, - }, - }, - ], - currentPage: 1, - totalCount: 2, - }, - type: 'JSExpression', - value: 'state.table_list_basic', - extType: 'variable', - }, - actionTitle: { - use: 'zh_CN', - en_US: 'Action', - zh_CN: '操作', - type: 'JSExpression', - value: '"操作"', - extType: 'i18n', - }, - indent: 16, - columns: [ - { - dataKey: 'name', - hidden: false, - dataType: 'text', - width: '300px', - lock: 'none', - sortable: false, - align: 'left', - title: { - en_US: 'Name', - use: 'zh_CN', - zh_CN: '活动名称', - type: 'JSExpression', - value: '"活动名称"', - extType: 'i18n', - }, - timeFormatter: 'YYYY-MM-DD HH:mm:ss', - }, - { - dataKey: 'type', - hidden: false, - dataType: 'text', - width: '150px', - lock: 'none', - sortable: false, - align: 'left', - title: { - en_US: 'Date', - use: 'zh_CN', - zh_CN: '活动类型', - type: 'JSExpression', - value: '"活动类型"', - extType: 'i18n', - }, - timeFormatter: 'YYYY-MM-DD', - }, - { - dataKey: 'created_at', - hidden: false, - dataType: 'timestamp', - width: 200, - lock: 'none', - sortable: false, - align: 'left', - title: { - en_US: 'contractDate', - use: 'zh_CN', - zh_CN: '创建时间', - type: 'JSExpression', - value: '"创建时间"', - extType: 'i18n', - }, - timeFormatter: 'YYYY-MM-DD', - }, - ], - rowSelector: 'checkboxSelector', - pageSizeSelector: false, - pageSize: 10, - setLoadingComponent: false, - showRowSelector: false, - showLinkBar: true, - searchBarPlaceholder: { - use: 'zh_CN', - en_US: 'Please Input', - zh_CN: '请搜索', - type: 'JSExpression', - value: '"请搜索"', - extType: 'i18n', - }, - type: 'normal', - pageSizePosition: 'end', - pageSizeList: '5,10,20', - fixedHeader: false, - showActionBar: true, - showSearch: true, - stickyHeader: false, - theme: 'split', - setEmptyContent: false, - actionFixed: 'none', - fieldId: 'tablePc_k1hjb4dl', - isPagination: true, - actionColumn: [ - { - pageMode: '', - callback: { - type: 'JSExpression', - value: 'edit.bind(this)', - }, - title: { - en_US: 'Detail', - use: 'zh_CN', - zh_CN: '编辑', - type: 'JSExpression', - value: '"编辑"', - extType: 'i18n', - }, - option: 'callback', - }, - { - pageMode: '', - callback: { - type: 'JSExpression', - value: 'del.bind(this)', - }, - title: { - use: 'zh_CN', - en_US: 'action', - zh_CN: '删除', - type: 'JSExpression', - value: '"删除"', - extType: 'i18n', - }, - option: 'callback', - }, - ], - hasHeader: true, - hideOnlyOnePage: false, - shape: 'arrow-only', - paginationPosition: 'right', - actionBar: [ - { - callback: { - type: 'JSExpression', - value: 'add.bind(this)', - }, - title: { - en_US: 'Action 1', - use: 'zh_CN', - zh_CN: '新增', - type: 'JSExpression', - value: '"新增"', - extType: 'i18n', - }, - option: 'callback', - }, - ], - actionType: 'link', - __router: { - type: 'JSExpression', - value: 'this.utils.router', - }, - linkBar: [], - size: 'medium', - onLoadData: { - rawType: 'events', - type: 'JSExpression', - value: 'this.utils.legaoBuiltin.execEventFlow.bind(this, [this.onLoadData])', - events: [ - { - name: 'onLoadData', - id: 'onLoadData', - params: {}, - type: 'actionRef', - uuid: '1570938442689_4', - }, - ], - }, - actionHidden: false, - dataSourceType: 'data', - primaryKey: 'id', - }, - }, - ], - componentName: 'RootContent', - id: 'node_k1hjb044', - props: { - contentBgColor: 'white', - contentPadding: '20', - }, - }, - { - condition: true, - children: [], - componentName: 'RootFooter', - id: 'node_k1hjb045', - props: {}, - }, - ], - methods: { - __initMethods__: { - type: 'JSExpression', - value: 'function (exports, module) { \'use strict\';\n\nexports.__esModule = true;\nexports.hellGlobal = hellGlobal;\n/**\n* 全局函数,可以被应用内所有页面调用\n*/\nfunction hellGlobal() {\n console.log(\'hello, global\');\n}\'use strict\';\n\nexports.__esModule = true;\nexports.add = add;\nexports.submit = submit;\nexports.onLoadData = onLoadData;\nexports.edit = edit;\nexports.del = del;\n// 点击新增\nfunction add() {\n this.state.formData = null;\n this.$(\'dialog\').show();\n}\n\n/**\n* 点击弹框的“确认”\n*/\nfunction submit() {\n const _this = this;\n\n this.$(\'form\').submit(function (data, error) {\n if (data) {\n _this.dataSourceMap[\'table_submit\'].load(data).then(function (res) {\n _this.utils.toast({\n type: \'success\',\n title: \'提交成功\'\n });\n _this.$(\'dialog\').hide();\n _this.dataSourceMap[\'table_list_basic\'].load();\n });\n }\n });\n}\n\n/**\n* tablePc onLoadData\n* @param currentPage 当前页码\n* @param pageSize 每页显示条数\n* @param searchKey 搜索关键字\n* @param orderColumn 排序列\n* @param orderType 排序方式(desc,asc)\n* @param from 触发来源(order,search,pagination)\n*/\nfunction onLoadData(currentPage, pageSize, searchKey, orderColumn, orderType, from) {\n const tableParams = {\n currentPage: from === \'search\' ? 1 : currentPage,\n pageSize: pageSize,\n searchKey: searchKey,\n orderColumn: orderColumn,\n orderType: orderType\n };\n this.setState({ tableParams: tableParams });\n}\n\n// 点击编辑\nfunction edit(rowData) {\n this.state.formData = rowData;\n this.$(\'dialog\').show();\n}\n\n// 点击删除\nfunction del(rowData) {\n const _this2 = this;\n\n this.utils.dialog({\n method: \'confirm\',\n title: \'提示\',\n content: \'确认删除该条目吗?\',\n onOk: function onOk() {\n _this2.dataSourceMap[\'table_delete\'].load({ id: rowData.id }).then(function () {\n _this2.utils.toast({\n type: \'success\',\n title: \'删除成功\'\n });\n _this2.dataSourceMap[\'table_list_basic\'].load();\n });\n }\n });\n} }', - }, - }, - componentName: 'Page', - fileName: 'page_index', - meta: { - title: '首页', - router: '/', - spmb: 'abef21', - }, - id: 'node_k1hjb042', - state: { - urlParams: { - type: 'JSExpression', - value: 'this.utils.legaoBuiltin.getUrlParams()', - }, - designUrlPrefix: { - type: 'JSExpression', - value: '"https://pre-go.alibaba-inc.com/fusion_developer/0.1.0/design"', - }, - tableParams: { - type: 'JSExpression', - value: '', - }, - }, - dataSource: { - offline: [], - globalConfig: { - fit: { - type: 'JSExpression', - value: '', - extType: 'function', - }, - }, - online: [], - list: [ - { - dataHandler: { - type: 'JSExpression', - value: 'function(data, err) { this.setState({table_list_basic: data}); return data; }', - extType: 'function', - }, - requestHandler: { - type: 'JSExpression', - value: 'this.utils.legaoBuiltin.dataSourceHandler', - }, - options: { - shouldFetch: true, - method: 'GET', - params: { - rawValue: [], - type: 'JSExpression', - value: 'state.tableParams', - extType: 'variable', - }, - isSync: false, - url: 'https://mocks.alibaba-inc.com/mock/legao_template/api/activity/list.json', - }, - id: 'table_list_basic', - type: 'legao', - isInit: true, - }, - { - dataHandler: { - type: 'JSExpression', - value: 'function(data, err) { this.setState({table_submit: data}); return data; }', - extType: 'function', - }, - requestHandler: { - type: 'JSExpression', - value: 'this.utils.legaoBuiltin.dataSourceHandler', - }, - options: { - shouldFetch: true, - method: 'POST', - params: [], - isSync: false, - url: 'https://mocks.alibaba-inc.com/mock/legao_template/api/activity/update.json', - }, - id: 'table_submit', - type: 'legao', - isInit: false, - }, - { - dataHandler: { - type: 'JSExpression', - value: 'function(data, err) { this.setState({table_delete: data}); return data; }', - extType: 'function', - }, - requestHandler: { - type: 'JSExpression', - value: 'this.utils.legaoBuiltin.dataSourceHandler', - }, - options: { - shouldFetch: true, - method: 'POST', - params: [], - isSync: true, - url: 'https://mocks.alibaba-inc.com/mock/legao_template/api/activity/delete.json', - }, - id: 'table_delete', - type: 'legao', - isInit: false, - }, - ], - sync: true, - }, - lifeCycles: { - 'init': { - type: 'JSExpression', - value: 'function constructor() {\nconst module = { exports: {} };\nconst _this = this;\nthis.__initMethods__(module.exports, module);\nObject.keys(module.exports).forEach(function(item) {\n if(typeof module.exports[item] === \'function\'){\n _this[item] = module.exports[item];\n }\n});\n\n}', - extType: 'function', - }, - didMount: { - type: 'JSExpression', - value: 'function main(){\n \'use strict\';\n\nconst __compiledFunc__ = function didMount() {\n // 页面节点加载渲染完毕\n console.log(\'这是个 function didMount\', this);\n};\n return __compiledFunc__.apply(this, arguments);\n}', - extType: 'function', - }, - }, - props: { - extensions: { - '启用页头': true, - }, - pageStyle: { - backgroundColor: '#f2f3f5', - }, - containerStyle: {}, - className: 'page_k1v3nkx7', - }, - }, - ], - utils: [ - { - name: 'clone', - type: 'npm', - content: { - 'package': 'lodash', - version: '0.0.1', - exportName: 'clone', - subName: '', - destructuring: false, - main: '/lib/clone', - }, - }, - { - name: 'beforeRequestHandler', - type: 'function', - content: { - type: 'JSExpression', - value: 'function(){\n ... \n}', - }, - }, - ], - constants: { - ENV: 'prod', - DOMAIN: 'xxx.alibaba-inc.com', - }, - css: 'body {font-size: 12px;} .table { width: 100px;}', - config: { - sdkVersion: '1.0.3', - historyMode: 'hash', - targetRootID: 'J_Container', - layout: { - componentName: 'BasicLayout', - props: { - navConfig: { - showLanguageChange: true, - data: [ - { - hidden: false, - navUuid: 'FORM-CP5669B1-3AW9DCLHZAY8EIY6WE6X1-GFZM3V1K-6', - children: [], - icon: '', - targetNew: false, - title: '测试基础表格', - inner: true, - relateUuid: 'FORM-CP5669B1-3AW9DCLHZAY8EIY6WE6X1-GFZM3V1K-6', - slug: 'qihfg', - }, - { - hidden: false, - navUuid: 'FORM-CP5669B1-8AW9XCUT4PCH15SMDWUM3-ZPQP3V1K-1', - children: [], - icon: '', - targetNew: false, - title: '测试查询表格', - inner: true, - relateUuid: 'zqhej', - slug: 'zqhej', - }, - ], - systemLink: '/my_dev_center_code/0.1.0', - appName: '乐高转码测试', - isFoldHorizontal: 'n', - showAppTitle: true, - isFold: 'n', - searchBarType: 'icon', - singletons: {}, - navTheme: 'default', - type: 'top_side_fold', - navStyle: 'orange', - layout: 'auto', - bgColor: 'white', - languageChangeUrl: '/common/account/changeAccountLanguage.json', - showSearch: 'n', - openSubMode: false, - showCrumb: true, - isFixed: 'y', - showIcon: false, - showNav: true, - }, - }, - }, - theme: { - 'package': '@alife/theme-fusion', - version: '^0.1.0', - primary: '#ff9966', - }, - }, - meta: { - name: 'demo应用', - git_group: 'appGroup', - project_name: 'app_demo', - description: '这是一个测试应用', - spma: 'spa23d', - creator: '月飞', - gmt_create: '2020-02-11 00:00:00', - gmt_modified: '2020-02-11 00:00:00', - }, - i18n: { - 'zh-CN': { - 'i18n-jwg27yo4': '你好', - 'i18n-jwg27yo3': '中国', - }, - 'en-US': { - 'i18n-jwg27yo4': 'Hello', - 'i18n-jwg27yo3': 'China', - }, - }, -}; - -export default demoData; diff --git a/packages/code-generator/src/demo/recoreDemo1.ts b/packages/code-generator/src/demo/recoreDemo1.ts deleted file mode 100644 index 1ef52bc0a..000000000 --- a/packages/code-generator/src/demo/recoreDemo1.ts +++ /dev/null @@ -1,165 +0,0 @@ -import { IProjectSchema } from '../types'; - -const demoData: IProjectSchema = { - version: '1.0.0', - componentsMap: [ - { - componentName: 'Button', - 'package': 'alife/next', - version: '1.0.0', - destructuring: true, - exportName: 'Select', - subName: 'Button', - }, - ], - componentsTree: [{ - componentName: 'Page', - id: 'node$1', - props: { - ref: 'outterView', - autoLoading: true, - style: { - padding: 20, - }, - }, - fileName: 'test', - dataSource: { - list: [], - }, - state: { - text: 'outter', - }, - children: [ - { - componentName: 'Button', - id: 'node$l', - props: {}, - }, - { - componentName: 'Button', - id: 'node$n', - props: { - type: 'secondary', - baseIcon: 'set', - }, - }, - { - componentName: 'Calendar', - id: 'node$p', - props: { - shape: 'card', - }, - }, - ], - }], - utils: [ - { - name: 'clone', - type: 'npm', - content: { - 'package': 'lodash', - version: '0.0.1', - exportName: 'clone', - subName: '', - destructuring: false, - main: '/lib/clone', - }, - }, - { - name: 'beforeRequestHandler', - type: 'function', - content: { - type: 'JSExpression', - value: 'function(){\n ... \n}', - }, - }, - ], - constants: { - ENV: 'prod', - DOMAIN: 'xxx.alibaba-inc.com', - }, - css: 'body {font-size: 12px;} .table { width: 100px;}', - config: { - sdkVersion: '1.0.3', - historyMode: 'hash', - targetRootID: 'J_Container', - layout: { - componentName: 'BasicLayout', - props: { - navConfig: { - showLanguageChange: true, - data: [ - { - hidden: false, - navUuid: 'FORM-CP5669B1-3AW9DCLHZAY8EIY6WE6X1-GFZM3V1K-6', - children: [], - icon: '', - targetNew: false, - title: '测试基础表格', - inner: true, - relateUuid: 'FORM-CP5669B1-3AW9DCLHZAY8EIY6WE6X1-GFZM3V1K-6', - slug: 'qihfg', - }, - { - hidden: false, - navUuid: 'FORM-CP5669B1-8AW9XCUT4PCH15SMDWUM3-ZPQP3V1K-1', - children: [], - icon: '', - targetNew: false, - title: '测试查询表格', - inner: true, - relateUuid: 'zqhej', - slug: 'zqhej', - }, - ], - systemLink: '/my_dev_center_code/0.1.0', - appName: '乐高转码测试', - isFoldHorizontal: 'n', - showAppTitle: true, - isFold: 'n', - searchBarType: 'icon', - singletons: {}, - navTheme: 'default', - type: 'top_side_fold', - navStyle: 'orange', - layout: 'auto', - bgColor: 'white', - languageChangeUrl: '/common/account/changeAccountLanguage.json', - showSearch: 'n', - openSubMode: false, - showCrumb: true, - isFixed: 'y', - showIcon: false, - showNav: true, - }, - }, - }, - theme: { - 'package': '@alife/theme-fusion', - version: '^0.1.0', - primary: '#ff9966', - }, - }, - meta: { - name: 'demo应用', - git_group: 'appGroup', - project_name: 'app_demo', - description: '这是一个测试应用', - spma: 'spa23d', - creator: '月飞', - gmt_create: '2020-02-11 00:00:00', - gmt_modified: '2020-02-11 00:00:00', - }, - i18n: { - 'zh-CN': { - 'i18n-jwg27yo4': '你好', - 'i18n-jwg27yo3': '中国', - }, - 'en-US': { - 'i18n-jwg27yo4': 'Hello', - 'i18n-jwg27yo3': 'China', - }, - }, -}; - -export default demoData; diff --git a/packages/code-generator/src/demo/simpleDemo.ts b/packages/code-generator/src/demo/simpleDemo.ts deleted file mode 100644 index 410ca35e3..000000000 --- a/packages/code-generator/src/demo/simpleDemo.ts +++ /dev/null @@ -1,243 +0,0 @@ -import { IProjectSchema } from '../types'; - -const demoData: IProjectSchema = { - version: '1.0.0', - componentsMap: [ - { - componentName: 'Button', - package: '@alifd/next', - version: '1.19.18', - destructuring: true, - exportName: 'Button', - }, - { - componentName: 'Button.Group', - package: '@alifd/next', - version: '1.19.18', - destructuring: true, - exportName: 'Button', - subName: 'Group', - }, - { - componentName: 'Input', - package: '@alifd/next', - version: '1.19.18', - destructuring: true, - exportName: 'Input', - }, - { - componentName: 'Form', - package: '@alifd/next', - version: '1.19.18', - destructuring: true, - exportName: 'Form', - }, - { - componentName: 'Form.Item', - package: '@alifd/next', - version: '1.19.18', - destructuring: true, - exportName: 'Form', - subName: 'Item', - }, - { - componentName: 'NumberPicker', - package: '@alifd/next', - version: '1.19.18', - destructuring: true, - exportName: 'NumberPicker', - }, - { - componentName: 'Select', - package: '@alifd/next', - version: '1.19.18', - destructuring: true, - exportName: 'Select', - }, - ], - componentsTree: [ - { - componentName: 'Page', - id: 'node$1', - meta: { - title: '测试', - router: '/', - }, - props: { - ref: 'outterView', - autoLoading: true, - }, - fileName: 'test', - state: { - text: 'outter', - }, - lifeCycles: { - componentDidMount: { - type: 'JSExpression', - value: 'function() { this.utils.request(this.props.url); }', - }, - }, - children: [ - { - componentName: 'Form', - id: 'node$2', - props: { - labelCol: { - type: 'JSExpression', - value: 'this.state.colNum', - }, - style: {}, - ref: 'testForm', - }, - children: [ - { - componentName: 'Form.Item', - id: 'node$3', - props: { - label: '姓名:', - name: 'name', - initValue: '李雷', - }, - children: [ - { - componentName: 'Input', - id: 'node$4', - props: { - placeholder: '请输入', - size: 'medium', - style: { - width: 320, - }, - }, - }, - ], - }, - { - componentName: 'Form.Item', - id: 'node$5', - props: { - label: '年龄:', - name: 'age', - initValue: '22', - }, - children: [ - { - componentName: 'NumberPicker', - id: 'node$6', - props: { - size: 'medium', - type: 'normal', - }, - }, - ], - }, - { - componentName: 'Form.Item', - id: 'node$7', - props: { - label: '职业:', - name: 'profession', - }, - children: [ - { - componentName: 'Select', - id: 'node$8', - props: { - dataSource: [ - { - label: '教师', - value: 't', - }, - { - label: '医生', - value: 'd', - }, - { - label: '歌手', - value: 's', - }, - ], - }, - }, - ], - }, - { - componentName: 'Div', - id: 'node$9', - props: { - style: { - textAlign: 'center', - }, - }, - children: [ - { - componentName: 'Button.Group', - id: 'node$a', - props: {}, - children: [ - { - componentName: 'Button', - id: 'node$b', - props: { - type: 'primary', - style: { - margin: '0 5px 0 5px', - }, - htmlType: 'submit', - }, - children: ['提交'], - }, - { - componentName: 'Button', - id: 'node$d', - props: { - type: 'normal', - style: { - margin: '0 5px 0 5px', - }, - htmlType: 'reset', - }, - children: ['重置'], - }, - ], - }, - ], - }, - ], - }, - ], - }, - ], - constants: { - ENV: 'prod', - DOMAIN: 'xxx.alibaba-inc.com', - }, - css: 'body {font-size: 12px;} .table { width: 100px;}', - config: { - sdkVersion: '1.0.3', - historyMode: 'hash', - targetRootID: 'J_Container', - layout: { - componentName: 'BasicLayout', - props: { - logo: '...', - name: '测试网站', - }, - }, - theme: { - package: '@alife/theme-fusion', - version: '^0.1.0', - primary: '#ff9966', - }, - }, - meta: { - name: 'demo应用', - git_group: 'appGroup', - project_name: 'app_demo', - description: '这是一个测试应用', - spma: 'spa23d', - creator: '月飞', - }, -}; - -export default demoData; diff --git a/packages/code-generator/src/generator/ModuleBuilder.ts b/packages/code-generator/src/generator/ModuleBuilder.ts index 8115f0def..991ffedec 100644 --- a/packages/code-generator/src/generator/ModuleBuilder.ts +++ b/packages/code-generator/src/generator/ModuleBuilder.ts @@ -1,18 +1,24 @@ import { BuilderComponentPlugin, CodeGeneratorError, + IBasicSchema, ICodeChunk, ICompiledModule, IModuleBuilder, + IParseResult, + IResultDir, IResultFile, + ISchemaParser, PostProcessor, } from '../types'; import { COMMON_SUB_MODULE_NAME } from '../const/generator'; +import SchemaParser from '../parser/SchemaParser'; import ChunkBuilder from './ChunkBuilder'; import CodeBuilder from './CodeBuilder'; +import ResultDir from '../model/ResultDir'; import ResultFile from '../model/ResultFile'; export function createModuleBuilder( @@ -66,6 +72,20 @@ export function createModuleBuilder( }; }; + const generateModuleCode = async (schema: IBasicSchema | string): Promise => { + // Init + const schemaParser: ISchemaParser = new SchemaParser(); + const parseResult: IParseResult = schemaParser.parse(schema); + + const containerInfo = parseResult.containers[0]; + const { files } = await generateModule(containerInfo); + + const dir = new ResultDir(containerInfo.moduleName); + files.forEach(file => dir.addFile(file)); + + return dir; + } + const linkCodeChunks = ( chunks: Record, fileName: string, @@ -88,6 +108,7 @@ export function createModuleBuilder( return { generateModule, + generateModuleCode, linkCodeChunks, addPlugin: chunkGenerator.addPlugin.bind(chunkGenerator), }; diff --git a/packages/code-generator/src/generator/ProjectBuilder.ts b/packages/code-generator/src/generator/ProjectBuilder.ts index bd36291f6..ec1c897b6 100644 --- a/packages/code-generator/src/generator/ProjectBuilder.ts +++ b/packages/code-generator/src/generator/ProjectBuilder.ts @@ -57,8 +57,8 @@ export class ProjectBuilder implements IProjectBuilder { this.postProcessors = postProcessors; } - public async generateProject(schema: IProjectSchema): Promise { - // Init working parts + public async generateProject(schema: IProjectSchema | string): Promise { + // Init const schemaParser: ISchemaParser = new SchemaParser(); const builders = this.createModuleBuilders(); const projectRoot = this.template.generateTemplate(); diff --git a/packages/code-generator/src/index.ts b/packages/code-generator/src/index.ts index 8d2433d25..9de9c1538 100644 --- a/packages/code-generator/src/index.ts +++ b/packages/code-generator/src/index.ts @@ -3,14 +3,42 @@ * */ import { createProjectBuilder } from './generator/ProjectBuilder'; +import { createModuleBuilder } from './generator/ModuleBuilder'; import { createDiskPublisher } from './publisher/disk'; import createIceJsProjectBuilder from './solutions/icejs'; import createRecoreProjectBuilder from './solutions/recore'; +// 引入说明 +import { REACT_CHUNK_NAME } from './plugins/component/react/const'; + +// 引入通用插件组 +import esmodule from './plugins/common/esmodule'; +import requireUtils from './plugins/common/requireUtils'; +import containerClass from './plugins/component/react/containerClass'; +import containerDataSource from './plugins/component/react/containerDataSource'; +import containerInitState from './plugins/component/react/containerInitState'; +import containerInjectUtils from './plugins/component/react/containerInjectUtils'; +import containerLifeCycle from './plugins/component/react/containerLifeCycle'; +import containerMethod from './plugins/component/react/containerMethod'; +import jsx from './plugins/component/react/jsx'; +import reactCommonDeps from './plugins/component/react/reactCommonDeps'; +import css from './plugins/component/style/css'; +import constants from './plugins/project/constants'; +import i18n from './plugins/project/i18n'; +import utils from './plugins/project/utils'; + +// 引入常用工具 +import * as utilsCommon from './utils/common'; +import * as utilsCompositeType from './utils/compositeType'; +import * as utilsJsExpression from './utils/jsExpression'; +import * as utilsNodeToJSX from './utils/nodeToJSX'; +import * as utilsTemplateHelper from './utils/templateHelper'; + export * from './types'; export default { createProjectBuilder, + createModuleBuilder, solutions: { icejs: createIceJsProjectBuilder, recore: createRecoreProjectBuilder, @@ -18,4 +46,35 @@ export default { publishers: { disk: createDiskPublisher, }, + plugins: { + common: { + esmodule, + requireUtils, + }, + react: { + containerClass, + containerDataSource, + containerInitState, + containerInjectUtils, + containerLifeCycle, + containerMethod, + jsx, + reactCommonDeps, + }, + style: { + css, + }, + project: { + constants, + i18n, + utils, + }, + }, + utils: { + common: utilsCommon, + compositeType: utilsCompositeType, + jsExpression: utilsJsExpression, + nodeToJSX: utilsNodeToJSX, + templateHelper: utilsTemplateHelper, + }, }; diff --git a/packages/code-generator/src/parser/SchemaParser.ts b/packages/code-generator/src/parser/SchemaParser.ts index a98309a41..d6b679ff0 100644 --- a/packages/code-generator/src/parser/SchemaParser.ts +++ b/packages/code-generator/src/parser/SchemaParser.ts @@ -46,12 +46,23 @@ class SchemaParser implements ISchemaParser { return true; } - public parse(schema: IProjectSchema): IParseResult { + public parse(schemaSrc: IProjectSchema | string): IParseResult { // TODO: collect utils depends in JSExpression const compDeps: Record = {}; const internalDeps: Record = {}; let utilsDeps: IExternalDependency[] = []; + let schema: IProjectSchema; + if (typeof schemaSrc === 'string') { + try { + schema = JSON.parse(schemaSrc); + } catch (error) { + throw new CodeGeneratorError(`Parse schema failed: ${error.message || 'unknown reason'}`); + } + } else { + schema = schemaSrc; + } + // 解析三方组件依赖 schema.componentsMap.forEach(info => { info.dependencyType = DependencyType.External; diff --git a/packages/code-generator/src/plugins/common/esmodule.ts b/packages/code-generator/src/plugins/common/esmodule.ts index 1e26706cd..316ed5821 100644 --- a/packages/code-generator/src/plugins/common/esmodule.ts +++ b/packages/code-generator/src/plugins/common/esmodule.ts @@ -123,7 +123,7 @@ function buildPackageImport( return chunks; } -interface PluginConfig { +type PluginConfig = { fileType: string; } diff --git a/packages/code-generator/src/plugins/component/react/containerDataSource.ts b/packages/code-generator/src/plugins/component/react/containerDataSource.ts index 1f6132b10..72d7efd6b 100644 --- a/packages/code-generator/src/plugins/component/react/containerDataSource.ts +++ b/packages/code-generator/src/plugins/component/react/containerDataSource.ts @@ -11,7 +11,7 @@ import { IContainerInfo, } from '../../../types'; -interface PluginConfig { +type PluginConfig = { fileType: string; } diff --git a/packages/code-generator/src/plugins/component/react/containerInitState.ts b/packages/code-generator/src/plugins/component/react/containerInitState.ts index c3ba77c2b..50984c961 100644 --- a/packages/code-generator/src/plugins/component/react/containerInitState.ts +++ b/packages/code-generator/src/plugins/component/react/containerInitState.ts @@ -11,7 +11,7 @@ import { IContainerInfo, } from '../../../types'; -interface PluginConfig { +type PluginConfig = { fileType: string; implementType: 'inConstructor' | 'insMember' | 'hooks'; } diff --git a/packages/code-generator/src/plugins/component/react/containerInjectUtils.ts b/packages/code-generator/src/plugins/component/react/containerInjectUtils.ts index bdc6dbd6d..8cded167b 100644 --- a/packages/code-generator/src/plugins/component/react/containerInjectUtils.ts +++ b/packages/code-generator/src/plugins/component/react/containerInjectUtils.ts @@ -8,7 +8,7 @@ import { ICodeStruct, } from '../../../types'; -interface PluginConfig { +type PluginConfig = { fileType: string; } diff --git a/packages/code-generator/src/plugins/component/react/containerLifeCycle.ts b/packages/code-generator/src/plugins/component/react/containerLifeCycle.ts index 08c88f968..d1951d8e2 100644 --- a/packages/code-generator/src/plugins/component/react/containerLifeCycle.ts +++ b/packages/code-generator/src/plugins/component/react/containerLifeCycle.ts @@ -18,7 +18,7 @@ import { IJSExpression, } from '../../../types'; -interface PluginConfig { +type PluginConfig = { fileType: string; exportNameMapping: Record; normalizeNameMapping: Record; diff --git a/packages/code-generator/src/plugins/component/react/containerMethod.ts b/packages/code-generator/src/plugins/component/react/containerMethod.ts index 527aad815..9bba467da 100644 --- a/packages/code-generator/src/plugins/component/react/containerMethod.ts +++ b/packages/code-generator/src/plugins/component/react/containerMethod.ts @@ -13,7 +13,7 @@ import { IJSExpression, } from '../../../types'; -interface PluginConfig { +type PluginConfig = { fileType: string; } diff --git a/packages/code-generator/src/plugins/component/react/jsx.ts b/packages/code-generator/src/plugins/component/react/jsx.ts index 2b168d259..bb6b8f383 100644 --- a/packages/code-generator/src/plugins/component/react/jsx.ts +++ b/packages/code-generator/src/plugins/component/react/jsx.ts @@ -11,7 +11,7 @@ import { REACT_CHUNK_NAME } from './const'; import { createReactNodeGenerator } from '../../../utils/nodeToJSX'; -interface PluginConfig { +type PluginConfig = { fileType: string; } diff --git a/packages/code-generator/src/plugins/component/recore/pageDataSource.ts b/packages/code-generator/src/plugins/component/recore/pageDataSource.ts index da7de385e..87d496aaf 100644 --- a/packages/code-generator/src/plugins/component/recore/pageDataSource.ts +++ b/packages/code-generator/src/plugins/component/recore/pageDataSource.ts @@ -31,25 +31,19 @@ const pluginFactory: BuilderComponentPluginFactory = () => { const { dataSource } = ir; const { list, - dataHandler, ...rest } = dataSource; let attrs: string[] = []; const extConfigs = Object.keys(rest).map(extConfigName => { - const value = rest[extConfigName] as CompositeValue; + const value = (rest as Record)[extConfigName]; const [isString, valueStr] = generateCompositeType(value); return `${extConfigName}: ${isString ? `'${valueStr}'` : valueStr}`; }); attrs = [...attrs, ...extConfigs]; - if (dataHandler) { - const handlerContent = packJsExpression(dataHandler); - attrs.push(`dataHandler: ${handlerContent}`); - } - const listProp = handleStringValueDefault(generateCompositeType(list as unknown as CompositeValue, { expression: packJsExpression, })); diff --git a/packages/code-generator/src/plugins/component/style/css.ts b/packages/code-generator/src/plugins/component/style/css.ts index cb9b2a4e0..a2e8b46f0 100644 --- a/packages/code-generator/src/plugins/component/style/css.ts +++ b/packages/code-generator/src/plugins/component/style/css.ts @@ -9,7 +9,7 @@ import { IContainerInfo, } from '../../../types'; -interface PluginConfig { +type PluginConfig = { fileType: string; moduleFileType: string; } diff --git a/packages/code-generator/src/types/core.ts b/packages/code-generator/src/types/core.ts index 5cdffaa4b..a370d5641 100644 --- a/packages/code-generator/src/types/core.ts +++ b/packages/code-generator/src/types/core.ts @@ -78,12 +78,13 @@ export interface ICompiledModule { } export interface IModuleBuilder { - generateModule: (input: unknown) => Promise; - linkCodeChunks: ( + generateModule(input: unknown): Promise; + generateModuleCode(schema: IBasicSchema | string): Promise; + linkCodeChunks( chunks: Record, fileName: string, - ) => IResultFile[]; - addPlugin: (plugin: BuilderComponentPlugin) => void; + ): IResultFile[]; + addPlugin(plugin: BuilderComponentPlugin): void; } /** @@ -105,7 +106,7 @@ export interface ICodeGenerator { export interface ISchemaParser { validate(schema: IBasicSchema): boolean; - parse(schema: IBasicSchema): IParseResult; + parse(schema: IBasicSchema | string): IParseResult; } export interface IProjectTemplate { @@ -136,7 +137,7 @@ export interface IProjectPlugins { } export interface IProjectBuilder { - generateProject(schema: IProjectSchema): Promise; + generateProject(schema: IProjectSchema | string): Promise; } export type PostProcessorFactory = (config?: T) => PostProcessor; @@ -168,3 +169,9 @@ export interface HandlerSet { } export type ExtGeneratorPlugin = (nodeItem: IComponentNodeItem) => CodePiece[]; + +// export interface InteratorScope { +// [$item: string]: string; // $item 默认取值 "item" +// [$index: string]: string | number; // $index 默认取值 "index" +// __proto__: BlockInstance; +// } diff --git a/packages/code-generator/src/types/schema.ts b/packages/code-generator/src/types/schema.ts index aa6e9459c..68226e8ab 100644 --- a/packages/code-generator/src/types/schema.ts +++ b/packages/code-generator/src/types/schema.ts @@ -88,10 +88,6 @@ export interface IUtilItem { content: IExternalDependency | IJSExpression; } -export interface IInlineStyle { - [cssAttribute: string]: string | number | IJSExpression; -} - export type ChildNodeItem = string | IJSExpression | IComponentNodeItem; export type ChildNodeType = ChildNodeItem | ChildNodeItem[]; @@ -107,9 +103,7 @@ export interface IComponentNodeItem { id?: string; componentName: string; // 组件名称 必填、首字母大写 props: { - className?: string; // 组件样式类名 - style?: IInlineStyle; // 组件内联样式 - [propName: string]: any; // 业务属性 + [propName: string]: CompositeValue; // 业务属性 }; // 组件属性对象 condition?: CompositeValue; // 渲染条件 loop?: CompositeValue; // 循环数据 @@ -127,13 +121,10 @@ export interface IComponentNodeItem { export interface IContainerNodeItem extends IComponentNodeItem { componentName: 'Page' | 'Block' | 'Component'; // 'Page' | 'Block' | 'Component' 组件类型 必填、首字母大写 fileName: string; // 文件名称 必填、英文 - defaultProps?: { - [propName: string]: any; // 业务属性 - }; state?: { - [stateName: string]: any; // 容器初始数据 + [stateName: string]: CompositeValue; // 容器初始数据 }; - css: string; // 样式文件 用于描述容器组件内部节点的样式,对应生成一个独立的样式文件,在对应容器组件生成的 .jsx 文件中 import 引入; + css?: string; // 样式文件 用于描述容器组件内部节点的样式,对应生成一个独立的样式文件,在对应容器组件生成的 .jsx 文件中 import 引入; /** * LifeCycle * • constructor(props, context) @@ -146,30 +137,13 @@ export interface IContainerNodeItem extends IComponentNodeItem { * • componentDidCatch(error, info) */ lifeCycles?: Record; // 生命周期Hook方法 - methods?: { - [methodName: string]: IJSExpression; - }; // 自定义方法设置 - dataSource?: IDataSource; // 异步数据源配置 + methods?: Record; // 自定义方法设置 + dataSource?: { + list: IDataSourceConfig[]; + }; // 异步数据源配置 meta?: IBasicMeta | IPageMeta; } -/** - * 搭建基础协议 - 数据源 - * - * @export - * @interface IDataSource - */ -export interface IDataSource { - list: IDataSourceConfig[]; // 成为为单个请求配置 - /** - * 参数:为dataMap对象,key:数据id, value: 单个请求结果 - * 返回值:数据对象data,将会在渲染引擎和schemaToCode中通过调用this.setState(...)将返回的数据对象生效到state中; - * 支持返回一个Promise,通过resolve(返回数据),常用于串型发送请求场景,配合this.dataSourceMap[oneRequest.id].load()使用; - */ - dataHandler?: IJSExpression; - [extConfigName: string]: any; -} - /** * 搭建基础协议 - 数据源单个配置 * diff --git a/packages/code-generator/src/utils/nodeToJSX.ts b/packages/code-generator/src/utils/nodeToJSX.ts index 82673f851..a60351202 100644 --- a/packages/code-generator/src/utils/nodeToJSX.ts +++ b/packages/code-generator/src/utils/nodeToJSX.ts @@ -1,7 +1,6 @@ import { ChildNodeType, IComponentNodeItem, - IInlineStyle, IJSExpression, ChildNodeItem, CodeGeneratorError, @@ -37,20 +36,6 @@ export function handleChildren( } } -export function generateInlineStyle(style: IInlineStyle): string | null { - const attrLines = Object.keys(style).map((cssAttribute: string) => { - const [isString, valueStr] = generateCompositeType(style[cssAttribute]); - const valuePart = isString ? `'${valueStr}'` : valueStr; - return `${cssAttribute}: ${valuePart},`; - }); - - if (attrLines.length === 0) { - return null; - } - - return `{ ${attrLines.join('')} }`; -} - export function generateAttr(attrName: string, attrValue: any): CodePiece[] { if (attrName === 'initValue' || attrName === 'labelCol') { return []; @@ -63,23 +48,8 @@ export function generateAttr(attrName: string, attrValue: any): CodePiece[] { } export function generateAttrs(nodeItem: IComponentNodeItem): CodePiece[] { - const { className, style, ...props } = nodeItem.props; + const { props } = nodeItem; let pieces: CodePiece[] = []; - if (className) { - pieces.push({ - value: `className="${className}"`, - type: PIECE_TYPE.ATTR, - }); - } - if (style) { - const inlineStyle = generateInlineStyle(style); - if (inlineStyle !== null) { - pieces.push({ - value: `style={${inlineStyle}}`, - type: PIECE_TYPE.ATTR, - }); - } - } Object.keys(props).forEach((propName: string) => pieces = pieces.concat(generateAttr(propName, props[propName])),