From 87dfa5d3e98d5d031a836e69ce7c7b3d998593ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=98=A5=E5=B8=8C?= Date: Mon, 27 Jul 2020 11:10:24 +0800 Subject: [PATCH 1/8] =?UTF-8?q?chore:=20=F0=9F=A4=96=20update=20demo=20dat?= =?UTF-8?q?a?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/code-generator/demo/assets.json | 480 +++++++++++++++++++++-- packages/code-generator/demo/schema.json | 474 +++++++++++++++++----- 2 files changed, 822 insertions(+), 132 deletions(-) diff --git a/packages/code-generator/demo/assets.json b/packages/code-generator/demo/assets.json index 3a9ce284a..f46fd9f22 100644 --- a/packages/code-generator/demo/assets.json +++ b/packages/code-generator/demo/assets.json @@ -25,6 +25,12 @@ { "componentName": "Page", "title": "Page", + "props": [ + { + "name": "style", + "propType": "object" + } + ], "configure": { "events": { "supportedLifecycles": [ @@ -60,6 +66,272 @@ } } }, + { + "componentName": "Table", + "title": "Table", + "docUrl": "", + "screenshot": "", + "npm": { + "package": "@alifd/next", + "version": "1.19.18", + "exportName": "Table", + "main": "src/index.js", + "destructuring": true, + "subName": "" + }, + "props": [ + { + "name": "prefix", + "propType": "string" + }, + { + "name": "pure", + "propType": "bool" + }, + { + "name": "rtl", + "propType": "bool" + }, + { + "name": "tableLayout", + "propType": { + "type": "oneOf", + "value": [ + "fixed", + "auto" + ] + } + }, + { + "name": "tableWidth", + "propType": "number" + }, + { + "name": "className", + "propType": "string" + }, + { + "name": "style", + "propType": "object" + }, + { + "name": "size", + "propType": { + "type": "oneOf", + "value": [ + "small", + "medium" + ] + } + }, + { + "name": "dataSource", + "propType": { + "type": "arrayOf", + "value": "object" + } + }, + { + "name": "entireDataSource", + "propType": "array" + }, + { + "name": "onRowClick", + "propType": "func" + }, + { + "name": "onRowMouseEnter", + "propType": "func" + }, + { + "name": "rowProps", + "propType": "func" + }, + { + "name": "cellProps", + "propType": "func" + }, + { + "name": "hasBorder", + "propType": "bool" + }, + { + "name": "hasHeader", + "propType": "bool" + }, + { + "name": "isZebra", + "propType": "bool" + }, + { + "name": "loading", + "propType": "bool" + }, + { + "name": "filterParams", + "propType": "object" + }, + { + "name": "sort", + "propType": "object" + }, + { + "name": "sortIcons", + "propType": "object" + }, + { + "name": "locale", + "propType": "object" + }, + { + "name": "components", + "propType": "object" + }, + { + "name": "columns", + "propType": "array" + }, + { + "name": "emptyContent", + "propType": "node" + }, + { + "name": "primaryKey", + "propType": "string" + }, + { + "name": "lockType", + "propType": { + "type": "oneOf", + "value": [ + "left", + "right" + ] + } + },{ + "name": "style", + "propType": "object" + }, + { + "name": "wrapperContent", + "propType": "any" + }, + { + "name": "refs", + "propType": "object" + }, + { + "name": "expandedRowRender", + "propType": "func" + }, + { + "name": "expandedRowIndent", + "propType": "array" + }, + { + "name": "hasExpandedRowCtrl", + "propType": "bool" + }, + { + "name": "getExpandedColProps", + "propType": "func" + }, + { + "name": "openRowKeys", + "propType": "array" + }, + { + "name": "onRowOpen", + "propType": "func" + }, + { + "name": "onExpandedRowClick", + "propType": "func" + }, + { + "name": "fixedHeader", + "propType": "bool" + }, + { + "name": "rowSelection", + "propType": "object" + }, + { + "name": "stickyHeader", + "propType": "bool" + }, + { + "name": "offsetTop", + "propType": "number" + }, + { + "name": "affixProps", + "propType": "object" + }, + { + "name": "indent", + "propType": "number" + }, + { + "name": "isTree", + "propType": "bool" + }, + { + "name": "useVirtual", + "propType": "bool" + }, + { + "name": "onBodyScroll", + "propType": "func" + }, + { + "name": "expandedIndexSimulate", + "propType": "bool" + }, + { + "name": "crossline", + "propType": "bool" + }, + { + "name": "lengths", + "propType": "object" + } + ], + "configure": { + "component": { + "isContainer": true + }, + "props": { + "isExtends": true, + "override": [{ + "name": "dataSource", + "setter": "JsonSetter" + }] + } + } + }, + { + "componentName": "Table.Column", + "title": "Table.Column", + "npm": { + "package": "@alifd/next", + "version": "1.19.18", + "exportName": "Table", + "main": "src/index.js", + "destructuring": true, + "subName": "Column" + }, + "props": [ + { + "name": "title", + "propType": "string" + }, + { + "name": "dataIndex", + "propType": "string" + } + ] + }, { "componentName": "Badge", "title": "Badge", @@ -614,7 +886,7 @@ "name": "children", "propType": { "type": "instanceOf", - "value": "custom" + "value": "node" }, "description": "面包屑子节点,需传入 Breadcrumb.Item" }, @@ -663,7 +935,12 @@ "name": "style", "propType": "object" } - ] + ], + "configure": { + "component": { + "isContainer": true + } + } }, { "componentName": "MCBreadcrumb", @@ -699,7 +976,7 @@ "name": "children", "propType": { "type": "instanceOf", - "value": "custom" + "value": "node" }, "description": "面包屑子节点,需传入 Breadcrumb.Item" }, @@ -748,7 +1025,12 @@ "name": "style", "propType": "object" } - ] + ], + "configure": { + "component": { + "isContainer": true + } + } }, { "componentName": "Breadcrumb.Item", @@ -804,7 +1086,12 @@ "name": "style", "propType": "object" } - ] + ], + "configure": { + "component": { + "isContainer": true + } + } }, { "componentName": "Button", @@ -962,12 +1249,7 @@ "propType": "object", "description": "自定义内联样式" } - ], - "configure": { - "component": { - "isContainer": true - } - } + ] }, { "componentName": "Button.Group", @@ -3823,7 +4105,7 @@ }, { "name": "visible", - "propType": "bool", + "propType": "oneOfType", "description": "是否显示", "defaultValue": false }, @@ -4000,7 +4282,11 @@ "name": "style", "propType": "object" } - ] + ], + "configure": { + "isContainer": true, + "isModel": true + } }, { "componentName": "Inner", @@ -4266,26 +4552,6 @@ } ] }, - { - "componentName": "Table", - "title": "Table", - "docUrl": "", - "screenshot": "", - "npm": { - "package": "@alifd/next", - "version": "1.19.18", - "exportName": "Table", - "main": "src/index.js", - "destructuring": true, - "subName": "" - }, - "props": [ - { - "name": "style", - "propType": "object" - } - ] - }, { "componentName": "Form", "title": "Form", @@ -11888,6 +12154,72 @@ } } ] + },{ + "componentName": "Table", + "title": "表格", + "icon": "https://alifd.oss-cn-hangzhou.aliyuncs.com/fusion-cool/icons/icon-light/ic_light_table.png", + "package": "@alife/next", + "library": "Next", + "snippets": [ + { + "title": "表格", + "screenshot": "https://alifd.oss-cn-hangzhou.aliyuncs.com/fusion-cool/icons/icon-light/ic_light_table.png", + "schema": { + "componentName": "Table", + "props": { + "dataSource": [{ + "id": 1, "time": "2016" + },{ + "id": 2, "time": "2017" + }], + "size": "medium", + "prefix": "next-", + "hasBorder": true, + "hasHeader": true, + "isZebra": false, + "loading": false, + "expandedIndexSimulate": false, + "primaryKey": "id", + "locale": "zhCN.Table", + "crossline": false + }, + "children": [ + { + "componentName": "Table.Column", + "props": { + "title": "id", + "dataIndex": "id" + } + }, + { + "componentName": "Table.Column", + "props": { + "title": "time", + "dataIndex": "time" + } + } + ] + } + } + ] + },{ + "componentName": "Table.Column", + "title": "表格列", + "icon": "https://alifd.oss-cn-hangzhou.aliyuncs.com/fusion-cool/icons/icon-light/ic_light_table.png", + "package": "@alife/next", + "library": "Next", + "snippets": [ + { + "title": "表格列", + "screenshot": "https://alifd.oss-cn-hangzhou.aliyuncs.com/fusion-cool/icons/icon-light/ic_light_table.png", + "schema": { + "componentName": "Table.Column", + "props": { + "title": "name" + } + } + } + ] }, { "componentName": "Calendar", @@ -12381,6 +12713,54 @@ } ] }, + { + "componentName": "Button.Group", + "title": "按钮组", + "icon": "", + "package": "@alife/next", + "library": "Next", + "snippets": [ + { + "title": "按钮组", + "screenshot": "https://img.alicdn.com/tfs/TB1t6dhvV67gK0jSZPfXXahhFXa-310-122.png", + "schema": { + "componentName": "Button.Group", + "props": { + + }, + "children": [{ + "componentName": "Button", + "props": { + "type": "primary", + "style": { + "margin": "0 5px 0 5px" + }, + "htmlType": "submit" + }, + "children": [ + { + "componentName": "Icon", + "props": { + "type": "success" + } + }, + "提交" + ] + }, { + "componentName": "Button", + "props": { + "type": "normal", + "style": { + "margin": "0 5px 0 5px" + }, + "htmlType": "reset" + }, + "children": "重置" + }] + } + } + ] + }, { "componentName": "Divider", "title": "分隔符", @@ -12559,6 +12939,28 @@ } } ] + },{ + "componentName": "Breadcrumb.Item", + "title": "面包屑 Item", + "icon": "", + "package": "@alife/next", + "library": "Next", + "snippets": [ + { + "title": "面包屑", + "screenshot": "https://alifd.oss-cn-hangzhou.aliyuncs.com/fusion-cool/icons/icon-light/ic_light_breadcrumb.png", + "schema": { + "componentName": "Breadcrumb.Item", + "props": { + "prefix": "next-" + }, + "children": [ + "222", + "222111" + ] + } + } + ] }, { "componentName": "MCBreadcrumb", @@ -12763,17 +13165,23 @@ }, { "componentName": "Form.Item", - "title": "表单辅助工具", + "title": "Form.Item", "icon": "", "package": "@alife/next", "library": "Next", "snippets": [ { - "title": "表单辅助工具", + "title": "Form.Item", "screenshot": "", "schema": { "componentName": "Form.Item", - "props": {} + "props": { + "style":{ + "margin-bottom": "0", + "min-width": "200px", + "min-height": "28px" + } + } } } ] diff --git a/packages/code-generator/demo/schema.json b/packages/code-generator/demo/schema.json index e5a3b43e7..0e60ac61c 100644 --- a/packages/code-generator/demo/schema.json +++ b/packages/code-generator/demo/schema.json @@ -1,138 +1,420 @@ { "componentName": "Page", + "id": "node_dockcviv8fo1", + "props": { + "ref": "outterView", + "autoLoading": true, + "style": { + "padding": "0 5px 0 5px" + } + }, "fileName": "test", "dataSource": { "list": [] }, "state": { - "text": "outter" + "text": "outter", + "isShowDialog": false }, - "css": "body {font-size: 12px;} .botton{width:100px;color:#ff00ff}", "lifeCycles": { "componentDidMount": { - "type": "JSExpression", - "value": "function() {\n \t\tconsole.log('did mount');\n\t}" + "type": "JSFunction", + "value": "function() {\n console.log('did mount');\n }" }, "componentWillUnmount": { - "type": "JSExpression", - "value": "function() {\n \t\tconsole.log('will umount');\n\t}" + "type": "JSFunction", + "value": "function() {\n console.log('will umount');\n }" } }, - "methods": { "testFunc": { "type": "JSFunction", - "value": "function() {console.log('test func');}" - } - }, - - "props": { - "ref": "outterView", - "autoLoading": true, - "style": { - "padding": 20 + "value": "function() {\n console.log('test func');\n }" + }, + "onClick": { + "type": "JSFunction", + "value": "function(){\n this.setState({\n isShowDialog:true\n })\n\t}" } }, "children": [{ - "componentName": "Form", + "componentName": "Box", + "id": "node_dockcy8n9xed", "props": { - "labelCol": 3, - "style": {}, - "ref": "testForm" + "style": { + "backgroundColor": "rgba(31,56,88,0.1)", + "padding": "12px 12px 12px 12px" + } }, "children": [{ - "componentName": "Form.Item", - "props": { - "label": "姓名:", - "name": "name", - "initValue": "李雷" - }, - "children": [{ - "componentName": "Input", - "props": { - "placeholder": "请输入", - "size": "medium", - "style": { - "width": 320 - } - } - }] - }, { - "componentName": "Form.Item", - "props": { - "label": "年龄:", - "name": "age", - "initValue": "22" - }, - "children": [{ - "componentName": "NumberPicker", - "props": { - "size": "medium", - "type": "normal" - } - }] - }, { - "componentName": "Form.Item", - "props": { - "label": "职业:", - "name": "profession" - }, - "children": [{ - "componentName": "Select", - "props": { - "dataSource": [{ - "label": "教师", - "value": "t" - }, { - "label": "医生", - "value": "d" - }, { - "label": "歌手", - "value": "s" - }] - } - }] - }, { - "componentName": "Form.Item", + "componentName": "Box", + "id": "node_dockcy8n9xee", "props": { "style": { - "textAlign": "center" + "padding": "12px 12px 12px 12px", + "backgroundColor": "#ffffff" } }, "children": [{ - "componentName": "Button.Group", - "props": {}, + "componentName": "Breadcrumb", + "id": "node_dockcy8n9xef", + "props": { + "prefix": "next-", + "maxNode": 100, + "component": "nav" + }, "children": [{ - "componentName": "Button", + "componentName": "Breadcrumb.Item", + "id": "node_dockcy8n9xeg", "props": { - "type": "primary", - "style": { - "margin": "0 5px 0 5px" - }, - "htmlType": "submit" + "prefix": "next-" }, - "children": [ - { + "children": ["首页"] + }, { + "componentName": "Breadcrumb.Item", + "id": "node_dockcy8n9xei", + "props": { + "prefix": "next-" + }, + "children": ["品质中台"] + }, { + "componentName": "Breadcrumb.Item", + "id": "node_dockcy8n9xek", + "props": { + "prefix": "next-" + }, + "children": ["商家品质页面管理"] + }, { + "componentName": "Breadcrumb.Item", + "id": "node_dockcy8n9xem", + "props": { + "prefix": "next-" + }, + "children": ["质检知识条配置"] + }] + }] + }, { + "componentName": "Box", + "id": "node_dockcy8n9xeo", + "props": { + "style": { + "marginTop": "12px", + "backgroundColor": "#ffffff" + } + }, + "children": [{ + "componentName": "Form", + "id": "node_dockcy8n9xep", + "props": { + "inline": true, + "style": { + "marginTop": "12px", + "marginRight": "12px", + "marginLeft": "12px" + }, + "__events": [] + }, + "children": [{ + "componentName": "Form.Item", + "id": "node_dockcy8n9xeq", + "props": { + "style": { + "marginBottom": "0" + }, + "label": "类目名:" + }, + "children": [{ + "componentName": "Select", + "id": "node_dockcy8n9xer", + "props": { + "mode": "single", + "hasArrow": true, + "cacheValue": true, + "style": { + "width": "150px" + } + } + }] + }, { + "componentName": "Form.Item", + "id": "node_dockcy8n9xes", + "props": { + "style": { + "marginBottom": "0" + }, + "label": "项目类型:" + }, + "children": [{ + "componentName": "Select", + "id": "node_dockcy8n9xet", + "props": { + "mode": "single", + "hasArrow": true, + "cacheValue": true, + "style": { + "width": "200px" + } + } + }] + }, { + "componentName": "Form.Item", + "id": "node_dockcy8n9xeu", + "props": { + "style": { + "marginBottom": "0" + }, + "label": "项目 ID:" + }, + "children": [{ + "componentName": "Input", + "id": "node_dockcy8n9xev", + "props": { + "hasBorder": true, + "size": "medium", + "autoComplete": "off", + "style": { + "width": "200px" + } + } + }] + }, { + "componentName": "Button.Group", + "id": "node_dockcy8n9xew", + "props": {}, + "children": [{ + "componentName": "Button", + "id": "node_dockcy8n9xex", + "props": { + "type": "primary", + "style": { + "margin": "0 5px 0 5px" + }, + "htmlType": "submit" + }, + "children": [{ "componentName": "Icon", + "id": "node_dockcy8n9xey", "props": { "type": "success" } + }, "搜索"] + }, { + "componentName": "Button", + "id": "node_dockcy8n9xe10", + "props": { + "type": "normal", + "style": { + "margin": "0 5px 0 5px" + }, + "htmlType": "reset" }, - "提交" - ] - }, { - "componentName": "Button", - "props": { - "type": "normal", - "style": { - "margin": "0 5px 0 5px" - }, - "htmlType": "reset" - }, - "children": "重置" + "children": ["清空"] + }] }] }] + }, { + "componentName": "Box", + "id": "node_dockcy8n9xe12", + "props": { + "style": { + "justifyContent": "flex-end", + "display": "flex", + "backgroundColor": "#ffffff", + "flexDirection": "row", + "paddingRight": "24px" + } + }, + "children": [{ + "componentName": "Button", + "id": "node_dockcy8n9xe13", + "props": { + "prefix": "next-", + "type": "primary", + "size": "medium", + "htmlType": "button", + "component": "button", + "style": { + "width": "100px" + }, + "events": { + "onClick": { + "type": "JSFunction", + "value": "function(){ this.onClick() }", + "__eventData": { + "type": "componentEvent", + "name": "onClick", + "relatedEventName": "onClick" + } + } + }, + "__events": [{ + "type": "componentEvent", + "name": "onClick", + "relatedEventName": "onClick" + }], + "onClick": { + "type": "JSFunction", + "value": "function(){ this.onClick() }" + } + }, + "children": ["新建配置"] + }] + }, { + "componentName": "Box", + "id": "node_dockcy8n9xe15", + "props": { + "style": { + "backgroundColor": "#ffffff" + } + }, + "children": [{ + "componentName": "Table", + "id": "node_dockcy8n9xe16", + "props": { + "dataSource": [{ + "firstCategory": "其他", + "secondCategory": "新品预览", + "leafCategory": "", + "projectType": "标识判断", + "projectId": "", + "title": "其他类目->新品预览类目类型知识库", + "url": "其他", + "operation": "编辑" + }, { + "firstCategory": "其他", + "secondCategory": "新品预览", + "leafCategory": "", + "projectType": "", + "projectId": "1", + "title": "其他类目->新品预览项目Id知识库", + "url": "其他", + "operation": "编辑" + }], + "size": "medium", + "prefix": "next-", + "hasBorder": true, + "hasHeader": true, + "isZebra": false, + "loading": false, + "expandedIndexSimulate": false, + "primaryKey": "id", + "locale": "zhCN.Table", + "crossline": false, + "style": { + "margin": "24px 12px 24px 12px" + } + }, + "children": [{ + "componentName": "Table.Column", + "id": "node_dockcy8n9xe17", + "props": { + "title": "一级类目", + "dataIndex": "firstCategory" + } + }, { + "componentName": "Table.Column", + "id": "node_dockcy8n9xe18", + "props": { + "title": "二级类目", + "dataIndex": "secondCategory" + } + }, { + "componentName": "Table.Column", + "id": "node_dockcy8n9xe19", + "props": { + "title": "叶子类目", + "dataIndex": "leafCategory" + } + }, { + "componentName": "Table.Column", + "id": "node_dockcy8n9xe1a", + "props": { + "title": "项目类型", + "dataIndex": "projectType" + } + }, { + "componentName": "Table.Column", + "id": "node_dockcy8n9xe1b", + "props": { + "title": "项目 ID", + "dataIndex": "projectId" + } + }, { + "componentName": "Table.Column", + "id": "node_dockcy8n9xe1c", + "props": { + "title": "知识条标题", + "dataIndex": "title" + } + }, { + "componentName": "Table.Column", + "id": "node_dockcy8n9xe1d", + "props": { + "title": "知识条链接", + "dataIndex": "url" + } + }, { + "componentName": "Table.Column", + "id": "node_dockcy8n9xe1e", + "props": { + "title": "操作", + "dataIndex": "operation" + } + }] + }] + }, { + "componentName": "Box", + "id": "node_dockcy8n9xe1f", + "props": { + "style": { + "backgroundColor": "#ffffff", + "paddingBottom": "24px" + } + }, + "children": [{ + "componentName": "Pagination", + "id": "node_dockcy8n9xe1g", + "props": { + "prefix": "next-", + "type": "normal", + "shape": "normal", + "size": "medium", + "defaultCurrent": 1, + "total": 100, + "pageShowCount": 5, + "pageSize": 10, + "pageSizePosition": "start", + "showJump": true, + "style": { + "display": "flex", + "justifyContent": "flex-end" + } + } + }] }] + }, { + "componentName": "Dialog", + "id": "node_dockcy8n9xe1h", + "props": { + "prefix": "next-", + "footerAlign": "right", + "footerActions": ["ok", "cancel"], + "closeable": "esc,close", + "hasMask": true, + "align": "cc cc", + "minMargin": 40, + "visible": { + "type": "JSExpression", + "value": "this.state.isShowDialog" + }, + "children": { + "type": "JSSlot" + }, + "title": "标题", + "footer": { + "type": "JSSlot" + }, + "events": [] + } }] } From 9061e4b3847f22a9222d62ab6f4c4d8f94161c08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=98=A5=E5=B8=8C?= Date: Mon, 27 Jul 2020 11:11:14 +0800 Subject: [PATCH 2/8] =?UTF-8?q?fix:=20=F0=9F=90=9B=20support=20JSFunction?= =?UTF-8?q?=20type?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/generator/ProjectBuilder.ts | 58 ++++------- .../src/plugins/common/esmodule.ts | 75 ++++++++------- .../component/react/containerLifeCycle.ts | 26 ++--- .../component/react/containerMethod.ts | 14 +-- .../code-generator/src/solutions/icejs.ts | 3 +- packages/code-generator/src/types/schema.ts | 46 +++++---- .../code-generator/src/utils/compositeType.ts | 30 +++--- .../code-generator/src/utils/jsExpression.ts | 95 ++++++++++--------- .../code-generator/src/utils/nodeToJSX.ts | 74 ++++++++------- packages/code-generator/src/utils/validate.ts | 3 + 10 files changed, 203 insertions(+), 221 deletions(-) create mode 100644 packages/code-generator/src/utils/validate.ts diff --git a/packages/code-generator/src/generator/ProjectBuilder.ts b/packages/code-generator/src/generator/ProjectBuilder.ts index ec1c897b6..34211d0e5 100644 --- a/packages/code-generator/src/generator/ProjectBuilder.ts +++ b/packages/code-generator/src/generator/ProjectBuilder.ts @@ -24,8 +24,8 @@ interface IModuleInfo { function getDirFromRoot(root: IResultDir, path: string[]): IResultDir { let current: IResultDir = root; - path.forEach(p => { - const exist = current.dirs.find(d => d.name === p); + path.forEach((p) => { + const exist = current.dirs.find((d) => d.name === p); if (exist) { current = exist; } else { @@ -57,7 +57,7 @@ export class ProjectBuilder implements IProjectBuilder { this.postProcessors = postProcessors; } - public async generateProject(schema: IProjectSchema | string): Promise { + async generateProject(schema: IProjectSchema | string): Promise { // Init const schemaParser: ISchemaParser = new SchemaParser(); const builders = this.createModuleBuilders(); @@ -76,7 +76,7 @@ export class ProjectBuilder implements IProjectBuilder { // components // pages const containerBuildResult: IModuleInfo[] = await Promise.all( - parseResult.containers.map(async containerInfo => { + parseResult.containers.map(async (containerInfo) => { let builder: IModuleBuilder; let path: string[]; if (containerInfo.containerType === 'Page') { @@ -100,9 +100,7 @@ export class ProjectBuilder implements IProjectBuilder { // router if (parseResult.globalRouter && builders.router) { - const { files } = await builders.router.generateModule( - parseResult.globalRouter, - ); + const { files } = await builders.router.generateModule(parseResult.globalRouter); buildResult.push({ path: this.template.slots.router.path, @@ -112,9 +110,7 @@ export class ProjectBuilder implements IProjectBuilder { // entry if (parseResult.project && builders.entry) { - const { files } = await builders.entry.generateModule( - parseResult.project, - ); + const { files } = await builders.entry.generateModule(parseResult.project); buildResult.push({ path: this.template.slots.entry.path, @@ -122,14 +118,8 @@ export class ProjectBuilder implements IProjectBuilder { }); } // constants? - if ( - parseResult.project && - builders.constants && - this.template.slots.constants - ) { - const { files } = await builders.constants.generateModule( - parseResult.project, - ); + if (parseResult.project && builders.constants && this.template.slots.constants) { + const { files } = await builders.constants.generateModule(parseResult.project); buildResult.push({ path: this.template.slots.constants.path, @@ -137,14 +127,8 @@ export class ProjectBuilder implements IProjectBuilder { }); } // utils? - if ( - parseResult.globalUtils && - builders.utils && - this.template.slots.utils - ) { - const { files } = await builders.utils.generateModule( - parseResult.globalUtils, - ); + if (parseResult.globalUtils && builders.utils && this.template.slots.utils) { + const { files } = await builders.utils.generateModule(parseResult.globalUtils); buildResult.push({ path: this.template.slots.utils.path, @@ -153,9 +137,7 @@ export class ProjectBuilder implements IProjectBuilder { } // i18n? if (parseResult.globalI18n && builders.i18n && this.template.slots.i18n) { - const { files } = await builders.i18n.generateModule( - parseResult.globalI18n, - ); + const { files } = await builders.i18n.generateModule(parseResult.globalI18n); buildResult.push({ path: this.template.slots.i18n.path, @@ -164,9 +146,7 @@ export class ProjectBuilder implements IProjectBuilder { } // globalStyle if (parseResult.project && builders.globalStyle) { - const { files } = await builders.globalStyle.generateModule( - parseResult.project, - ); + const { files } = await builders.globalStyle.generateModule(parseResult.project); buildResult.push({ path: this.template.slots.globalStyle.path, @@ -175,9 +155,7 @@ export class ProjectBuilder implements IProjectBuilder { } // htmlEntry if (parseResult.project && builders.htmlEntry) { - const { files } = await builders.htmlEntry.generateModule( - parseResult.project, - ); + const { files } = await builders.htmlEntry.generateModule(parseResult.project); buildResult.push({ path: this.template.slots.htmlEntry.path, @@ -186,9 +164,7 @@ export class ProjectBuilder implements IProjectBuilder { } // packageJSON if (parseResult.project && builders.packageJSON) { - const { files } = await builders.packageJSON.generateModule( - parseResult.project, - ); + const { files } = await builders.packageJSON.generateModule(parseResult.project); buildResult.push({ path: this.template.slots.packageJSON.path, @@ -199,14 +175,14 @@ export class ProjectBuilder implements IProjectBuilder { // Post Process // Combine Modules - buildResult.forEach(moduleInfo => { + buildResult.forEach((moduleInfo) => { let targetDir = getDirFromRoot(projectRoot, moduleInfo.path); if (moduleInfo.moduleName) { const dir = new ResultDir(moduleInfo.moduleName); targetDir.addDirectory(dir); targetDir = dir; } - moduleInfo.files.forEach(file => targetDir.addFile(file)); + moduleInfo.files.forEach((file) => targetDir.addFile(file)); }); return projectRoot; @@ -215,7 +191,7 @@ export class ProjectBuilder implements IProjectBuilder { private createModuleBuilders(): Record { const builders: Record = {}; - Object.keys(this.plugins).forEach(pluginName => { + Object.keys(this.plugins).forEach((pluginName) => { if (this.plugins[pluginName].length > 0) { const options: { mainFileName?: string } = {}; if (this.template.slots[pluginName] && this.template.slots[pluginName].fileName) { diff --git a/packages/code-generator/src/plugins/common/esmodule.ts b/packages/code-generator/src/plugins/common/esmodule.ts index 50f315e52..2fbff2fed 100644 --- a/packages/code-generator/src/plugins/common/esmodule.ts +++ b/packages/code-generator/src/plugins/common/esmodule.ts @@ -15,6 +15,8 @@ import { IWithDependency, } from '../../types'; +import { isValidIdentifier } from '../../utils/validate'; + function groupDepsByPack(deps: IDependency[]): Record { const depMap: Record = {}; @@ -25,48 +27,53 @@ function groupDepsByPack(deps: IDependency[]): Record { depMap[pkg].push(dep); }; - deps.forEach(dep => { + // TODO: main 这个信息到底怎么用,是不是外部包不需要使用? + // deps.forEach(dep => { + // if (dep.dependencyType === DependencyType.Internal) { + // addDep( + // `${(dep as IInternalDependency).moduleName}${`/${dep.main}` || ''}`, + // dep, + // ); + // } else { + // addDep(`${(dep as IExternalDependency).package}${`/${dep.main}` || ''}`, dep); + // } + // }); + + deps.forEach((dep) => { if (dep.dependencyType === DependencyType.Internal) { - addDep( - `${(dep as IInternalDependency).moduleName}${`/${dep.main}` || ''}`, - dep, - ); + addDep(`${(dep as IInternalDependency).moduleName}`, dep); } else { - addDep(`${(dep as IExternalDependency).package}${`/${dep.main}` || ''}`, dep); + addDep(`${(dep as IExternalDependency).package}`, dep); } }); return depMap; } -function buildPackageImport( - pkg: string, - deps: IDependency[], - targetFileType: string, -): ICodeChunk[] { +function buildPackageImport(pkg: string, deps: IDependency[], targetFileType: string): ICodeChunk[] { const chunks: ICodeChunk[] = []; - let defaultImport: string = ''; - let defaultImportAs: string = ''; + let defaultImport = ''; + let defaultImportAs = ''; const imports: Record = {}; - deps.forEach(dep => { + deps.forEach((dep) => { const srcName = dep.exportName; let targetName = dep.importName || dep.exportName; - if (dep.subName) { - return; - } if (dep.subName) { - chunks.push({ - type: ChunkType.STRING, - fileType: targetFileType, - name: COMMON_CHUNK_NAME.FileVarDefine, - content: `const ${targetName} = ${srcName}.${dep.subName};`, - linkAfter: [ - COMMON_CHUNK_NAME.ExternalDepsImport, - COMMON_CHUNK_NAME.InternalDepsImport, - ], - }); + if (targetName !== `${srcName}.${dep.subName}`) { + if (!isValidIdentifier(targetName)) { + throw new CodeGeneratorError(`Invalid Identifier [${targetName}]`); + } + + chunks.push({ + type: ChunkType.STRING, + fileType: targetFileType, + name: COMMON_CHUNK_NAME.FileVarDefine, + content: `const ${targetName} = ${srcName}.${dep.subName};`, + linkAfter: [COMMON_CHUNK_NAME.ExternalDepsImport, COMMON_CHUNK_NAME.InternalDepsImport], + }); + } targetName = srcName; } @@ -74,18 +81,14 @@ function buildPackageImport( if (dep.destructuring) { imports[srcName] = targetName; } else if (defaultImport) { - throw new CodeGeneratorError( - `[${pkg}] has more than one default export.`, - ); + throw new CodeGeneratorError(`[${pkg}] has more than one default export.`); } else { defaultImport = srcName; defaultImportAs = targetName; } }); - const items = Object.keys(imports).map(src => - src === imports[src] ? src : `${src} as ${imports[src]}`, - ); + const items = Object.keys(imports).map((src) => (src === imports[src] ? src : `${src} as ${imports[src]}`)); const statementL = ['import']; if (defaultImport) { @@ -125,7 +128,7 @@ function buildPackageImport( type PluginConfig = { fileType: string; -} +}; const pluginFactory: BuilderComponentPluginFactory = (config?: PluginConfig) => { const cfg: PluginConfig = { @@ -143,9 +146,9 @@ const pluginFactory: BuilderComponentPluginFactory = (config?: Plu if (ir && ir.deps && ir.deps.length > 0) { const packs = groupDepsByPack(ir.deps); - Object.keys(packs).forEach(pkg => { + Object.keys(packs).forEach((pkg) => { const chunks = buildPackageImport(pkg, packs[pkg], cfg.fileType); - next.chunks.push.apply(next.chunks, chunks); + next.chunks.push(...chunks); }); } diff --git a/packages/code-generator/src/plugins/component/react/containerLifeCycle.ts b/packages/code-generator/src/plugins/component/react/containerLifeCycle.ts index d1951d8e2..000355b7d 100644 --- a/packages/code-generator/src/plugins/component/react/containerLifeCycle.ts +++ b/packages/code-generator/src/plugins/component/react/containerLifeCycle.ts @@ -1,28 +1,23 @@ import { CLASS_DEFINE_CHUNK_NAME, DEFAULT_LINK_AFTER } from '../../../const/generator'; import { REACT_CHUNK_NAME } from './const'; -import { - getFuncExprBody, - transformFuncExpr2MethodMember, -} from '../../../utils/jsExpression'; +import { generateFunction } from '../../../utils/jsExpression'; import { BuilderComponentPlugin, BuilderComponentPluginFactory, ChunkType, - CodeGeneratorError, FileType, ICodeChunk, ICodeStruct, IContainerInfo, - IJSExpression, } from '../../../types'; type PluginConfig = { fileType: string; exportNameMapping: Record; normalizeNameMapping: Record; -} +}; const pluginFactory: BuilderComponentPluginFactory = (config?) => { const cfg: PluginConfig = { @@ -41,7 +36,7 @@ const pluginFactory: BuilderComponentPluginFactory = (config?) => if (ir.lifeCycles) { const lifeCycles = ir.lifeCycles; - const chunks = Object.keys(lifeCycles).map(lifeCycleName => { + const chunks = Object.keys(lifeCycles).map((lifeCycleName) => { const normalizeName = cfg.normalizeNameMapping[lifeCycleName] || lifeCycleName; const exportName = cfg.exportNameMapping[lifeCycleName] || lifeCycleName; if (normalizeName === 'constructor') { @@ -49,9 +44,7 @@ const pluginFactory: BuilderComponentPluginFactory = (config?) => type: ChunkType.STRING, fileType: cfg.fileType, name: CLASS_DEFINE_CHUNK_NAME.ConstructorContent, - content: getFuncExprBody( - (lifeCycles[lifeCycleName] as IJSExpression).value, - ), + content: generateFunction(lifeCycles[lifeCycleName], { isBlock: true }), linkAfter: [...DEFAULT_LINK_AFTER[CLASS_DEFINE_CHUNK_NAME.ConstructorStart]], }; } @@ -60,9 +53,7 @@ const pluginFactory: BuilderComponentPluginFactory = (config?) => type: ChunkType.STRING, fileType: cfg.fileType, name: REACT_CHUNK_NAME.ClassRenderPre, - content: getFuncExprBody( - (lifeCycles[lifeCycleName] as IJSExpression).value, - ), + content: generateFunction(lifeCycles[lifeCycleName], { isBlock: true }), linkAfter: [REACT_CHUNK_NAME.ClassRenderStart], }; } @@ -71,15 +62,12 @@ const pluginFactory: BuilderComponentPluginFactory = (config?) => type: ChunkType.STRING, fileType: cfg.fileType, name: CLASS_DEFINE_CHUNK_NAME.InsMethod, - content: transformFuncExpr2MethodMember( - exportName, - (lifeCycles[lifeCycleName] as IJSExpression).value, - ), + content: generateFunction(lifeCycles[lifeCycleName], { name: exportName, isMember: true }), linkAfter: [...DEFAULT_LINK_AFTER[CLASS_DEFINE_CHUNK_NAME.InsMethod]], }; }); - next.chunks.push.apply(next.chunks, chunks); + next.chunks.push(...chunks); } return next; diff --git a/packages/code-generator/src/plugins/component/react/containerMethod.ts b/packages/code-generator/src/plugins/component/react/containerMethod.ts index 9bba467da..148f2cffd 100644 --- a/packages/code-generator/src/plugins/component/react/containerMethod.ts +++ b/packages/code-generator/src/plugins/component/react/containerMethod.ts @@ -1,6 +1,6 @@ import { CLASS_DEFINE_CHUNK_NAME, DEFAULT_LINK_AFTER } from '../../../const/generator'; -import { transformFuncExpr2MethodMember } from '../../../utils/jsExpression'; +import { generateFunction } from '../../../utils/jsExpression'; import { BuilderComponentPlugin, @@ -10,12 +10,11 @@ import { ICodeChunk, ICodeStruct, IContainerInfo, - IJSExpression, } from '../../../types'; type PluginConfig = { fileType: string; -} +}; const pluginFactory: BuilderComponentPluginFactory = (config?) => { const cfg: PluginConfig = { @@ -32,18 +31,15 @@ const pluginFactory: BuilderComponentPluginFactory = (config?) => if (ir.methods) { const methods = ir.methods; - const chunks = Object.keys(methods).map(methodName => ({ + const chunks = Object.keys(methods).map((methodName) => ({ type: ChunkType.STRING, fileType: cfg.fileType, name: CLASS_DEFINE_CHUNK_NAME.InsMethod, - content: transformFuncExpr2MethodMember( - methodName, - (methods[methodName] as IJSExpression).value, - ), + content: generateFunction(methods[methodName], { name: methodName, isMember: true }), linkAfter: [...DEFAULT_LINK_AFTER[CLASS_DEFINE_CHUNK_NAME.InsMethod]], })); - next.chunks.push.apply(next.chunks, chunks); + next.chunks.push(...chunks); } return next; diff --git a/packages/code-generator/src/solutions/icejs.ts b/packages/code-generator/src/solutions/icejs.ts index 66a865cbe..b1a35052e 100644 --- a/packages/code-generator/src/solutions/icejs.ts +++ b/packages/code-generator/src/solutions/icejs.ts @@ -59,6 +59,7 @@ export default function createIceJsProjectBuilder(): IProjectBuilder { Component: 'div', Page: 'div', Block: 'div', + // Box: 'div', }, }), css(), @@ -72,6 +73,6 @@ export default function createIceJsProjectBuilder(): IProjectBuilder { htmlEntry: [icejs.plugins.entryHtml()], packageJSON: [icejs.plugins.packageJSON()], }, - postProcessors: [prettier()], + postProcessors: [prettier()], // prettier() }); } diff --git a/packages/code-generator/src/types/schema.ts b/packages/code-generator/src/types/schema.ts index 68226e8ab..8ce54afa3 100644 --- a/packages/code-generator/src/types/schema.ts +++ b/packages/code-generator/src/types/schema.ts @@ -13,18 +13,36 @@ export interface IJSExpression { [extConfigName: string]: any; } +/** + * 搭建基础协议 - 函数定义 + * + * @export + * @interface IJSFunction + */ +export interface IJSFunction { + type: 'JSFunction'; + value: string; + [extConfigName: string]: any; +} + +/** + * 搭建基础协议 - 函数定义 + * + * @export + * @interface IJSSlot + */ +export interface IJSSlot { + type: 'JSSlot'; + value: IComponentNodeItem; + [extConfigName: string]: any; +} + // JSON 基本类型 export interface IJSONObject { [key: string]: JSONValue; } -export type JSONValue = - | boolean - | string - | number - | null - | JSONArray - | IJSONObject; +export type JSONValue = boolean | string | number | null | JSONArray | IJSONObject; export type JSONArray = JSONValue[]; export type CompositeArray = CompositeValue[]; @@ -33,11 +51,7 @@ export interface ICompositeObject { } // 复合类型 -export type CompositeValue = - | JSONValue - | IJSExpression - | CompositeArray - | ICompositeObject; +export type CompositeValue = JSONValue | IJSExpression | IJSFunction | IJSSlot | CompositeArray | ICompositeObject; /** * 搭建基础协议 - 多语言描述 @@ -136,8 +150,8 @@ export interface IContainerNodeItem extends IComponentNodeItem { * • componentWillUnmount() * • componentDidCatch(error, info) */ - lifeCycles?: Record; // 生命周期Hook方法 - methods?: Record; // 自定义方法设置 + lifeCycles?: Record; // 生命周期Hook方法 + methods?: Record; // 自定义方法设置 dataSource?: { list: IDataSourceConfig[]; }; // 异步数据源配置 @@ -154,9 +168,9 @@ export interface IDataSourceConfig { id: string; // 数据请求ID标识 isInit: boolean; // 是否为初始数据 支持表达式 值为true时,将在组件初始化渲染时自动发送当前数据请求 type: string; // 数据请求类型 'fetch' | 'mtop' | 'jsonp' | 'custom' - requestHandler?: IJSExpression; // 自定义扩展的外部请求处理器 仅type='custom'时生效 + requestHandler?: IJSExpression | IJSFunction; // 自定义扩展的外部请求处理器 仅type='custom'时生效 options?: IFetchOptions; // 请求参数配置 每种请求类型对应不同参数 - dataHandler?: IJSExpression; // 数据结果处理函数,形如:(data, err) => Object + dataHandler?: IJSExpression | IJSFunction; // 数据结果处理函数,形如:(data, err) => Object } /** diff --git a/packages/code-generator/src/utils/compositeType.ts b/packages/code-generator/src/utils/compositeType.ts index b62b2afe3..8c9011512 100644 --- a/packages/code-generator/src/utils/compositeType.ts +++ b/packages/code-generator/src/utils/compositeType.ts @@ -1,5 +1,5 @@ import { CompositeArray, CompositeValue, ICompositeObject } from '../types'; -import { generateExpression, isJsExpression } from './jsExpression'; +import { generateExpression, generateFunction, isJsExpression, isJsFunction } from './jsExpression'; type CustomHandler = (data: unknown) => string; interface CustomHandlerSet { @@ -11,18 +11,12 @@ interface CustomHandlerSet { expression?: CustomHandler; } -function generateArray( - value: CompositeArray, - handlers: CustomHandlerSet = {}, -): string { - const body = value.map(v => generateUnknownType(v, handlers)).join(','); +function generateArray(value: CompositeArray, handlers: CustomHandlerSet = {}): string { + const body = value.map((v) => generateUnknownType(v, handlers)).join(','); return `[${body}]`; } -function generateObject( - value: ICompositeObject, - handlers: CustomHandlerSet = {}, -): string { +function generateObject(value: ICompositeObject, handlers: CustomHandlerSet = {}): string { if (isJsExpression(value)) { if (handlers.expression) { return handlers.expression(value); @@ -30,8 +24,12 @@ function generateObject( return generateExpression(value); } + if (isJsFunction(value)) { + return generateFunction(value, { isArrow: true }); + } + const body = Object.keys(value) - .map(key => { + .map((key) => { const v = generateUnknownType(value[key], handlers); return `${key}: ${v}`; }) @@ -40,10 +38,7 @@ function generateObject( return `{${body}}`; } -export function generateUnknownType( - value: CompositeValue, - handlers: CustomHandlerSet = {}, -): string { +export function generateUnknownType(value: CompositeValue, handlers: CustomHandlerSet = {}): string { if (Array.isArray(value)) { if (handlers.array) { return handlers.array(value); @@ -67,10 +62,7 @@ export function generateUnknownType( return `${value}`; } -export function generateCompositeType( - value: CompositeValue, - handlers: CustomHandlerSet = {}, -): [boolean, string] { +export function generateCompositeType(value: CompositeValue, handlers: CustomHandlerSet = {}): [boolean, string] { const result = generateUnknownType(value, handlers); if (result.substr(0, 1) === "'" && result.substr(-1, 1) === "'") { diff --git a/packages/code-generator/src/utils/jsExpression.ts b/packages/code-generator/src/utils/jsExpression.ts index 9c8541692..d975228ee 100644 --- a/packages/code-generator/src/utils/jsExpression.ts +++ b/packages/code-generator/src/utils/jsExpression.ts @@ -1,39 +1,6 @@ -import traverse from '@babel/traverse'; -import * as parser from '@babel/parser'; -import { CodeGeneratorError, IJSExpression } from '../types'; - -let count = 0; - -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: ', JSON.stringify(path)); - } - }); - - if (count === 0) { - count++; - - test('this.aaa && this.bbb'); - } - } catch (error) { - // console.log('Error'); - console.log(error.message); - } - console.log('====================='); -} - -export function transformFuncExpr2MethodMember( - methodName: string, - functionBody: string, -): string { - // test(functionBody); +import { CodeGeneratorError, IJSExpression, IJSFunction } from '../types'; +export function transformFuncExpr2MethodMember(methodName: string, functionBody: string): string { const args = getFuncExprArguments(functionBody); const body = getFuncExprBody(functionBody); @@ -66,20 +33,60 @@ export function getFuncExprBody(functionBody: string) { return body; } -export function generateExpression(value: any): string { - if (value && (value as IJSExpression).type === 'JSExpression') { - // test((value as IJSExpression).value); +export function getArrowFunction(functionBody: string) { + const args = getFuncExprArguments(functionBody); + const body = getFuncExprBody(functionBody); + return `(${args}) => { ${body} }`; +} + +export function isJsExpression(value: unknown): boolean { + return value && typeof value === 'object' && (value as IJSExpression).type === 'JSExpression'; +} + +export function isJsFunction(value: unknown): boolean { + return value && typeof value === 'object' && (value as IJSFunction).type === 'JSFunction'; +} + +export function isJsCode(value: unknown): boolean { + return isJsExpression(value) || isJsFunction(value); +} + +export function generateExpression(value: any): string { + if (isJsExpression(value)) { return (value as IJSExpression).value || 'null'; } throw new CodeGeneratorError('Not a JSExpression'); } -export function isJsExpression(value: any): boolean { - return ( - value && - typeof value === 'object' && - (value as IJSExpression).type === 'JSExpression' - ); +export function generateFunction( + value: any, + config: { + name?: string; + isMember?: boolean; + isBlock?: boolean; + isArrow?: boolean; + } = { + name: undefined, + isMember: false, + isBlock: false, + isArrow: false, + }, +) { + if (isJsCode(value)) { + const functionCfg = value as IJSFunction; + if (config.isMember) { + return transformFuncExpr2MethodMember(config.name || '', functionCfg.value); + } + if (config.isBlock) { + return getFuncExprBody(functionCfg.value); + } + if (config.isArrow) { + return getArrowFunction(functionCfg.value); + } + return functionCfg.value; + } + + throw new CodeGeneratorError('Not a JSFunction or JSExpression'); } diff --git a/packages/code-generator/src/utils/nodeToJSX.ts b/packages/code-generator/src/utils/nodeToJSX.ts index 050d64f9d..ef6b4617e 100644 --- a/packages/code-generator/src/utils/nodeToJSX.ts +++ b/packages/code-generator/src/utils/nodeToJSX.ts @@ -11,7 +11,7 @@ import { INodeGeneratorConfig, } from '../types'; import { generateCompositeType } from './compositeType'; -import { generateExpression } from './jsExpression'; +import { generateExpression, isJsExpression } from './jsExpression'; // tslint:disable-next-line: no-empty const noop = () => []; @@ -24,7 +24,7 @@ export function handleChildren( children: ChildNodeType, handlers: HandlerSet, options?: { - rerun?: boolean, + rerun?: boolean; }, ): T[] { const opt = { @@ -34,13 +34,11 @@ export function handleChildren( if (Array.isArray(children)) { const list: ChildNodeItem[] = children as ChildNodeItem[]; - return list - .map(child => handleChildren(child, handlers, opt)) - .reduce((p, c) => p.concat(c), []); + return list.map((child) => handleChildren(child, handlers, opt)).reduce((p, c) => p.concat(c), []); } else if (typeof children === 'string') { const handler = handlers.string || handlers.common || noop; return handler(children as string); - } else if ((children as IJSExpression).type === 'JSExpression') { + } else if (isJsExpression(children)) { const handler = handlers.expression || handlers.common || noop; return handler(children as IJSExpression); } else { @@ -59,19 +57,19 @@ export function generateAttr(attrName: string, attrValue: any): CodePiece[] { return []; } const [isString, valueStr] = generateCompositeType(attrValue); - return [{ - value: `${attrName}=${isString ? `"${valueStr}"` : `{${valueStr}}`}`, - type: PIECE_TYPE.ATTR, - }]; + return [ + { + value: `${attrName}=${isString ? `"${valueStr}"` : `{${valueStr}}`}`, + type: PIECE_TYPE.ATTR, + }, + ]; } export function generateAttrs(nodeItem: IComponentNodeItem): CodePiece[] { const { props } = nodeItem; let pieces: CodePiece[] = []; - Object.keys(props).forEach((propName: string) => - pieces = pieces.concat(generateAttr(propName, props[propName])), - ); + Object.keys(props).forEach((propName: string) => (pieces = pieces.concat(generateAttr(propName, props[propName])))); return pieces; } @@ -98,8 +96,8 @@ export function generateReactCtrlLine(nodeItem: IComponentNodeItem): CodePiece[] if (nodeItem.loop && nodeItem.loopArgs) { let loopDataExp; - if ((nodeItem.loop as IJSExpression).type === 'JSExpression') { - loopDataExp = `(${(nodeItem.loop as IJSExpression).value})`; + if (isJsExpression(nodeItem.loop)) { + loopDataExp = `(${generateExpression(nodeItem.loop)})`; } else { loopDataExp = JSON.stringify(nodeItem.loop); } @@ -141,29 +139,29 @@ export function generateReactCtrlLine(nodeItem: IComponentNodeItem): CodePiece[] } export function linkPieces(pieces: CodePiece[]): string { - if (pieces.filter(p => p.type === PIECE_TYPE.TAG).length !== 1) { + if (pieces.filter((p) => p.type === PIECE_TYPE.TAG).length !== 1) { throw new CodeGeneratorError('One node only need one tag define'); } - const tagName = pieces.filter(p => p.type === PIECE_TYPE.TAG)[0].value; + const tagName = pieces.filter((p) => p.type === PIECE_TYPE.TAG)[0].value; const beforeParts = pieces - .filter(p => p.type === PIECE_TYPE.BEFORE) - .map(p => p.value) + .filter((p) => p.type === PIECE_TYPE.BEFORE) + .map((p) => p.value) .join(''); const afterParts = pieces - .filter(p => p.type === PIECE_TYPE.AFTER) - .map(p => p.value) + .filter((p) => p.type === PIECE_TYPE.AFTER) + .map((p) => p.value) .join(''); const childrenParts = pieces - .filter(p => p.type === PIECE_TYPE.CHILDREN) - .map(p => p.value) + .filter((p) => p.type === PIECE_TYPE.CHILDREN) + .map((p) => p.value) .join(''); let attrsParts = pieces - .filter(p => p.type === PIECE_TYPE.ATTR) - .map(p => p.value) + .filter((p) => p.type === PIECE_TYPE.ATTR) + .map((p) => p.value) .join(' '); attrsParts = !!attrsParts ? ` ${attrsParts}` : ''; @@ -188,16 +186,18 @@ export function createNodeGenerator( const generateNode = (nodeItem: IComponentNodeItem): string => { let pieces: CodePiece[] = []; - plugins.forEach(p => { + plugins.forEach((p) => { pieces = pieces.concat(p(nodeItem)); }); pieces = pieces.concat(generateBasicNode(nodeItem, nodeTypeMapping)); pieces = pieces.concat(generateAttrs(nodeItem)); if (nodeItem.children && (nodeItem.children as unknown[]).length > 0) { - pieces = pieces.concat(handleChildren(nodeItem.children, handlers).map(l => ({ - type: PIECE_TYPE.CHILDREN, - value: l, - }))); + pieces = pieces.concat( + handleChildren(nodeItem.children, handlers).map((l) => ({ + type: PIECE_TYPE.CHILDREN, + value: l, + })), + ); } return linkPieces(pieces); @@ -211,10 +211,12 @@ export function createNodeGenerator( export const generateString = (input: string) => [input]; export function createReactNodeGenerator(cfg?: INodeGeneratorConfig) { - return createNodeGenerator({ - string: generateString, - expression: (input) => [generateExpression(input)], - }, [ - generateReactCtrlLine, - ], cfg); + return createNodeGenerator( + { + string: generateString, + expression: (input) => [generateExpression(input)], + }, + [generateReactCtrlLine], + cfg, + ); } diff --git a/packages/code-generator/src/utils/validate.ts b/packages/code-generator/src/utils/validate.ts new file mode 100644 index 000000000..118d21ad4 --- /dev/null +++ b/packages/code-generator/src/utils/validate.ts @@ -0,0 +1,3 @@ +export const isValidIdentifier = (name: string) => { + return /^[_$a-zA-Z\xA0-\uFFFF][_$a-zA-Z0-9\xA0-\uFFFF]*$/.test(name); +}; From 8de2a9d799e77db051a845591f5904aa6a207df0 Mon Sep 17 00:00:00 2001 From: "mark.ck" Date: Mon, 27 Jul 2020 14:27:16 +0800 Subject: [PATCH 3/8] =?UTF-8?q?1.=20container=20=E7=BB=84=E4=BB=B6?= =?UTF-8?q?=E5=8F=AF=E9=85=8D=E7=BD=AE=20children=EF=BC=9B=202.=20schema.c?= =?UTF-8?q?hildren=20=E5=92=8C=20props.children=20=E5=86=85=E5=AE=B9?= =?UTF-8?q?=E5=90=88=E5=B9=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/demo/public/assets.json | 72 ++++++++++++------- packages/demo/public/schema.json | 8 +-- .../src/transducers/parse-props.ts | 1 + .../src/renderer-view.tsx | 10 ++- 4 files changed, 59 insertions(+), 32 deletions(-) diff --git a/packages/demo/public/assets.json b/packages/demo/public/assets.json index 2de653885..1d4ada11d 100644 --- a/packages/demo/public/assets.json +++ b/packages/demo/public/assets.json @@ -188,8 +188,9 @@ "propType": "object" }, { - "name": "columns", - "propType": "array" + "name": "children", + "propType": "array", + "description": "列" }, { "name": "emptyContent", @@ -1077,10 +1078,8 @@ }, { "name": "children", - "propType": { - "type": "instanceOf", - "value": "node" - } + "description": "内容", + "propType": "array" }, { "name": "style", @@ -1239,17 +1238,19 @@ }, { "name": "children", - "propType": { - "type": "instanceOf", - "value": "node" - } + "propType": "array" }, { "name": "style", "propType": "object", "description": "自定义内联样式" } - ] + ], + "configure": { + "component": { + "isContainer": true + } + } }, { "componentName": "Button.Group", @@ -4120,8 +4121,14 @@ { "name": "children", "propType": { - "type": "instanceOf", - "value": "node" + "type": "oneOfType", + "value": [ + "bool", + { + "type": "instanceOf", + "value": "node" + } + ] }, "description": "内容" }, @@ -4284,8 +4291,10 @@ } ], "configure": { - "isContainer": true, - "isModel": true + "component": { + "isContainer": true, + "isModel": true + } } }, { @@ -10510,11 +10519,24 @@ "propType": "func", "description": "接收 children 自定义渲染列表" }, + { + "name": "dataSource", + "propType": "array" + }, { "name": "style", "propType": "object" } - ] + ], + "configure": { + "props": { + "isExtends": true, + "override": [{ + "name": "dataSource", + "setter": "JsonSetter" + }] + } + } }, { "componentName": "Tree", @@ -12706,9 +12728,9 @@ "type": "primary", "size": "large", "htmlType": "button", - "component": "button" - }, - "children": "提交" + "component": "button", + "children": ["提交"] + } } } ] @@ -12952,12 +12974,12 @@ "schema": { "componentName": "Breadcrumb.Item", "props": { - "prefix": "next-" - }, - "children": [ - "222", - "222111" - ] + "prefix": "next-", + "children": [ + "222", + "222111" + ] + } } } ] diff --git a/packages/demo/public/schema.json b/packages/demo/public/schema.json index 065d5eabb..fcf89ccd0 100644 --- a/packages/demo/public/schema.json +++ b/packages/demo/public/schema.json @@ -456,13 +456,9 @@ "type":"JSExpression", "value":"this.state.isShowDialog" }, - "children":{ - "type":"JSSlot" - }, + "title":"标题", - "footer":{ - "type":"JSSlot" - }, + "events":[ ] } diff --git a/packages/editor-skeleton/src/transducers/parse-props.ts b/packages/editor-skeleton/src/transducers/parse-props.ts index 0bf803e41..10e153924 100644 --- a/packages/editor-skeleton/src/transducers/parse-props.ts +++ b/packages/editor-skeleton/src/transducers/parse-props.ts @@ -211,6 +211,7 @@ export default function(metadata: TransformedComponentMetadata): TransformedComp ) { if (component.isContainer !== false) { component.isContainer = true; + props.push(propConfigToFieldConfig(prop)); return; } } diff --git a/packages/react-simulator-renderer/src/renderer-view.tsx b/packages/react-simulator-renderer/src/renderer-view.tsx index 5adf162b4..e1945d853 100644 --- a/packages/react-simulator-renderer/src/renderer-view.tsx +++ b/packages/react-simulator-renderer/src/renderer-view.tsx @@ -142,10 +142,18 @@ class Renderer extends Component<{ renderer: SimulatorRenderer }> { }); console.info('menuprops', viewProps); } + let _children = leaf?.isContainer() ? (children == null ? [] : Array.isArray(children) ? children : [children]) : children; + if (props.children && props.children.length) { + if (Array.isArray(props.children)) { + _children = Array.isArray(_children) ? _children.concat(props.children) : props.children.unshift(_children); + } else { + Array.isArray(_children) && _children.push(props.children) || (_children = [_children].push(props.children)); + } + } return createElement( getDeviceView(Component, device, designMode), viewProps, - leaf?.isContainer() ? (children == null ? [] : Array.isArray(children) ? children : [children]) : children, + _children, ); }} onCompGetRef={(schema: any, ref: ReactInstance | null) => { From dc6f8e3844dfc4fd664dafc3ddaf316751e29d37 Mon Sep 17 00:00:00 2001 From: "mark.ck" Date: Mon, 27 Jul 2020 17:06:49 +0800 Subject: [PATCH 4/8] =?UTF-8?q?=E5=AE=8C=E5=96=84=E8=B5=84=E4=BA=A7?= =?UTF-8?q?=E5=8C=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/demo/public/assets.json | 222 +++++++++++++++--- packages/demo/public/schema.json | 6 +- .../src/renderer-view.tsx | 21 +- 3 files changed, 198 insertions(+), 51 deletions(-) diff --git a/packages/demo/public/assets.json b/packages/demo/public/assets.json index 1d4ada11d..4256d8320 100644 --- a/packages/demo/public/assets.json +++ b/packages/demo/public/assets.json @@ -9,8 +9,8 @@ { "title": "fusion组件库", "package": "@alifd/next", - "version": "1.19.18", - "urls": ["https://unpkg.antfin-inc.com/@alife/next@1.19.18/dist/next.js", "https://unpkg.antfin-inc.com/@alife/next@1.19.18/dist/next.css"], + "version": "1.20.0", + "urls": ["https://unpkg.antfin-inc.com/@alifd/next@1.20.0/dist/next.js", "https://unpkg.antfin-inc.com/@alifd/next@1.20.0/dist/next.css"], "library": "Next" }, { @@ -320,7 +320,7 @@ "exportName": "Table", "main": "src/index.js", "destructuring": true, - "subName": "" + "subName": "Column" }, "props": [ { @@ -388,7 +388,7 @@ "name": "showZero", "propType": "bool", "description": "当count为0时,是否显示count", - "defaultValue": false + "defaultValue": true }, { "name": "content", @@ -6121,7 +6121,12 @@ "name": "style", "propType": "object" } - ] + ], + "configure": { + "component": { + "isContainer": true + } + } }, { "componentName": "SubMenu", @@ -6245,7 +6250,7 @@ ] }, { - "componentName": "SelectableItem", + "componentName": "Menu.Item", "title": "SelectableItem", "docUrl": "", "screenshot": "", @@ -6543,8 +6548,8 @@ ] }, { - "componentName": "Group", - "title": "Group", + "componentName": "Menu.Group", + "title": "Menu.Group", "docUrl": "", "screenshot": "", "npm": { @@ -7847,7 +7852,7 @@ }, { "name": "backgroundColor", - "propType": "string", + "propType": "color", "description": "背景色" }, { @@ -8237,6 +8242,11 @@ "name": "renderPreview", "propType": "func", "description": "预览态模式下渲染的内容\n@param {number} value 评分值" + }, + { + "name": "value", + "propType": "number", + "description": "分值" } ] }, @@ -9967,6 +9977,73 @@ } ] }, + { + "componentName": "Tag", + "title": "Tag", + "docUrl": "", + "screenshot": "", + "npm": { + "package": "@alifd/next", + "version": "1.19.18", + "exportName": "Tag", + "main": "src/index.js", + "destructuring": true + }, + "props": [ + { + "name": "prefix", + "propType": "string", + "defaultValue": "next-" + }, + { + "name": "type", + "propType": { + "type": "oneOf", + "value": [ + "normal", + "primary" + ] + }, + "description": "标签的类型" + }, + { + "name": "size", + "propType": { + "type": "oneOf", + "value": [ + "small", + "medium", + "large" + ] + }, + "description": "标签的尺寸(large 尺寸为兼容表单场景 large = medium)" + }, + { + "name": "closeArea", + "propType": { + "type": "oneOf", + "value": [ + "tag", + "tail" + ] + } + }, + { + "name": "color", + "propType": "string", + "description": "标签颜色, 目前支持:blue、 green、 orange、red、 turquoise、 yellow 和 hex 颜色值 (`color keywords`作为 Tag 组件的保留字,请勿直接使用 ), `1.19.0` 以上版本生效" + }, + { + "name": "children", + "propType": "array" + } + ], + "configure": { + "component": { + "isContainer": true + } + } + }, { "componentName": "TimePicker", "title": "TimePicker", @@ -10261,7 +10338,12 @@ "name": "style", "propType": "object" } - ] + ], + "configure": { + "component": { + "isContainer": true + } + } }, { "componentName": "TimelineItem", @@ -10784,7 +10866,12 @@ "name": "style", "propType": "object" } - ] + ], + "configure": { + "component": { + "isContainer": true + } + } }, { "componentName": "TreeNode", @@ -11958,11 +12045,16 @@ "name": "style", "propType": "object" } - ] + ], + "configure": { + "component": { + "isContainer": true + } + } }, { - "componentName": "Cell", - "title": "Cell", + "componentName": "ResponsiveGrid.Cell", + "title": "ResponsiveGrid.Cell", "docUrl": "", "screenshot": "", "npm": { @@ -12015,7 +12107,12 @@ "name": "style", "propType": "object" } - ] + ], + "configure": { + "component": { + "isContainer": true + } + } }, { "componentName": "Box", @@ -12171,7 +12268,7 @@ "componentName": "Badge", "props": { "prefix": "next-", - "overflowCount": 99 + "showZero": true } } } @@ -12420,6 +12517,30 @@ } ] }, + { + "componentName": "Menu.Item", + "title": "菜单项", + "icon": "", + "package": "@alife/next", + "library": "Next", + "snippets": [ + { + "title": "菜单项", + "screenshot": "https://alifd.oss-cn-hangzhou.aliyuncs.com/fusion-cool/icons/icon-light/ic_light_menu.png", + "schema": { + "componentName": "Menu.Item", + "props": { + "parentMode": "inline", + "type": "item", + "component": "", + "disabled": true, + "className": "", + "needIndent": "" + } + } + } + ] + }, { "componentName": "Progress", "title": "进度指示器", @@ -12514,6 +12635,46 @@ "screenshot": "https://alifd.oss-cn-hangzhou.aliyuncs.com/fusion-cool/icons/icon-light/ic_light_timeline.png", "schema": { "componentName": "Timeline", + "props": { + "prefix": "next-", + "fold": [], + "animation": true + },"children": [ + { + "componentName": "TimelineItem", + "props": { + "state": "process", + "title": "12344" + } + }, + { + "componentName": "TimelineItem", + "props": { + "title": "Ship" + } + }, + { + "componentName": "TimelineItem", + "props": { + "title": "Order" + } + } + ] + } + } + ] + },{ + "componentName": "TimelineItem", + "title": "时间轴 Item", + "icon": "", + "package": "@alife/next", + "library": "Next", + "snippets": [ + { + "title": "时间轴 Item", + "screenshot": "https://alifd.oss-cn-hangzhou.aliyuncs.com/fusion-cool/icons/icon-light/ic_light_timeline.png", + "schema": { + "componentName": "TimelineItem", "props": { "prefix": "next-", "fold": [], @@ -12656,23 +12817,6 @@ } } ] - }, - { - "componentName": "Notification", - "title": "通知", - "icon": "", - "package": "@alife/next", - "library": "Next", - "snippets": [ - { - "title": "通知", - "screenshot": "", - "schema": { - "componentName": "Notification", - "props": {} - } - } - ] } ], "icon": "" @@ -12833,7 +12977,9 @@ "screenshot": "", "schema": { "componentName": "Icon", - "props": {} + "props": { + "type": "smile" + } } } ] @@ -12878,17 +13024,17 @@ ] }, { - "componentName": "Shell", - "title": "框架", + "componentName": "ResponsiveGrid.Cell", + "title": "栅格布局 Cell", "icon": "", "package": "@alife/next", "library": "Next", "snippets": [ { - "title": "框架", + "title": "栅格布局 Cell", "screenshot": "", "schema": { - "componentName": "Shell", + "componentName": "ResponsiveGrid.Cell", "props": {} } } diff --git a/packages/demo/public/schema.json b/packages/demo/public/schema.json index fcf89ccd0..a57d5a2e4 100644 --- a/packages/demo/public/schema.json +++ b/packages/demo/public/schema.json @@ -286,10 +286,10 @@ "onClick":{ "type":"JSFunction", "value":"function(){ this.onClick() }" - } - }, - "children":[ + }, + "children":[ "新建配置"] + } }] }, { diff --git a/packages/react-simulator-renderer/src/renderer-view.tsx b/packages/react-simulator-renderer/src/renderer-view.tsx index e1945d853..ca00e07ee 100644 --- a/packages/react-simulator-renderer/src/renderer-view.tsx +++ b/packages/react-simulator-renderer/src/renderer-view.tsx @@ -108,9 +108,17 @@ class Renderer extends Component<{ renderer: SimulatorRenderer }> { const leaf = host.document.getNode(__id); viewProps._leaf = leaf; viewProps._componentName = leaf?.componentName; + let _children = leaf?.isContainer() ? (children == null ? [] : Array.isArray(children) ? children : [children]) : children; + if (props.children && props.children.length) { + if (Array.isArray(props.children)) { + _children = Array.isArray(_children) ? _children.concat(props.children) : props.children.unshift(_children); + } else { + Array.isArray(_children) && _children.push(props.children) || (_children = [_children].push(props.children)); + } + } // 如果是容器 && 无children && 高宽为空 增加一个占位容器,方便拖动 - if (leaf?.isContainer() && children == null && (!viewProps.style || Object.keys(viewProps.style).length == 0)){ - children =
{ }); console.info('menuprops', viewProps); } - let _children = leaf?.isContainer() ? (children == null ? [] : Array.isArray(children) ? children : [children]) : children; - if (props.children && props.children.length) { - if (Array.isArray(props.children)) { - _children = Array.isArray(_children) ? _children.concat(props.children) : props.children.unshift(_children); - } else { - Array.isArray(_children) && _children.push(props.children) || (_children = [_children].push(props.children)); - } - } + return createElement( getDeviceView(Component, device, designMode), viewProps, From e51b9cbf7743866c8143c621be7253b36392d028 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=98=A5=E5=B8=8C?= Date: Mon, 27 Jul 2020 17:34:25 +0800 Subject: [PATCH 5/8] =?UTF-8?q?feat:=20=F0=9F=8E=B8=20code=20generator=20f?= =?UTF-8?q?ix=20slot=20support?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/code-generator/src/index.ts | 6 +- .../code-generator/src/parser/SchemaParser.ts | 16 ++-- .../component/recore/pageDataSource.ts | 17 ++-- .../plugins/component/recore/pageVmBody.ts | 31 ++++--- .../src/plugins/project/constants.ts | 5 +- packages/code-generator/src/types/core.ts | 39 +++++--- packages/code-generator/src/types/schema.ts | 3 +- .../code-generator/src/utils/compositeType.ts | 71 +++++++------- packages/code-generator/src/utils/jsSlot.ts | 21 +++++ .../code-generator/src/utils/nodeToJSX.ts | 92 +++++++++++++++---- 10 files changed, 202 insertions(+), 99 deletions(-) create mode 100644 packages/code-generator/src/utils/jsSlot.ts diff --git a/packages/code-generator/src/index.ts b/packages/code-generator/src/index.ts index 5d670b5ab..79e527354 100644 --- a/packages/code-generator/src/index.ts +++ b/packages/code-generator/src/index.ts @@ -11,11 +11,7 @@ import createRecoreProjectBuilder from './solutions/recore'; // 引入说明 import { REACT_CHUNK_NAME } from './plugins/component/react/const'; -import { - COMMON_CHUNK_NAME, - CLASS_DEFINE_CHUNK_NAME, - DEFAULT_LINK_AFTER, -} from './const/generator'; +import { COMMON_CHUNK_NAME, CLASS_DEFINE_CHUNK_NAME, DEFAULT_LINK_AFTER } from './const/generator'; // 引入通用插件组 import esmodule from './plugins/common/esmodule'; diff --git a/packages/code-generator/src/parser/SchemaParser.ts b/packages/code-generator/src/parser/SchemaParser.ts index 001cb2ca6..57cb01070 100644 --- a/packages/code-generator/src/parser/SchemaParser.ts +++ b/packages/code-generator/src/parser/SchemaParser.ts @@ -5,7 +5,7 @@ import { SUPPORT_SCHEMA_VERSION_LIST } from '../const'; -import { handleChildren } from '../utils/nodeToJSX'; +import { handleSubNodes } from '../utils/nodeToJSX'; import { uniqueArray } from '../utils/common'; import { @@ -198,11 +198,15 @@ class SchemaParser implements ISchemaParser { } getComponentNames(children: ChildNodeType): string[] { - return handleChildren(children, { - node: (i: IComponentNodeItem) => [i.componentName], - }, { - rerun: true, - }); + return handleSubNodes( + children, + { + node: (i: IComponentNodeItem) => [i.componentName], + }, + { + rerun: true, + }, + ); } } diff --git a/packages/code-generator/src/plugins/component/recore/pageDataSource.ts b/packages/code-generator/src/plugins/component/recore/pageDataSource.ts index 87d496aaf..2c580e72f 100644 --- a/packages/code-generator/src/plugins/component/recore/pageDataSource.ts +++ b/packages/code-generator/src/plugins/component/recore/pageDataSource.ts @@ -29,14 +29,11 @@ const pluginFactory: BuilderComponentPluginFactory = () => { const ir = next.ir as IContainerInfo; if (ir.dataSource) { const { dataSource } = ir; - const { - list, - ...rest - } = dataSource; + const { list, ...rest } = dataSource; let attrs: string[] = []; - const extConfigs = Object.keys(rest).map(extConfigName => { + const extConfigs = Object.keys(rest).map((extConfigName) => { const value = (rest as Record)[extConfigName]; const [isString, valueStr] = generateCompositeType(value); return `${extConfigName}: ${isString ? `'${valueStr}'` : valueStr}`; @@ -44,9 +41,13 @@ const pluginFactory: BuilderComponentPluginFactory = () => { attrs = [...attrs, ...extConfigs]; - const listProp = handleStringValueDefault(generateCompositeType(list as unknown as CompositeValue, { - expression: packJsExpression, - })); + const listProp = handleStringValueDefault( + generateCompositeType((list as unknown) as CompositeValue, { + handlers: { + expression: packJsExpression, + }, + }), + ); attrs.push(`list: ${listProp}`); diff --git a/packages/code-generator/src/plugins/component/recore/pageVmBody.ts b/packages/code-generator/src/plugins/component/recore/pageVmBody.ts index 8660ad195..ce09d5e50 100644 --- a/packages/code-generator/src/plugins/component/recore/pageVmBody.ts +++ b/packages/code-generator/src/plugins/component/recore/pageVmBody.ts @@ -5,23 +5,26 @@ import { ICodeStruct, IContainerInfo, IComponentNodeItem, + INodeGeneratorContext, CodePiece, PIECE_TYPE, } from '../../../types'; -import { COMMON_CHUNK_NAME, DEFAULT_LINK_AFTER } from '../../../const/generator'; +import { COMMON_CHUNK_NAME } from '../../../const/generator'; import { createNodeGenerator, generateString } from '../../../utils/nodeToJSX'; import { generateExpression } from '../../../utils/jsExpression'; import { generateCompositeType, handleStringValueDefault } from '../../../utils/compositeType'; -const generateGlobalProps = (nodeItem: IComponentNodeItem): CodePiece[] => { - return [{ - value: `{...globalProps.${nodeItem.componentName}}`, - type: PIECE_TYPE.ATTR, - }]; +const generateGlobalProps = (ctx: INodeGeneratorContext, nodeItem: IComponentNodeItem): CodePiece[] => { + return [ + { + value: `{...globalProps.${nodeItem.componentName}}`, + type: PIECE_TYPE.ATTR, + }, + ]; }; -const generateCtrlLine = (nodeItem: IComponentNodeItem): CodePiece[] => { +const generateCtrlLine = (ctx: INodeGeneratorContext, nodeItem: IComponentNodeItem): CodePiece[] => { const pieces: CodePiece[] = []; if (nodeItem.loop && nodeItem.loopArgs) { @@ -49,13 +52,13 @@ const generateCtrlLine = (nodeItem: IComponentNodeItem): CodePiece[] => { }; const pluginFactory: BuilderComponentPluginFactory = () => { - const generator = createNodeGenerator({ - string: generateString, - expression: (input) => [generateExpression(input)], - }, [ - generateGlobalProps, - generateCtrlLine, - ]); + const generator = createNodeGenerator( + { + string: generateString, + expression: (input) => [generateExpression(input)], + }, + [generateGlobalProps, generateCtrlLine], + ); const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => { const next: ICodeStruct = { diff --git a/packages/code-generator/src/plugins/project/constants.ts b/packages/code-generator/src/plugins/project/constants.ts index 5c02e9711..392a0b96d 100644 --- a/packages/code-generator/src/plugins/project/constants.ts +++ b/packages/code-generator/src/plugins/project/constants.ts @@ -26,10 +26,7 @@ const pluginFactory: BuilderComponentPluginFactory = () => { content: ` const constantConfig = ${constantStr}; `, - linkAfter: [ - COMMON_CHUNK_NAME.ExternalDepsImport, - COMMON_CHUNK_NAME.InternalDepsImport, - ], + linkAfter: [COMMON_CHUNK_NAME.ExternalDepsImport, COMMON_CHUNK_NAME.InternalDepsImport], }); next.chunks.push({ diff --git a/packages/code-generator/src/types/core.ts b/packages/code-generator/src/types/core.ts index cf2088f22..489bf17d9 100644 --- a/packages/code-generator/src/types/core.ts +++ b/packages/code-generator/src/types/core.ts @@ -53,17 +53,12 @@ export interface ICodeStruct extends IBaseCodeStruct { chunks: ICodeChunk[]; } -export type BuilderComponentPlugin = ( - initStruct: ICodeStruct, -) => Promise; +export type BuilderComponentPlugin = (initStruct: ICodeStruct) => Promise; export type BuilderComponentPluginFactory = (config?: T) => BuilderComponentPlugin; export interface IChunkBuilder { - run( - ir: any, - initialStructure?: ICodeStruct, - ): Promise<{ chunks: ICodeChunk[][] }>; + run(ir: any, initialStructure?: ICodeStruct): Promise<{ chunks: ICodeChunk[][] }>; getPlugins(): BuilderComponentPlugin[]; addPlugin(plugin: BuilderComponentPlugin): void; } @@ -80,10 +75,7 @@ export interface ICompiledModule { export interface IModuleBuilder { generateModule(input: unknown): Promise; generateModuleCode(schema: IBasicSchema | string): Promise; - linkCodeChunks( - chunks: Record, - fileName: string, - ): IResultFile[]; + linkCodeChunks(chunks: Record, fileName: string): IResultFile[]; addPlugin(plugin: BuilderComponentPlugin): void; } @@ -154,7 +146,7 @@ export enum PIECE_TYPE { ATTR = 'NodeCodePieceAttr', CHILDREN = 'NodeCodePieceChildren', AFTER = 'NodeCodePieceAfter', -}; +} export interface CodePiece { value: string; @@ -168,14 +160,35 @@ export interface HandlerSet { common?: (input: unknown) => T[]; } -export type ExtGeneratorPlugin = (nodeItem: IComponentNodeItem) => CodePiece[]; +export type ExtGeneratorPlugin = (ctx: INodeGeneratorContext, nodeItem: IComponentNodeItem) => CodePiece[]; export interface INodeGeneratorConfig { nodeTypeMapping?: Record; } +export type NodeGenerator = (nodeItem: IComponentNodeItem) => string; + +export interface INodeGeneratorContext { + generator: NodeGenerator; +} + // export interface InteratorScope { // [$item: string]: string; // $item 默认取值 "item" // [$index: string]: string | number; // $index 默认取值 "index" // __proto__: BlockInstance; // } + +export type CompositeValueCustomHandler = (data: unknown) => string; +export interface CompositeValueCustomHandlerSet { + boolean?: CompositeValueCustomHandler; + number?: CompositeValueCustomHandler; + string?: CompositeValueCustomHandler; + array?: CompositeValueCustomHandler; + object?: CompositeValueCustomHandler; + expression?: CompositeValueCustomHandler; +} + +export interface CompositeValueGeneratorOptions { + handlers?: CompositeValueCustomHandlerSet; + nodeGenerator?: NodeGenerator; +} diff --git a/packages/code-generator/src/types/schema.ts b/packages/code-generator/src/types/schema.ts index 8ce54afa3..e102c54cd 100644 --- a/packages/code-generator/src/types/schema.ts +++ b/packages/code-generator/src/types/schema.ts @@ -33,7 +33,8 @@ export interface IJSFunction { */ export interface IJSSlot { type: 'JSSlot'; - value: IComponentNodeItem; + value: IComponentNodeItem[]; + params?: string[]; [extConfigName: string]: any; } diff --git a/packages/code-generator/src/utils/compositeType.ts b/packages/code-generator/src/utils/compositeType.ts index 8c9011512..0bb6891b8 100644 --- a/packages/code-generator/src/utils/compositeType.ts +++ b/packages/code-generator/src/utils/compositeType.ts @@ -1,25 +1,22 @@ -import { CompositeArray, CompositeValue, ICompositeObject } from '../types'; +import { + CompositeArray, + CompositeValue, + ICompositeObject, + CompositeValueGeneratorOptions, + CodeGeneratorError, +} from '../types'; import { generateExpression, generateFunction, isJsExpression, isJsFunction } from './jsExpression'; +import { isJsSlot, generateJsSlot } from './jsSlot'; -type CustomHandler = (data: unknown) => string; -interface CustomHandlerSet { - boolean?: CustomHandler; - number?: CustomHandler; - string?: CustomHandler; - array?: CustomHandler; - object?: CustomHandler; - expression?: CustomHandler; -} - -function generateArray(value: CompositeArray, handlers: CustomHandlerSet = {}): string { - const body = value.map((v) => generateUnknownType(v, handlers)).join(','); +function generateArray(value: CompositeArray, options: CompositeValueGeneratorOptions = {}): string { + const body = value.map((v) => generateUnknownType(v, options)).join(','); return `[${body}]`; } -function generateObject(value: ICompositeObject, handlers: CustomHandlerSet = {}): string { +function generateObject(value: ICompositeObject, options: CompositeValueGeneratorOptions = {}): string { if (isJsExpression(value)) { - if (handlers.expression) { - return handlers.expression(value); + if (options.handlers && options.handlers.expression) { + return options.handlers.expression(value); } return generateExpression(value); } @@ -28,9 +25,16 @@ function generateObject(value: ICompositeObject, handlers: CustomHandlerSet = {} return generateFunction(value, { isArrow: true }); } + if (isJsSlot(value)) { + if (options.nodeGenerator) { + return generateJsSlot(value, options.nodeGenerator); + } + throw new CodeGeneratorError("Can't find Node Generator"); + } + const body = Object.keys(value) .map((key) => { - const v = generateUnknownType(value[key], handlers); + const v = generateUnknownType(value[key], options); return `${key}: ${v}`; }) .join(',\n'); @@ -38,32 +42,35 @@ function generateObject(value: ICompositeObject, handlers: CustomHandlerSet = {} return `{${body}}`; } -export function generateUnknownType(value: CompositeValue, handlers: CustomHandlerSet = {}): string { +export function generateUnknownType(value: CompositeValue, options: CompositeValueGeneratorOptions = {}): string { if (Array.isArray(value)) { - if (handlers.array) { - return handlers.array(value); + if (options.handlers && options.handlers.array) { + return options.handlers.array(value); } - return generateArray(value as CompositeArray, handlers); + return generateArray(value as CompositeArray, options); } else if (typeof value === 'object') { - if (handlers.object) { - return handlers.object(value); + if (options.handlers && options.handlers.object) { + return options.handlers.object(value); } - return generateObject(value as ICompositeObject, handlers); + return generateObject(value as ICompositeObject, options); } else if (typeof value === 'string') { - if (handlers.string) { - return handlers.string(value); + if (options.handlers && options.handlers.string) { + return options.handlers.string(value); } return `'${value}'`; - } else if (typeof value === 'number' && handlers.number) { - return handlers.number(value); - } else if (typeof value === 'boolean' && handlers.boolean) { - return handlers.boolean(value); + } else if (typeof value === 'number' && options.handlers && options.handlers.number) { + return options.handlers.number(value); + } else if (typeof value === 'boolean' && options.handlers && options.handlers.boolean) { + return options.handlers.boolean(value); } return `${value}`; } -export function generateCompositeType(value: CompositeValue, handlers: CustomHandlerSet = {}): [boolean, string] { - const result = generateUnknownType(value, handlers); +export function generateCompositeType( + value: CompositeValue, + options: CompositeValueGeneratorOptions = {}, +): [boolean, string] { + const result = generateUnknownType(value, options); if (result.substr(0, 1) === "'" && result.substr(-1, 1) === "'") { return [true, result.substring(1, result.length - 1)]; diff --git a/packages/code-generator/src/utils/jsSlot.ts b/packages/code-generator/src/utils/jsSlot.ts new file mode 100644 index 000000000..13f40eef6 --- /dev/null +++ b/packages/code-generator/src/utils/jsSlot.ts @@ -0,0 +1,21 @@ +import { CodeGeneratorError, NodeGenerator, IJSSlot } from '../types'; + +export function isJsSlot(value: unknown): boolean { + return value && typeof value === 'object' && (value as IJSSlot).type === 'JSSlot'; +} + +export function generateJsSlot(value: any, generator: NodeGenerator): string { + if (isJsSlot(value)) { + const slotCfg = value as IJSSlot; + if (!slotCfg.value) { + return 'null'; + } + const results = slotCfg.value.map((n) => generator(n)); + if (results.length === 1) { + return results[0]; + } + return `[${results.join(',')}]`; + } + + throw new CodeGeneratorError('Not a JSSlot'); +} diff --git a/packages/code-generator/src/utils/nodeToJSX.ts b/packages/code-generator/src/utils/nodeToJSX.ts index ef6b4617e..28583e7e3 100644 --- a/packages/code-generator/src/utils/nodeToJSX.ts +++ b/packages/code-generator/src/utils/nodeToJSX.ts @@ -9,6 +9,8 @@ import { HandlerSet, ExtGeneratorPlugin, INodeGeneratorConfig, + INodeGeneratorContext, + NodeGenerator, } from '../types'; import { generateCompositeType } from './compositeType'; import { generateExpression, isJsExpression } from './jsExpression'; @@ -20,7 +22,7 @@ const handleChildrenDefaultOptions = { rerun: false, }; -export function handleChildren( +export function handleSubNodes( children: ChildNodeType, handlers: HandlerSet, options?: { @@ -34,7 +36,7 @@ export function handleChildren( if (Array.isArray(children)) { const list: ChildNodeItem[] = children as ChildNodeItem[]; - return list.map((child) => handleChildren(child, handlers, opt)).reduce((p, c) => p.concat(c), []); + return list.map((child) => handleSubNodes(child, handlers, opt)).reduce((p, c) => p.concat(c), []); } else if (typeof children === 'string') { const handler = handlers.string || handlers.common || noop; return handler(children as string); @@ -45,18 +47,53 @@ export function handleChildren( const handler = handlers.node || handlers.common || noop; let curRes = handler(children as IComponentNodeItem); if (opt.rerun && children.children) { - const childRes = handleChildren(children.children, handlers, opt); + const childRes = handleSubNodes(children.children, handlers, opt); curRes = curRes.concat(childRes || []); } return curRes; } } -export function generateAttr(attrName: string, attrValue: any): CodePiece[] { +export function handleChildren( + ctx: INodeGeneratorContext, + children: ChildNodeType, + handlers: HandlerSet, + options?: { + rerun?: boolean; + }, +): T[] { + const opt = { + ...handleChildrenDefaultOptions, + ...(options || {}), + }; + + if (Array.isArray(children)) { + const list: ChildNodeItem[] = children as ChildNodeItem[]; + return list.map((child) => handleChildren(ctx, child, handlers, opt)).reduce((p, c) => p.concat(c), []); + } else if (typeof children === 'string') { + const handler = handlers.string || handlers.common || noop; + return handler(children as string); + } else if (isJsExpression(children)) { + const handler = handlers.expression || handlers.common || noop; + return handler(children as IJSExpression); + } else { + const handler = handlers.node || handlers.common || noop; + let curRes = handler(children as IComponentNodeItem); + if (opt.rerun && children.children) { + const childRes = handleChildren(ctx, children.children, handlers, opt); + curRes = curRes.concat(childRes || []); + } + return curRes; + } +} + +export function generateAttr(ctx: INodeGeneratorContext, attrName: string, attrValue: any): CodePiece[] { if (attrName === 'initValue') { return []; } - const [isString, valueStr] = generateCompositeType(attrValue); + const [isString, valueStr] = generateCompositeType(attrValue, { + nodeGenerator: ctx.generator, + }); return [ { value: `${attrName}=${isString ? `"${valueStr}"` : `{${valueStr}}`}`, @@ -65,11 +102,13 @@ export function generateAttr(attrName: string, attrValue: any): CodePiece[] { ]; } -export function generateAttrs(nodeItem: IComponentNodeItem): CodePiece[] { +export function generateAttrs(ctx: INodeGeneratorContext, nodeItem: IComponentNodeItem): CodePiece[] { const { props } = nodeItem; let pieces: CodePiece[] = []; - Object.keys(props).forEach((propName: string) => (pieces = pieces.concat(generateAttr(propName, props[propName])))); + Object.keys(props).forEach( + (propName: string) => (pieces = pieces.concat(generateAttr(ctx, propName, props[propName]))), + ); return pieces; } @@ -81,7 +120,11 @@ function mapNodeName(src: string, mapping: Record): string { return src; } -export function generateBasicNode(nodeItem: IComponentNodeItem, mapping: Record): CodePiece[] { +export function generateBasicNode( + ctx: INodeGeneratorContext, + nodeItem: IComponentNodeItem, + mapping: Record, +): CodePiece[] { const pieces: CodePiece[] = []; pieces.push({ value: mapNodeName(nodeItem.componentName, mapping), @@ -91,7 +134,19 @@ export function generateBasicNode(nodeItem: IComponentNodeItem, mapping: Record< return pieces; } -export function generateReactCtrlLine(nodeItem: IComponentNodeItem): CodePiece[] { +// TODO: 生成文档 +// 为包裹的代码片段生成子上下文,集成父级上下文,并传入子级上下文新增内容。(如果存在多级上下文怎么处理?) +// 创建新的上下文,并从作用域中取对应同名变量塞到作用域里面? +// export function createSubContext() {} + +/** + * JSX 生成逻辑插件。在 React 代码模式下生成 loop 与 condition 相关的逻辑代码 + * + * @export + * @param {IComponentNodeItem} nodeItem 当前 UI 节点 + * @returns {CodePiece[]} 实现功能的相关代码片段 + */ +export function generateReactCtrlLine(ctx: INodeGeneratorContext, nodeItem: IComponentNodeItem): CodePiece[] { const pieces: CodePiece[] = []; if (nodeItem.loop && nodeItem.loopArgs) { @@ -112,7 +167,9 @@ export function generateReactCtrlLine(nodeItem: IComponentNodeItem): CodePiece[] } if (nodeItem.condition) { - const [isString, value] = generateCompositeType(nodeItem.condition); + const [isString, value] = generateCompositeType(nodeItem.condition, { + nodeGenerator: ctx.generator, + }); pieces.unshift({ value: `(${isString ? `'${value}'` : value}) && (`, @@ -177,7 +234,7 @@ export function createNodeGenerator( handlers: HandlerSet, plugins: ExtGeneratorPlugin[], cfg?: INodeGeneratorConfig, -) { +): NodeGenerator { let nodeTypeMapping: Record = {}; if (cfg && cfg.nodeTypeMapping) { nodeTypeMapping = cfg.nodeTypeMapping; @@ -185,15 +242,18 @@ export function createNodeGenerator( const generateNode = (nodeItem: IComponentNodeItem): string => { let pieces: CodePiece[] = []; + const ctx: INodeGeneratorContext = { + generator: generateNode, + }; plugins.forEach((p) => { - pieces = pieces.concat(p(nodeItem)); + pieces = pieces.concat(p(ctx, nodeItem)); }); - pieces = pieces.concat(generateBasicNode(nodeItem, nodeTypeMapping)); - pieces = pieces.concat(generateAttrs(nodeItem)); + pieces = pieces.concat(generateBasicNode(ctx, nodeItem, nodeTypeMapping)); + pieces = pieces.concat(generateAttrs(ctx, nodeItem)); if (nodeItem.children && (nodeItem.children as unknown[]).length > 0) { pieces = pieces.concat( - handleChildren(nodeItem.children, handlers).map((l) => ({ + handleChildren(ctx, nodeItem.children, handlers).map((l) => ({ type: PIECE_TYPE.CHILDREN, value: l, })), @@ -210,7 +270,7 @@ export function createNodeGenerator( export const generateString = (input: string) => [input]; -export function createReactNodeGenerator(cfg?: INodeGeneratorConfig) { +export function createReactNodeGenerator(cfg?: INodeGeneratorConfig): NodeGenerator { return createNodeGenerator( { string: generateString, From f9310dac0b4560855dd74077b161a9b734fa45f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=98=A5=E5=B8=8C?= Date: Mon, 27 Jul 2020 17:51:42 +0800 Subject: [PATCH 6/8] =?UTF-8?q?chore:=20=F0=9F=A4=96=20fix=20demo=20schema?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/demo/public/schema.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/demo/public/schema.json b/packages/demo/public/schema.json index a57d5a2e4..4622272a4 100644 --- a/packages/demo/public/schema.json +++ b/packages/demo/public/schema.json @@ -135,7 +135,7 @@ "id":"node_dockcy8n9xeq", "props":{ "style":{ - "margin-bottom":"0" + "marginBottom":"0" }, "label":"类目名:" }, @@ -158,7 +158,7 @@ "id":"node_dockcy8n9xes", "props":{ "style":{ - "margin-bottom":"0" + "marginBottom":"0" }, "label":"项目类型:" }, @@ -181,7 +181,7 @@ "id":"node_dockcy8n9xeu", "props":{ "style":{ - "margin-bottom":"0" + "marginBottom":"0" }, "label":"项目 ID:" }, From f91da661b3359641f288da04d31f90447e30deba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=98=A5=E5=B8=8C?= Date: Mon, 27 Jul 2020 18:13:10 +0800 Subject: [PATCH 7/8] =?UTF-8?q?feat:=20=F0=9F=8E=B8=20saveload=20btn=20for?= =?UTF-8?q?=20demo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/demo/src/editor/components.ts | 2 + packages/demo/src/editor/config.js | 8 +++ .../demo/src/editor/plugins/saveload.scss | 4 ++ packages/demo/src/editor/plugins/saveload.tsx | 68 +++++++++++++++++++ 4 files changed, 82 insertions(+) create mode 100644 packages/demo/src/editor/plugins/saveload.scss create mode 100644 packages/demo/src/editor/plugins/saveload.tsx diff --git a/packages/demo/src/editor/components.ts b/packages/demo/src/editor/components.ts index 6e64a4201..4a9a9382b 100644 --- a/packages/demo/src/editor/components.ts +++ b/packages/demo/src/editor/components.ts @@ -9,6 +9,7 @@ import variableBindDialog from '@ali/lowcode-plugin-variable-bind-dialog'; import sourceEditor from '@ali/lowcode-plugin-source-editor'; import codeout from './plugins/codeout'; +import saveload from './plugins/saveload'; export default { logo, @@ -21,4 +22,5 @@ export default { variableBindDialog, sourceEditor, codeout, + saveload, }; diff --git a/packages/demo/src/editor/config.js b/packages/demo/src/editor/config.js index ebf7be410..f950c31ae 100644 --- a/packages/demo/src/editor/config.js +++ b/packages/demo/src/editor/config.js @@ -45,6 +45,14 @@ export default { width: 64, }, }, + { + pluginKey: 'saveload', + type: 'Custom', + props: { + align: 'right', + width: 128, + }, + }, ], leftArea: [ { diff --git a/packages/demo/src/editor/plugins/saveload.scss b/packages/demo/src/editor/plugins/saveload.scss new file mode 100644 index 000000000..1882d1f91 --- /dev/null +++ b/packages/demo/src/editor/plugins/saveload.scss @@ -0,0 +1,4 @@ +.lowcode-plugin-saveload { + padding: 10px 4px; + display: inline-block; +} diff --git a/packages/demo/src/editor/plugins/saveload.tsx b/packages/demo/src/editor/plugins/saveload.tsx new file mode 100644 index 000000000..fc7ba6acd --- /dev/null +++ b/packages/demo/src/editor/plugins/saveload.tsx @@ -0,0 +1,68 @@ +/* eslint-disable @typescript-eslint/no-empty-function */ +/* eslint-disable @typescript-eslint/no-empty-interface */ +import React from 'react'; +import { Button } from '@alifd/next'; +import { PluginProps, NpmInfo } from '@ali/lowcode-types'; +import { Designer } from '@ali/lowcode-designer'; + +import './saveload.scss'; + +interface BasicSection { + componentName: string; + title: string; + description?: string; + docUrl?: string; + screenshot?: string; + icon?: string; + tags?: string[]; + devMode?: 'proCode' | 'lowCode'; + npm: NpmInfo; + [k: string]: any; +} + +const Codeout = ({ editor }: PluginProps) => { + const handleSaveClick = () => { + const designer = editor.get(Designer); + if (designer) { + const schema = designer.schema.componentsTree[0]; // editor.get('schema'); + const schemaStr = JSON.stringify(schema); + window.localStorage.setItem('schema_data', schemaStr); + console.info('save schema:', schemaStr); + alert('保存成功'); + } + }; + + const handleLoadClick = () => { + const designer = editor.get(Designer); + if (designer) { + const tmp = window.localStorage.getItem('schema_data'); + if (tmp) { + try { + const schema = JSON.parse(tmp); + editor.set('schema', schema); + console.info('load schema:', schema); + alert('加载成功'); + } catch (error) { + console.log('Invalid Schema', error); + } + } + } + }; + + return ( + +
+ +
+
+ +
+
+ ); +}; + +export default Codeout; From 75e95680ba285b599dfc288de9b7d795ce3fe210 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=87=91=E7=A6=85?= Date: Mon, 27 Jul 2020 21:53:00 +0800 Subject: [PATCH 8/8] add drawer component --- packages/demo/public/assets.json | 283 ++++++++++++++++++++++++++++++- packages/demo/public/schema.json | 59 ++++--- 2 files changed, 311 insertions(+), 31 deletions(-) diff --git a/packages/demo/public/assets.json b/packages/demo/public/assets.json index 4256d8320..2dd7a5c09 100644 --- a/packages/demo/public/assets.json +++ b/packages/demo/public/assets.json @@ -66,6 +66,262 @@ } } }, + { + "componentName": "Drawer", + "title": "抽屉", + "docUrl": "", + "screenshot": "", + "npm": { + "package": "@alifd/next", + "version": "1.19.18", + "exportName": "Drawer", + "main": "src/index.js", + "destructuring": true, + "subName": "" + }, + "props": [ + { + "name": "prefix", + "propType": "string", + "defaultValue": "next-" + }, + { + "name": "style", + "propType": "object" + }, + { + "name": "pure", + "propType": "bool" + }, + { + "name": "rtl", + "propType": "bool" + }, + { + "name": "trigger", + "propType": { + "type": "instanceOf", + "value": "element" + }, + "defaultValue": null + }, + { + "name": "triggerType", + "propType": { + "type": "oneOfType", + "value": [ + "string", + { + "type": "instanceOf", + "value": "array" + } + ] + }, + "defaultValue": "click" + }, + { + "name": "width", + "propType": { + "type": "oneOfType", + "value": [ + "number", + "string" + ] + }, + "description": "宽度,仅在 placement是 left right 的时候生效" + }, + { + "name": "height", + "propType": { + "type": "oneOfType", + "value": [ + "number", + "string" + ] + }, + "description": "高度,仅在 placement是 top bottom 的时候生效" + }, + { + "name": "closeable", + "propType": { + "type": "oneOfType", + "value": [ + "string", + "bool" + ] + }, + "description": "控制对话框关闭的方式,值可以为字符串或者布尔值,其中字符串是由以下值组成:\n**close** 表示点击关闭按钮可以关闭对话框\n**mask** 表示点击遮罩区域可以关闭对话框\n**esc** 表示按下 esc 键可以关闭对话框\n如 'close' 或 'close,esc,mask'\n如果设置为 true,则以上关闭方式全部生效\n如果设置为 false,则以上关闭方式全部失效", + "defaultValue": true + }, + { + "name": "onClose", + "propType": "func", + "description": "对话框关闭时触发的回调函数\n@param {String} trigger 关闭触发行为的描述字符串\n@param {Object} event 关闭时事件对象" + }, + { + "name": "placement", + "propType": { + "type": "oneOf", + "value": [ + "top", + "right", + "bottom", + "left" + ] + }, + "description": "位于页面的位置", + "defaultValue": "right" + }, + { + "name": "title", + "propType": { + "type": "instanceOf", + "value": "node" + }, + "description": "标题" + }, + { + "name": "headerStyle", + "propType": "object", + "description": "header上的样式" + }, + { + "name": "bodyStyle", + "propType": "object", + "description": "body上的样式" + }, + { + "name": "visible", + "propType": "bool", + "description": "是否显示" + }, + { + "name": "hasMask", + "propType": "bool", + "description": "是否显示遮罩", + "defaultValue": true + }, + { + "name": "onVisibleChange", + "propType": "func" + }, + { + "name": "animation", + "propType": { + "type": "oneOfType", + "value": [ + "object", + "bool" + ] + }, + "description": "显示隐藏时动画的播放方式\n@property {String} in 进场动画\n@property {String} out 出场动画" + }, + { + "name": "locale", + "propType": "object" + }, + { + "name": "popupContainer", + "propType": "any" + } + ],"configure": { + "component": { + "isContainer": true, + "isModel": true + } + } + }, + { + "componentName": "Drawer.Inner", + "title": "Drawer.Inner", + "docUrl": "", + "screenshot": "", + "npm": { + "package": "@alifd/next", + "version": "1.19.18", + "exportName": "Drawer", + "main": "src/index.js", + "destructuring": true, + "subName": "Inner" + }, + "props": [ + { + "name": "prefix", + "propType": "string", + "defaultValue": "next-" + }, + { + "name": "className", + "propType": "string" + }, + { + "name": "closeable", + "propType": "bool", + "defaultValue": true + }, + { + "name": "role", + "propType": "string", + "defaultValue": "dialog" + }, + { + "name": "title", + "propType": "string" + }, + { + "name": "placement", + "propType": { + "type": "oneOf", + "value": [ + "top", + "right", + "bottom", + "left" + ] + } + }, + { + "name": "rtl", + "propType": "bool" + }, + { + "name": "onClose", + "propType": "func" + }, + { + "name": "locale", + "propType": "object" + }, + { + "name": "headerStyle", + "propType": "object" + }, + { + "name": "bodyStyle", + "propType": "object" + }, + { + "name": "afterClose", + "propType": "func" + }, + { + "name": "beforeOpen", + "propType": "func" + }, + { + "name": "beforeClose", + "propType": "func" + }, + { + "name": "cache", + "propType": "bool" + }, + { + "name": "shouldUpdatePosition", + "propType": "bool" + } + ] + }, { "componentName": "Table", "title": "Table", @@ -12273,7 +12529,32 @@ } } ] - },{ + }, + { + "componentName": "Drawer", + "title": "抽屉", + "icon": "", + "package": "@alife/next", + "library": "Next", + "snippets": [ + { + "title": "抽屉", + "screenshot": "https://img.alicdn.com/tfs/TB1RiM3lgHqK1RjSZFEXXcGMXXa-404-422.png", + "schema": { + "componentName": "Drawer", + "props": { + "prefix": "next-", + "triggerType": "click", + "closeable": true, + "placement": "right", + "hasMask": true, + "visible": true + } + } + } + ] + }, + { "componentName": "Table", "title": "表格", "icon": "https://alifd.oss-cn-hangzhou.aliyuncs.com/fusion-cool/icons/icon-light/ic_light_table.png", diff --git a/packages/demo/public/schema.json b/packages/demo/public/schema.json index 4622272a4..91880b822 100644 --- a/packages/demo/public/schema.json +++ b/packages/demo/public/schema.json @@ -72,37 +72,37 @@ "componentName":"Breadcrumb.Item", "id":"node_dockcy8n9xeg", "props":{ - "prefix":"next-" - }, - "children":[ - "首页"] + "prefix":"next-", + "children":[ + "首页"] + } }, { "componentName":"Breadcrumb.Item", "id":"node_dockcy8n9xei", "props":{ - "prefix":"next-" - }, - "children":[ - "品质中台"] + "prefix":"next-", + "children":[ + "品质中台"] + } }, { "componentName":"Breadcrumb.Item", "id":"node_dockcy8n9xek", "props":{ - "prefix":"next-" - }, - "children":[ - "商家品质页面管理"] + "prefix":"next-", + "children":[ + "商家品质页面管理"] + } }, { "componentName":"Breadcrumb.Item", "id":"node_dockcy8n9xem", "props":{ - "prefix":"next-" - }, - "children":[ - "质检知识条配置"] + "prefix":"next-", + "children":[ + "质检知识条配置"] + } }] }] }, @@ -213,17 +213,17 @@ "style":{ "margin":"0 5px 0 5px" }, - "htmlType":"submit" - }, - "children":[ - { + "htmlType":"submit", + "children":[ + { "componentName":"Icon", "id":"node_dockcy8n9xey", "props":{ - "type":"success" + "type":"success" } - }, - "搜索"] + }, + "搜索"] + } }, { "componentName":"Button", @@ -233,10 +233,10 @@ "style":{ "margin":"0 5px 0 5px" }, - "htmlType":"reset" - }, - "children":[ - "清空"] + "htmlType":"reset", + "children":[ + "清空"] + } }] }] }] @@ -266,6 +266,7 @@ "style":{ "width":"100px" }, + "children":["新建配置"], "events":{ "onClick":{ "type":"JSFunction", @@ -286,9 +287,7 @@ "onClick":{ "type":"JSFunction", "value":"function(){ this.onClick() }" - }, - "children":[ - "新建配置"] + } } }] },