mirror of
https://github.com/alibaba/lowcode-engine.git
synced 2026-01-13 01:21:58 +00:00
Merge branch 'release/0.9.0' of gitlab.alibaba-inc.com:ali-lowcode/ali-lowcode-engine into release/0.9.0
This commit is contained in:
commit
89d05b572b
53
packages/code-generator/demo/demo.js
Normal file
53
packages/code-generator/demo/demo.js
Normal file
@ -0,0 +1,53 @@
|
||||
const fs = require('fs');
|
||||
const CodeGenerator = require('../lib').default;
|
||||
|
||||
function flatFiles(rootName, dir) {
|
||||
const dirRoot = rootName ? `${rootName}/${dir.name}` : dir.name;
|
||||
const files = dir.files.map(file => ({
|
||||
name: `${dirRoot}/${file.name}.${file.ext}`,
|
||||
content: file.content,
|
||||
ext: '',
|
||||
}));
|
||||
const filesInSub = dir.dirs.map(subDir => flatFiles(`${dirRoot}`, subDir));
|
||||
const result = files.concat.apply(files, filesInSub);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
function displayResultInConsole(root, fileName) {
|
||||
const files = flatFiles('.', root);
|
||||
files.forEach(file => {
|
||||
if (!fileName || fileName === file.name) {
|
||||
console.log(`========== ${file.name} Start ==========`);
|
||||
console.log(file.content);
|
||||
console.log(`========== ${file.name} End ==========`);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async function writeResultToDisk(root, path) {
|
||||
const publisher = CodeGenerator.publishers.disk();
|
||||
|
||||
return publisher.publish({
|
||||
project: root,
|
||||
outputPath: path,
|
||||
projectSlug: 'demo-project',
|
||||
createProjectFolder: true,
|
||||
});
|
||||
}
|
||||
|
||||
function main() {
|
||||
const schemaJson = fs.readFileSync('./demo/sampleSchema.json', { encoding: 'utf8' });
|
||||
const createIceJsProjectBuilder = CodeGenerator.solutions.icejs;
|
||||
const builder = createIceJsProjectBuilder();
|
||||
|
||||
builder.generateProject(schemaJson).then(result => {
|
||||
displayResultInConsole(result);
|
||||
writeResultToDisk(result, 'output/lowcodeDemo').then(response =>
|
||||
console.log('Write to disk: ', JSON.stringify(response)),
|
||||
);
|
||||
return result;
|
||||
});
|
||||
}
|
||||
|
||||
main();
|
||||
243
packages/code-generator/demo/sampleSchema.json
Normal file
243
packages/code-generator/demo/sampleSchema.json
Normal file
@ -0,0 +1,243 @@
|
||||
{
|
||||
"version": "1.0.0",
|
||||
"componentsMap": [
|
||||
{
|
||||
"componentName": "Button",
|
||||
"package": "@alifd/next",
|
||||
"version": "1.19.18",
|
||||
"destructuring": true,
|
||||
"exportName": "Button"
|
||||
},
|
||||
{
|
||||
"componentName": "Button.Group",
|
||||
"package": "@alifd/next",
|
||||
"version": "1.19.18",
|
||||
"destructuring": true,
|
||||
"exportName": "Button",
|
||||
"subName": "Group"
|
||||
},
|
||||
{
|
||||
"componentName": "Input",
|
||||
"package": "@alifd/next",
|
||||
"version": "1.19.18",
|
||||
"destructuring": true,
|
||||
"exportName": "Input"
|
||||
},
|
||||
{
|
||||
"componentName": "Form",
|
||||
"package": "@alifd/next",
|
||||
"version": "1.19.18",
|
||||
"destructuring": true,
|
||||
"exportName": "Form"
|
||||
},
|
||||
{
|
||||
"componentName": "Form.Item",
|
||||
"package": "@alifd/next",
|
||||
"version": "1.19.18",
|
||||
"destructuring": true,
|
||||
"exportName": "Form",
|
||||
"subName": "Item"
|
||||
},
|
||||
{
|
||||
"componentName": "NumberPicker",
|
||||
"package": "@alifd/next",
|
||||
"version": "1.19.18",
|
||||
"destructuring": true,
|
||||
"exportName": "NumberPicker"
|
||||
},
|
||||
{
|
||||
"componentName": "Select",
|
||||
"package": "@alifd/next",
|
||||
"version": "1.19.18",
|
||||
"destructuring": true,
|
||||
"exportName": "Select"
|
||||
}
|
||||
],
|
||||
"componentsTree": [
|
||||
{
|
||||
"componentName": "Page",
|
||||
"id": "node$1",
|
||||
"meta": {
|
||||
"title": "测试",
|
||||
"router": "/"
|
||||
},
|
||||
"props": {
|
||||
"ref": "outterView",
|
||||
"autoLoading": true
|
||||
},
|
||||
"fileName": "test",
|
||||
"state": {
|
||||
"text": "outter"
|
||||
},
|
||||
"lifeCycles": {
|
||||
"componentDidMount": {
|
||||
"type": "JSExpression",
|
||||
"value": "function() { this.utils.request(this.props.url); }"
|
||||
}
|
||||
},
|
||||
"children": [
|
||||
{
|
||||
"componentName": "Form",
|
||||
"id": "node$2",
|
||||
"props": {
|
||||
"labelCol": {
|
||||
"type": "JSExpression",
|
||||
"value": "this.state.colNum"
|
||||
},
|
||||
"style": {},
|
||||
"ref": "testForm"
|
||||
},
|
||||
"children": [
|
||||
{
|
||||
"componentName": "Form.Item",
|
||||
"id": "node$3",
|
||||
"props": {
|
||||
"label": "姓名:",
|
||||
"name": "name",
|
||||
"initValue": "李雷"
|
||||
},
|
||||
"children": [
|
||||
{
|
||||
"componentName": "Input",
|
||||
"id": "node$4",
|
||||
"props": {
|
||||
"placeholder": "请输入",
|
||||
"size": "medium",
|
||||
"style": {
|
||||
"width": 320
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"componentName": "Form.Item",
|
||||
"id": "node$5",
|
||||
"props": {
|
||||
"label": "年龄:",
|
||||
"name": "age",
|
||||
"initValue": "22"
|
||||
},
|
||||
"children": [
|
||||
{
|
||||
"componentName": "NumberPicker",
|
||||
"id": "node$6",
|
||||
"props": {
|
||||
"size": "medium",
|
||||
"type": "normal"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"componentName": "Form.Item",
|
||||
"id": "node$7",
|
||||
"props": {
|
||||
"label": "职业:",
|
||||
"name": "profession"
|
||||
},
|
||||
"children": [
|
||||
{
|
||||
"componentName": "Select",
|
||||
"id": "node$8",
|
||||
"props": {
|
||||
"dataSource": [
|
||||
{
|
||||
"label": "教师",
|
||||
"value": "t"
|
||||
},
|
||||
{
|
||||
"label": "医生",
|
||||
"value": "d"
|
||||
},
|
||||
{
|
||||
"label": "歌手",
|
||||
"value": "s"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"componentName": "Div",
|
||||
"id": "node$9",
|
||||
"props": {
|
||||
"style": {
|
||||
"textAlign": "center"
|
||||
}
|
||||
},
|
||||
"children": [
|
||||
{
|
||||
"componentName": "Button.Group",
|
||||
"id": "node$a",
|
||||
"props": {},
|
||||
"children": [
|
||||
{
|
||||
"componentName": "Button",
|
||||
"id": "node$b",
|
||||
"props": {
|
||||
"type": "primary",
|
||||
"style": {
|
||||
"margin": "0 5px 0 5px"
|
||||
},
|
||||
"htmlType": "submit"
|
||||
},
|
||||
"children": [
|
||||
"提交"
|
||||
]
|
||||
},
|
||||
{
|
||||
"componentName": "Button",
|
||||
"id": "node$d",
|
||||
"props": {
|
||||
"type": "normal",
|
||||
"style": {
|
||||
"margin": "0 5px 0 5px"
|
||||
},
|
||||
"htmlType": "reset"
|
||||
},
|
||||
"children": [
|
||||
"重置"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"constants": {
|
||||
"ENV": "prod",
|
||||
"DOMAIN": "xxx.alibaba-inc.com"
|
||||
},
|
||||
"css": "body {font-size: 12px;} .table { width: 100px;}",
|
||||
"config": {
|
||||
"sdkVersion": "1.0.3",
|
||||
"historyMode": "hash",
|
||||
"targetRootID": "J_Container",
|
||||
"layout": {
|
||||
"componentName": "BasicLayout",
|
||||
"props": {
|
||||
"logo": "...",
|
||||
"name": "测试网站"
|
||||
}
|
||||
},
|
||||
"theme": {
|
||||
"package": "@alife/theme-fusion",
|
||||
"version": "^0.1.0",
|
||||
"primary": "#ff9966"
|
||||
}
|
||||
},
|
||||
"meta": {
|
||||
"name": "demo应用",
|
||||
"git_group": "appGroup",
|
||||
"project_name": "app_demo",
|
||||
"description": "这是一个测试应用",
|
||||
"spma": "spa23d",
|
||||
"creator": "月飞"
|
||||
}
|
||||
}
|
||||
@ -8,17 +8,24 @@
|
||||
],
|
||||
"scripts": {
|
||||
"build": "rimraf lib && tsc",
|
||||
"demo": "ts-node -r tsconfig-paths/register ./src/demo/main.ts",
|
||||
"test": "ava"
|
||||
"demo": "node ./demo/demo.js",
|
||||
"test": "ava",
|
||||
"template": "node ./tools/createTemplate.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@ali/am-eslint-config": "*",
|
||||
"@ali/my-prettier": "^1.0.0",
|
||||
"@babel/generator": "^7.9.5",
|
||||
"@babel/parser": "^7.9.4",
|
||||
"@babel/traverse": "^7.9.5",
|
||||
"@babel/types": "^7.9.5",
|
||||
"@types/prettier": "^1.19.1",
|
||||
"change-case": "^3.1.0",
|
||||
"prettier": "^2.0.2",
|
||||
"short-uuid": "^3.1.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/babel__traverse": "^7.0.10",
|
||||
"ava": "^1.0.1",
|
||||
"rimraf": "^3.0.2",
|
||||
"ts-loader": "^6.2.2",
|
||||
|
||||
6
packages/code-generator/src/@types/ali__my-prettier/index.d.ts
vendored
Normal file
6
packages/code-generator/src/@types/ali__my-prettier/index.d.ts
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
/// <reference types="node" />
|
||||
|
||||
declare module '@ali/my-prettier' {
|
||||
function format(text: string, type: string): string;
|
||||
export default format;
|
||||
}
|
||||
@ -8,6 +8,107 @@ export const COMMON_CHUNK_NAME = {
|
||||
StyleDepsImport: 'CommonStyleDepsImport',
|
||||
StyleCssContent: 'CommonStyleCssContent',
|
||||
HtmlContent: 'CommonHtmlContent',
|
||||
CustomContent: 'CommonCustomContent',
|
||||
};
|
||||
|
||||
export const CLASS_DEFINE_CHUNK_NAME = {
|
||||
Start: 'CommonClassDefineStart',
|
||||
ConstructorStart: 'CommonClassDefineConstructorStart',
|
||||
ConstructorContent: 'CommonClassDefineConstructorContent',
|
||||
ConstructorEnd: 'CommonClassDefineConstructorEnd',
|
||||
StaticVar: 'CommonClassDefineStaticVar',
|
||||
StaticMethod: 'CommonClassDefineStaticMethod',
|
||||
InsVar: 'CommonClassDefineInsVar',
|
||||
InsVarMethod: 'CommonClassDefineInsVarMethod',
|
||||
InsMethod: 'CommonClassDefineInsMethod',
|
||||
End: 'CommonClassDefineEnd',
|
||||
};
|
||||
|
||||
export const DEFAULT_LINK_AFTER = {
|
||||
[COMMON_CHUNK_NAME.ExternalDepsImport]: [],
|
||||
[COMMON_CHUNK_NAME.InternalDepsImport]: [COMMON_CHUNK_NAME.ExternalDepsImport],
|
||||
[COMMON_CHUNK_NAME.FileVarDefine]: [
|
||||
COMMON_CHUNK_NAME.ExternalDepsImport,
|
||||
COMMON_CHUNK_NAME.InternalDepsImport,
|
||||
],
|
||||
[COMMON_CHUNK_NAME.FileUtilDefine]: [
|
||||
COMMON_CHUNK_NAME.ExternalDepsImport,
|
||||
COMMON_CHUNK_NAME.InternalDepsImport,
|
||||
COMMON_CHUNK_NAME.FileVarDefine,
|
||||
],
|
||||
[CLASS_DEFINE_CHUNK_NAME.Start]: [
|
||||
COMMON_CHUNK_NAME.ExternalDepsImport,
|
||||
COMMON_CHUNK_NAME.InternalDepsImport,
|
||||
COMMON_CHUNK_NAME.FileVarDefine,
|
||||
COMMON_CHUNK_NAME.FileUtilDefine,
|
||||
],
|
||||
[CLASS_DEFINE_CHUNK_NAME.ConstructorStart]: [
|
||||
CLASS_DEFINE_CHUNK_NAME.Start,
|
||||
CLASS_DEFINE_CHUNK_NAME.StaticVar,
|
||||
CLASS_DEFINE_CHUNK_NAME.StaticMethod,
|
||||
CLASS_DEFINE_CHUNK_NAME.InsVar,
|
||||
CLASS_DEFINE_CHUNK_NAME.InsVarMethod,
|
||||
],
|
||||
[CLASS_DEFINE_CHUNK_NAME.ConstructorContent]: [
|
||||
CLASS_DEFINE_CHUNK_NAME.ConstructorStart,
|
||||
],
|
||||
[CLASS_DEFINE_CHUNK_NAME.ConstructorEnd]: [
|
||||
CLASS_DEFINE_CHUNK_NAME.ConstructorStart,
|
||||
CLASS_DEFINE_CHUNK_NAME.ConstructorContent,
|
||||
],
|
||||
[CLASS_DEFINE_CHUNK_NAME.StaticVar]: [
|
||||
CLASS_DEFINE_CHUNK_NAME.Start,
|
||||
],
|
||||
[CLASS_DEFINE_CHUNK_NAME.StaticMethod]: [
|
||||
CLASS_DEFINE_CHUNK_NAME.Start,
|
||||
CLASS_DEFINE_CHUNK_NAME.StaticVar,
|
||||
],
|
||||
[CLASS_DEFINE_CHUNK_NAME.InsVar]: [
|
||||
CLASS_DEFINE_CHUNK_NAME.Start,
|
||||
CLASS_DEFINE_CHUNK_NAME.StaticVar,
|
||||
CLASS_DEFINE_CHUNK_NAME.StaticMethod,
|
||||
],
|
||||
[CLASS_DEFINE_CHUNK_NAME.InsVarMethod]: [
|
||||
CLASS_DEFINE_CHUNK_NAME.Start,
|
||||
CLASS_DEFINE_CHUNK_NAME.StaticVar,
|
||||
CLASS_DEFINE_CHUNK_NAME.StaticMethod,
|
||||
CLASS_DEFINE_CHUNK_NAME.InsVar,
|
||||
],
|
||||
[CLASS_DEFINE_CHUNK_NAME.InsMethod]: [
|
||||
CLASS_DEFINE_CHUNK_NAME.Start,
|
||||
CLASS_DEFINE_CHUNK_NAME.StaticVar,
|
||||
CLASS_DEFINE_CHUNK_NAME.StaticMethod,
|
||||
CLASS_DEFINE_CHUNK_NAME.InsVar,
|
||||
CLASS_DEFINE_CHUNK_NAME.InsVarMethod,
|
||||
CLASS_DEFINE_CHUNK_NAME.ConstructorEnd,
|
||||
],
|
||||
[CLASS_DEFINE_CHUNK_NAME.End]: [
|
||||
CLASS_DEFINE_CHUNK_NAME.Start,
|
||||
CLASS_DEFINE_CHUNK_NAME.StaticVar,
|
||||
CLASS_DEFINE_CHUNK_NAME.StaticMethod,
|
||||
CLASS_DEFINE_CHUNK_NAME.InsVar,
|
||||
CLASS_DEFINE_CHUNK_NAME.InsVarMethod,
|
||||
CLASS_DEFINE_CHUNK_NAME.InsMethod,
|
||||
CLASS_DEFINE_CHUNK_NAME.ConstructorEnd,
|
||||
],
|
||||
[COMMON_CHUNK_NAME.FileMainContent]: [
|
||||
COMMON_CHUNK_NAME.ExternalDepsImport,
|
||||
COMMON_CHUNK_NAME.InternalDepsImport,
|
||||
COMMON_CHUNK_NAME.FileVarDefine,
|
||||
COMMON_CHUNK_NAME.FileUtilDefine,
|
||||
CLASS_DEFINE_CHUNK_NAME.End,
|
||||
],
|
||||
[COMMON_CHUNK_NAME.FileExport]: [
|
||||
COMMON_CHUNK_NAME.ExternalDepsImport,
|
||||
COMMON_CHUNK_NAME.InternalDepsImport,
|
||||
COMMON_CHUNK_NAME.FileVarDefine,
|
||||
COMMON_CHUNK_NAME.FileUtilDefine,
|
||||
CLASS_DEFINE_CHUNK_NAME.End,
|
||||
COMMON_CHUNK_NAME.FileMainContent,
|
||||
],
|
||||
[COMMON_CHUNK_NAME.StyleDepsImport]: [],
|
||||
[COMMON_CHUNK_NAME.StyleCssContent]: [COMMON_CHUNK_NAME.StyleDepsImport],
|
||||
[COMMON_CHUNK_NAME.HtmlContent]: [],
|
||||
}
|
||||
|
||||
export const COMMON_SUB_MODULE_NAME = 'index';
|
||||
|
||||
@ -1,53 +0,0 @@
|
||||
import { IResultDir, IResultFile } from '../types';
|
||||
|
||||
import CodeGenerator from '../index';
|
||||
import { createDiskPublisher } from '../publisher/disk';
|
||||
import demoSchema from './simpleDemo';
|
||||
|
||||
function flatFiles(rootName: string | null, dir: IResultDir): IResultFile[] {
|
||||
const dirRoot: string = rootName ? `${rootName}/${dir.name}` : dir.name;
|
||||
const files: IResultFile[] = dir.files.map(file => ({
|
||||
name: `${dirRoot}/${file.name}.${file.ext}`,
|
||||
content: file.content,
|
||||
ext: '',
|
||||
}));
|
||||
const filesInSub = dir.dirs.map(subDir => flatFiles(`${dirRoot}`, subDir));
|
||||
const result: IResultFile[] = files.concat.apply(files, filesInSub);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
function displayResultInConsole(root: IResultDir, fileName?: string): void {
|
||||
const files = flatFiles('.', root);
|
||||
files.forEach(file => {
|
||||
if (!fileName || fileName === file.name) {
|
||||
console.log(`========== ${file.name} Start ==========`);
|
||||
console.log(file.content);
|
||||
console.log(`========== ${file.name} End ==========`);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async function writeResultToDisk(root: IResultDir, path: string): Promise<any> {
|
||||
const publisher = createDiskPublisher();
|
||||
|
||||
return publisher.publish({
|
||||
project: root,
|
||||
outputPath: path,
|
||||
projectSlug: 'demo-project',
|
||||
createProjectFolder: true,
|
||||
});
|
||||
}
|
||||
|
||||
function main() {
|
||||
const createIceJsProjectBuilder = CodeGenerator.solutions.icejs;
|
||||
const builder = createIceJsProjectBuilder();
|
||||
builder.generateProject(demoSchema).then(result => {
|
||||
// displayResultInConsole(result, '././src/routes.js');
|
||||
writeResultToDisk(result, '/Users/armslave/lowcodeDemo').then(response =>
|
||||
console.log('Write to disk: ', JSON.stringify(response)),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
main();
|
||||
@ -1,234 +0,0 @@
|
||||
import { IProjectSchema } from '../types';
|
||||
|
||||
const demoData: IProjectSchema = {
|
||||
version: '1.0.0',
|
||||
componentsMap: [
|
||||
{
|
||||
componentName: 'Button',
|
||||
package: '@alifd/next',
|
||||
version: '1.19.18',
|
||||
destructuring: true,
|
||||
exportName: 'Button',
|
||||
},
|
||||
{
|
||||
componentName: 'Button.Group',
|
||||
package: '@alifd/next',
|
||||
version: '1.19.18',
|
||||
destructuring: true,
|
||||
exportName: 'Button',
|
||||
subName: 'Group',
|
||||
},
|
||||
{
|
||||
componentName: 'Input',
|
||||
package: '@alifd/next',
|
||||
version: '1.19.18',
|
||||
destructuring: true,
|
||||
exportName: 'Input',
|
||||
},
|
||||
{
|
||||
componentName: 'Form',
|
||||
package: '@alifd/next',
|
||||
version: '1.19.18',
|
||||
destructuring: true,
|
||||
exportName: 'Form',
|
||||
},
|
||||
{
|
||||
componentName: 'Form.Item',
|
||||
package: '@alifd/next',
|
||||
version: '1.19.18',
|
||||
destructuring: true,
|
||||
exportName: 'Form',
|
||||
subName: 'Item',
|
||||
},
|
||||
{
|
||||
componentName: 'NumberPicker',
|
||||
package: '@alifd/next',
|
||||
version: '1.19.18',
|
||||
destructuring: true,
|
||||
exportName: 'NumberPicker',
|
||||
},
|
||||
{
|
||||
componentName: 'Select',
|
||||
package: '@alifd/next',
|
||||
version: '1.19.18',
|
||||
destructuring: true,
|
||||
exportName: 'Select',
|
||||
},
|
||||
],
|
||||
componentsTree: [
|
||||
{
|
||||
componentName: 'Page',
|
||||
id: 'node_1',
|
||||
meta: {
|
||||
title: '测试',
|
||||
router: '/',
|
||||
},
|
||||
props: {
|
||||
ref: 'outterView',
|
||||
autoLoading: true,
|
||||
},
|
||||
fileName: 'test',
|
||||
state: {
|
||||
text: 'outter',
|
||||
},
|
||||
children: [
|
||||
{
|
||||
componentName: 'Form',
|
||||
id: 'node_2',
|
||||
props: {
|
||||
labelCol: 4,
|
||||
style: {},
|
||||
ref: 'testForm',
|
||||
},
|
||||
children: [
|
||||
{
|
||||
componentName: 'Form.Item',
|
||||
id: 'node_3',
|
||||
props: {
|
||||
label: '姓名:',
|
||||
name: 'name',
|
||||
initValue: '李雷',
|
||||
},
|
||||
children: [
|
||||
{
|
||||
componentName: 'Input',
|
||||
id: 'node_4',
|
||||
props: {
|
||||
placeholder: '请输入',
|
||||
size: 'medium',
|
||||
style: {
|
||||
width: 320,
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
componentName: 'Form.Item',
|
||||
id: 'node_5',
|
||||
props: {
|
||||
label: '年龄:',
|
||||
name: 'age',
|
||||
initValue: '22',
|
||||
},
|
||||
children: [
|
||||
{
|
||||
componentName: 'NumberPicker',
|
||||
id: 'node_6',
|
||||
props: {
|
||||
size: 'medium',
|
||||
type: 'normal',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
componentName: 'Form.Item',
|
||||
id: 'node_7',
|
||||
props: {
|
||||
label: '职业:',
|
||||
name: 'profession',
|
||||
},
|
||||
children: [
|
||||
{
|
||||
componentName: 'Select',
|
||||
id: 'node_8',
|
||||
props: {
|
||||
dataSource: [
|
||||
{
|
||||
label: '教师',
|
||||
value: 't',
|
||||
},
|
||||
{
|
||||
label: '医生',
|
||||
value: 'd',
|
||||
},
|
||||
{
|
||||
label: '歌手',
|
||||
value: 's',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
componentName: 'Div',
|
||||
id: 'node_9',
|
||||
props: {
|
||||
style: {
|
||||
textAlign: 'center',
|
||||
},
|
||||
},
|
||||
children: [
|
||||
{
|
||||
componentName: 'Button.Group',
|
||||
id: 'node_a',
|
||||
props: {},
|
||||
children: [
|
||||
{
|
||||
componentName: 'Button',
|
||||
id: 'node_b',
|
||||
props: {
|
||||
type: 'primary',
|
||||
style: {
|
||||
margin: '0 5px 0 5px',
|
||||
},
|
||||
htmlType: 'submit',
|
||||
},
|
||||
children: ['提交'],
|
||||
},
|
||||
{
|
||||
componentName: 'Button',
|
||||
id: 'node_d',
|
||||
props: {
|
||||
type: 'normal',
|
||||
style: {
|
||||
margin: '0 5px 0 5px',
|
||||
},
|
||||
htmlType: 'reset',
|
||||
},
|
||||
children: ['重置'],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
constants: {
|
||||
ENV: 'prod',
|
||||
DOMAIN: 'xxx.alibaba-inc.com',
|
||||
},
|
||||
css: 'body {font-size: 12px;} .table { width: 100px;}',
|
||||
config: {
|
||||
sdkVersion: '1.0.3',
|
||||
historyMode: 'hash',
|
||||
targetRootID: 'J_Container',
|
||||
layout: {
|
||||
componentName: 'BasicLayout',
|
||||
props: {
|
||||
logo: '...',
|
||||
name: '测试网站',
|
||||
},
|
||||
},
|
||||
theme: {
|
||||
package: '@alife/theme-fusion',
|
||||
version: '^0.1.0',
|
||||
primary: '#ff9966',
|
||||
},
|
||||
},
|
||||
meta: {
|
||||
name: 'demo应用',
|
||||
git_group: 'appGroup',
|
||||
project_name: 'app_demo',
|
||||
description: '这是一个测试应用',
|
||||
spma: 'spa23d',
|
||||
creator: '月飞',
|
||||
},
|
||||
};
|
||||
|
||||
export default demoData;
|
||||
@ -62,10 +62,12 @@ export default class Builder implements ICodeBuilder {
|
||||
}
|
||||
|
||||
unprocessedChunks.splice(indexToRemove, 1);
|
||||
unprocessedChunks.forEach(
|
||||
// remove the processed chunk from all the linkAfter arrays from the remaining chunks
|
||||
ch => (ch.linkAfter = ch.linkAfter.filter(after => after !== name)),
|
||||
);
|
||||
if (!unprocessedChunks.some(ch => ch.name === name)) {
|
||||
unprocessedChunks.forEach(
|
||||
// remove the processed chunk from all the linkAfter arrays from the remaining chunks
|
||||
ch => (ch.linkAfter = ch.linkAfter.filter(after => after !== name)),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return resultingString.join('\n');
|
||||
|
||||
@ -1,18 +1,24 @@
|
||||
import {
|
||||
BuilderComponentPlugin,
|
||||
CodeGeneratorError,
|
||||
IBasicSchema,
|
||||
ICodeChunk,
|
||||
ICompiledModule,
|
||||
IModuleBuilder,
|
||||
IParseResult,
|
||||
IResultDir,
|
||||
IResultFile,
|
||||
ISchemaParser,
|
||||
PostProcessor,
|
||||
} from '../types';
|
||||
|
||||
import { COMMON_SUB_MODULE_NAME } from '../const/generator';
|
||||
|
||||
import SchemaParser from '../parser/SchemaParser';
|
||||
import ChunkBuilder from './ChunkBuilder';
|
||||
import CodeBuilder from './CodeBuilder';
|
||||
|
||||
import ResultDir from '../model/ResultDir';
|
||||
import ResultFile from '../model/ResultFile';
|
||||
|
||||
export function createModuleBuilder(
|
||||
@ -66,6 +72,20 @@ export function createModuleBuilder(
|
||||
};
|
||||
};
|
||||
|
||||
const generateModuleCode = async (schema: IBasicSchema | string): Promise<IResultDir> => {
|
||||
// Init
|
||||
const schemaParser: ISchemaParser = new SchemaParser();
|
||||
const parseResult: IParseResult = schemaParser.parse(schema);
|
||||
|
||||
const containerInfo = parseResult.containers[0];
|
||||
const { files } = await generateModule(containerInfo);
|
||||
|
||||
const dir = new ResultDir(containerInfo.moduleName);
|
||||
files.forEach(file => dir.addFile(file));
|
||||
|
||||
return dir;
|
||||
}
|
||||
|
||||
const linkCodeChunks = (
|
||||
chunks: Record<string, ICodeChunk[]>,
|
||||
fileName: string,
|
||||
@ -88,6 +108,7 @@ export function createModuleBuilder(
|
||||
|
||||
return {
|
||||
generateModule,
|
||||
generateModuleCode,
|
||||
linkCodeChunks,
|
||||
addPlugin: chunkGenerator.addPlugin.bind(chunkGenerator),
|
||||
};
|
||||
|
||||
@ -57,8 +57,8 @@ export class ProjectBuilder implements IProjectBuilder {
|
||||
this.postProcessors = postProcessors;
|
||||
}
|
||||
|
||||
public async generateProject(schema: IProjectSchema): Promise<IResultDir> {
|
||||
// Init working parts
|
||||
public async generateProject(schema: IProjectSchema | string): Promise<IResultDir> {
|
||||
// Init
|
||||
const schemaParser: ISchemaParser = new SchemaParser();
|
||||
const builders = this.createModuleBuilders();
|
||||
const projectRoot = this.template.generateTemplate();
|
||||
@ -90,7 +90,7 @@ export class ProjectBuilder implements IProjectBuilder {
|
||||
const { files } = await builder.generateModule(containerInfo);
|
||||
|
||||
return {
|
||||
moduleName: containerInfo.fileName,
|
||||
moduleName: containerInfo.moduleName,
|
||||
path,
|
||||
files,
|
||||
};
|
||||
@ -215,61 +215,19 @@ export class ProjectBuilder implements IProjectBuilder {
|
||||
private createModuleBuilders(): Record<string, IModuleBuilder> {
|
||||
const builders: Record<string, IModuleBuilder> = {};
|
||||
|
||||
builders.components = createModuleBuilder({
|
||||
plugins: this.plugins.components,
|
||||
postProcessors: this.postProcessors,
|
||||
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) {
|
||||
options.mainFileName = this.template.slots[pluginName].fileName;
|
||||
}
|
||||
builders[pluginName] = createModuleBuilder({
|
||||
plugins: this.plugins[pluginName],
|
||||
postProcessors: this.postProcessors,
|
||||
...options,
|
||||
});
|
||||
}
|
||||
});
|
||||
builders.pages = createModuleBuilder({
|
||||
plugins: this.plugins.pages,
|
||||
postProcessors: this.postProcessors,
|
||||
});
|
||||
builders.router = createModuleBuilder({
|
||||
plugins: this.plugins.router,
|
||||
mainFileName: this.template.slots.router.fileName,
|
||||
postProcessors: this.postProcessors,
|
||||
});
|
||||
builders.entry = createModuleBuilder({
|
||||
plugins: this.plugins.entry,
|
||||
mainFileName: this.template.slots.entry.fileName,
|
||||
postProcessors: this.postProcessors,
|
||||
});
|
||||
builders.globalStyle = createModuleBuilder({
|
||||
plugins: this.plugins.globalStyle,
|
||||
mainFileName: this.template.slots.globalStyle.fileName,
|
||||
postProcessors: this.postProcessors,
|
||||
});
|
||||
builders.htmlEntry = createModuleBuilder({
|
||||
plugins: this.plugins.htmlEntry,
|
||||
mainFileName: this.template.slots.htmlEntry.fileName,
|
||||
postProcessors: this.postProcessors,
|
||||
});
|
||||
builders.packageJSON = createModuleBuilder({
|
||||
plugins: this.plugins.packageJSON,
|
||||
mainFileName: this.template.slots.packageJSON.fileName,
|
||||
postProcessors: this.postProcessors,
|
||||
});
|
||||
|
||||
if (this.template.slots.constants && this.plugins.constants) {
|
||||
builders.constants = createModuleBuilder({
|
||||
plugins: this.plugins.constants,
|
||||
mainFileName: this.template.slots.constants.fileName,
|
||||
postProcessors: this.postProcessors,
|
||||
});
|
||||
}
|
||||
if (this.template.slots.utils && this.plugins.utils) {
|
||||
builders.utils = createModuleBuilder({
|
||||
plugins: this.plugins.utils,
|
||||
mainFileName: this.template.slots.utils.fileName,
|
||||
postProcessors: this.postProcessors,
|
||||
});
|
||||
}
|
||||
if (this.template.slots.i18n && this.plugins.i18n) {
|
||||
builders.i18n = createModuleBuilder({
|
||||
plugins: this.plugins.i18n,
|
||||
mainFileName: this.template.slots.i18n.fileName,
|
||||
postProcessors: this.postProcessors,
|
||||
});
|
||||
}
|
||||
|
||||
return builders;
|
||||
}
|
||||
|
||||
@ -3,17 +3,78 @@
|
||||
*
|
||||
*/
|
||||
import { createProjectBuilder } from './generator/ProjectBuilder';
|
||||
import { createModuleBuilder } from './generator/ModuleBuilder';
|
||||
import { createDiskPublisher } from './publisher/disk';
|
||||
import createIceJsProjectBuilder from './solutions/icejs';
|
||||
import createRecoreProjectBuilder from './solutions/recore';
|
||||
|
||||
// 引入说明
|
||||
import { REACT_CHUNK_NAME } from './plugins/component/react/const';
|
||||
|
||||
// 引入通用插件组
|
||||
import esmodule from './plugins/common/esmodule';
|
||||
import requireUtils from './plugins/common/requireUtils';
|
||||
import containerClass from './plugins/component/react/containerClass';
|
||||
import containerDataSource from './plugins/component/react/containerDataSource';
|
||||
import containerInitState from './plugins/component/react/containerInitState';
|
||||
import containerInjectUtils from './plugins/component/react/containerInjectUtils';
|
||||
import containerLifeCycle from './plugins/component/react/containerLifeCycle';
|
||||
import containerMethod from './plugins/component/react/containerMethod';
|
||||
import jsx from './plugins/component/react/jsx';
|
||||
import reactCommonDeps from './plugins/component/react/reactCommonDeps';
|
||||
import css from './plugins/component/style/css';
|
||||
import constants from './plugins/project/constants';
|
||||
import i18n from './plugins/project/i18n';
|
||||
import utils from './plugins/project/utils';
|
||||
|
||||
// 引入常用工具
|
||||
import * as utilsCommon from './utils/common';
|
||||
import * as utilsCompositeType from './utils/compositeType';
|
||||
import * as utilsJsExpression from './utils/jsExpression';
|
||||
import * as utilsNodeToJSX from './utils/nodeToJSX';
|
||||
import * as utilsTemplateHelper from './utils/templateHelper';
|
||||
|
||||
export * from './types';
|
||||
|
||||
export default {
|
||||
createProjectBuilder,
|
||||
createModuleBuilder,
|
||||
solutions: {
|
||||
icejs: createIceJsProjectBuilder,
|
||||
recore: createRecoreProjectBuilder,
|
||||
},
|
||||
publishers: {
|
||||
disk: createDiskPublisher,
|
||||
},
|
||||
plugins: {
|
||||
common: {
|
||||
esmodule,
|
||||
requireUtils,
|
||||
},
|
||||
react: {
|
||||
containerClass,
|
||||
containerDataSource,
|
||||
containerInitState,
|
||||
containerInjectUtils,
|
||||
containerLifeCycle,
|
||||
containerMethod,
|
||||
jsx,
|
||||
reactCommonDeps,
|
||||
},
|
||||
style: {
|
||||
css,
|
||||
},
|
||||
project: {
|
||||
constants,
|
||||
i18n,
|
||||
utils,
|
||||
},
|
||||
},
|
||||
utils: {
|
||||
common: utilsCommon,
|
||||
compositeType: utilsCompositeType,
|
||||
jsExpression: utilsJsExpression,
|
||||
nodeToJSX: utilsNodeToJSX,
|
||||
templateHelper: utilsTemplateHelper,
|
||||
},
|
||||
};
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
|
||||
import { SUPPORT_SCHEMA_VERSION_LIST } from '../const';
|
||||
|
||||
import { handleChildren } from '../utils/children';
|
||||
import { handleChildren } from '../utils/nodeToJSX';
|
||||
|
||||
import {
|
||||
ChildNodeType,
|
||||
@ -28,7 +28,8 @@ import {
|
||||
|
||||
const defaultContainer: IContainerInfo = {
|
||||
containerType: 'Component',
|
||||
componentName: 'Index',
|
||||
componentName: 'Component',
|
||||
moduleName: 'Index',
|
||||
fileName: 'Index',
|
||||
css: '',
|
||||
props: {},
|
||||
@ -45,12 +46,23 @@ class SchemaParser implements ISchemaParser {
|
||||
return true;
|
||||
}
|
||||
|
||||
public parse(schema: IProjectSchema): IParseResult {
|
||||
public parse(schemaSrc: IProjectSchema | string): IParseResult {
|
||||
// TODO: collect utils depends in JSExpression
|
||||
const compDeps: Record<string, IExternalDependency> = {};
|
||||
const internalDeps: Record<string, IInternalDependency> = {};
|
||||
let utilsDeps: IExternalDependency[] = [];
|
||||
|
||||
let schema: IProjectSchema;
|
||||
if (typeof schemaSrc === 'string') {
|
||||
try {
|
||||
schema = JSON.parse(schemaSrc);
|
||||
} catch (error) {
|
||||
throw new CodeGeneratorError(`Parse schema failed: ${error.message || 'unknown reason'}`);
|
||||
}
|
||||
} else {
|
||||
schema = schemaSrc;
|
||||
}
|
||||
|
||||
// 解析三方组件依赖
|
||||
schema.componentsMap.forEach(info => {
|
||||
info.dependencyType = DependencyType.External;
|
||||
@ -78,7 +90,7 @@ class SchemaParser implements ISchemaParser {
|
||||
const container: IContainerInfo = {
|
||||
...subRoot,
|
||||
containerType: subRoot.componentName,
|
||||
componentName: subRoot.fileName,
|
||||
moduleName: subRoot.fileName, // TODO: 驼峰化名称
|
||||
};
|
||||
return container;
|
||||
});
|
||||
@ -104,9 +116,9 @@ class SchemaParser implements ISchemaParser {
|
||||
|
||||
const dep: IInternalDependency = {
|
||||
type,
|
||||
moduleName: container.componentName,
|
||||
moduleName: container.moduleName,
|
||||
destructuring: false,
|
||||
exportName: container.componentName,
|
||||
exportName: container.moduleName,
|
||||
dependencyType: DependencyType.Internal,
|
||||
};
|
||||
|
||||
@ -131,9 +143,15 @@ class SchemaParser implements ISchemaParser {
|
||||
.filter(container => container.containerType === 'Page')
|
||||
.map(page => {
|
||||
const meta = page.meta as IPageMeta;
|
||||
if (meta) {
|
||||
return {
|
||||
path: meta.router,
|
||||
componentName: page.moduleName,
|
||||
};
|
||||
}
|
||||
return {
|
||||
path: meta.router,
|
||||
componentName: page.componentName,
|
||||
path: '',
|
||||
componentName: page.moduleName,
|
||||
};
|
||||
});
|
||||
|
||||
|
||||
@ -2,6 +2,7 @@ import { COMMON_CHUNK_NAME } from '../../const/generator';
|
||||
|
||||
import {
|
||||
BuilderComponentPlugin,
|
||||
BuilderComponentPluginFactory,
|
||||
ChunkType,
|
||||
CodeGeneratorError,
|
||||
DependencyType,
|
||||
@ -41,7 +42,7 @@ function groupDepsByPack(deps: IDependency[]): Record<string, IDependency[]> {
|
||||
function buildPackageImport(
|
||||
pkg: string,
|
||||
deps: IDependency[],
|
||||
isJSX: boolean,
|
||||
targetFileType: string,
|
||||
): ICodeChunk[] {
|
||||
const chunks: ICodeChunk[] = [];
|
||||
let defaultImport: string = '';
|
||||
@ -58,7 +59,7 @@ function buildPackageImport(
|
||||
if (dep.subName) {
|
||||
chunks.push({
|
||||
type: ChunkType.STRING,
|
||||
fileType: isJSX ? FileType.JSX : FileType.JS,
|
||||
fileType: targetFileType,
|
||||
name: COMMON_CHUNK_NAME.FileVarDefine,
|
||||
content: `const ${targetName} = ${srcName}.${dep.subName};`,
|
||||
linkAfter: [
|
||||
@ -103,7 +104,7 @@ function buildPackageImport(
|
||||
statementL.push(`'@/${(deps[0] as IInternalDependency).type}/${pkg}';`);
|
||||
chunks.push({
|
||||
type: ChunkType.STRING,
|
||||
fileType: isJSX ? FileType.JSX : FileType.JS,
|
||||
fileType: targetFileType,
|
||||
name: COMMON_CHUNK_NAME.InternalDepsImport,
|
||||
content: statementL.join(' '),
|
||||
linkAfter: [COMMON_CHUNK_NAME.ExternalDepsImport],
|
||||
@ -112,7 +113,7 @@ function buildPackageImport(
|
||||
statementL.push(`'${pkg}';`);
|
||||
chunks.push({
|
||||
type: ChunkType.STRING,
|
||||
fileType: isJSX ? FileType.JSX : FileType.JS,
|
||||
fileType: targetFileType,
|
||||
name: COMMON_CHUNK_NAME.ExternalDepsImport,
|
||||
content: statementL.join(' '),
|
||||
linkAfter: [],
|
||||
@ -122,25 +123,36 @@ function buildPackageImport(
|
||||
return chunks;
|
||||
}
|
||||
|
||||
const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => {
|
||||
const next: ICodeStruct = {
|
||||
...pre,
|
||||
type PluginConfig = {
|
||||
fileType: string;
|
||||
}
|
||||
|
||||
const pluginFactory: BuilderComponentPluginFactory<PluginConfig> = (config?: PluginConfig) => {
|
||||
const cfg: PluginConfig = {
|
||||
fileType: FileType.JS,
|
||||
...config,
|
||||
};
|
||||
|
||||
const isJSX = next.chunks.some(chunk => chunk.fileType === FileType.JSX);
|
||||
const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => {
|
||||
const next: ICodeStruct = {
|
||||
...pre,
|
||||
};
|
||||
|
||||
const ir = next.ir as IWithDependency;
|
||||
const ir = next.ir as IWithDependency;
|
||||
|
||||
if (ir && ir.deps && ir.deps.length > 0) {
|
||||
const packs = groupDepsByPack(ir.deps);
|
||||
if (ir && ir.deps && ir.deps.length > 0) {
|
||||
const packs = groupDepsByPack(ir.deps);
|
||||
|
||||
Object.keys(packs).forEach(pkg => {
|
||||
const chunks = buildPackageImport(pkg, packs[pkg], isJSX);
|
||||
next.chunks.push.apply(next.chunks, chunks);
|
||||
});
|
||||
}
|
||||
Object.keys(packs).forEach(pkg => {
|
||||
const chunks = buildPackageImport(pkg, packs[pkg], cfg.fileType);
|
||||
next.chunks.push.apply(next.chunks, chunks);
|
||||
});
|
||||
}
|
||||
|
||||
return next;
|
||||
return next;
|
||||
};
|
||||
|
||||
return plugin;
|
||||
};
|
||||
|
||||
export default plugin;
|
||||
export default pluginFactory;
|
||||
|
||||
@ -2,26 +2,30 @@ import { COMMON_CHUNK_NAME } from '../../const/generator';
|
||||
|
||||
import {
|
||||
BuilderComponentPlugin,
|
||||
BuilderComponentPluginFactory,
|
||||
ChunkType,
|
||||
FileType,
|
||||
ICodeStruct,
|
||||
} from '../../types';
|
||||
|
||||
// TODO: How to merge this logic to common deps
|
||||
const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => {
|
||||
const next: ICodeStruct = {
|
||||
...pre,
|
||||
const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
|
||||
const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => {
|
||||
const next: ICodeStruct = {
|
||||
...pre,
|
||||
};
|
||||
|
||||
next.chunks.push({
|
||||
type: ChunkType.STRING,
|
||||
fileType: FileType.JSX,
|
||||
name: COMMON_CHUNK_NAME.InternalDepsImport,
|
||||
content: `import * from 'react';`,
|
||||
linkAfter: [],
|
||||
});
|
||||
|
||||
return next;
|
||||
};
|
||||
|
||||
next.chunks.push({
|
||||
type: ChunkType.STRING,
|
||||
fileType: FileType.JSX,
|
||||
name: COMMON_CHUNK_NAME.InternalDepsImport,
|
||||
content: `import * from 'react';`,
|
||||
linkAfter: [],
|
||||
});
|
||||
|
||||
return next;
|
||||
return plugin;
|
||||
};
|
||||
|
||||
export default plugin;
|
||||
export default pluginFactory;
|
||||
|
||||
@ -1,15 +1,8 @@
|
||||
export const REACT_CHUNK_NAME = {
|
||||
ClassStart: 'ReactComponentClassDefineStart',
|
||||
ClassEnd: 'ReactComponentClassDefineEnd',
|
||||
ClassLifeCycle: 'ReactComponentClassMemberLifeCycle',
|
||||
ClassMethod: 'ReactComponentClassMemberMethod',
|
||||
ClassRenderStart: 'ReactComponentClassRenderStart',
|
||||
ClassRenderPre: 'ReactComponentClassRenderPre',
|
||||
ClassRenderEnd: 'ReactComponentClassRenderEnd',
|
||||
ClassRenderJSX: 'ReactComponentClassRenderJSX',
|
||||
ClassConstructorStart: 'ReactComponentClassConstructorStart',
|
||||
ClassConstructorEnd: 'ReactComponentClassConstructorEnd',
|
||||
ClassConstructorContent: 'ReactComponentClassConstructorContent',
|
||||
ClassDidMountStart: 'ReactComponentClassDidMountStart',
|
||||
ClassDidMountEnd: 'ReactComponentClassDidMountEnd',
|
||||
ClassDidMountContent: 'ReactComponentClassDidMountContent',
|
||||
|
||||
@ -1,101 +1,104 @@
|
||||
import { COMMON_CHUNK_NAME } from '../../../const/generator';
|
||||
import { COMMON_CHUNK_NAME, CLASS_DEFINE_CHUNK_NAME } from '../../../const/generator';
|
||||
import { REACT_CHUNK_NAME } from './const';
|
||||
|
||||
import {
|
||||
BuilderComponentPlugin,
|
||||
BuilderComponentPluginFactory,
|
||||
ChunkType,
|
||||
FileType,
|
||||
ICodeStruct,
|
||||
IContainerInfo,
|
||||
} from '../../../types';
|
||||
|
||||
const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => {
|
||||
const next: ICodeStruct = {
|
||||
...pre,
|
||||
const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
|
||||
const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => {
|
||||
const next: ICodeStruct = {
|
||||
...pre,
|
||||
};
|
||||
|
||||
const ir = next.ir as IContainerInfo;
|
||||
|
||||
next.chunks.push({
|
||||
type: ChunkType.STRING,
|
||||
fileType: FileType.JSX,
|
||||
name: CLASS_DEFINE_CHUNK_NAME.Start,
|
||||
content: `class ${ir.moduleName} extends React.Component {`,
|
||||
linkAfter: [
|
||||
COMMON_CHUNK_NAME.ExternalDepsImport,
|
||||
COMMON_CHUNK_NAME.InternalDepsImport,
|
||||
COMMON_CHUNK_NAME.FileVarDefine,
|
||||
COMMON_CHUNK_NAME.FileUtilDefine,
|
||||
],
|
||||
});
|
||||
|
||||
next.chunks.push({
|
||||
type: ChunkType.STRING,
|
||||
fileType: FileType.JSX,
|
||||
name: CLASS_DEFINE_CHUNK_NAME.End,
|
||||
content: `}`,
|
||||
linkAfter: [CLASS_DEFINE_CHUNK_NAME.Start, REACT_CHUNK_NAME.ClassRenderEnd],
|
||||
});
|
||||
|
||||
next.chunks.push({
|
||||
type: ChunkType.STRING,
|
||||
fileType: FileType.JSX,
|
||||
name: CLASS_DEFINE_CHUNK_NAME.ConstructorStart,
|
||||
content: 'constructor(props, context) { super(props); ',
|
||||
linkAfter: [CLASS_DEFINE_CHUNK_NAME.Start],
|
||||
});
|
||||
|
||||
next.chunks.push({
|
||||
type: ChunkType.STRING,
|
||||
fileType: FileType.JSX,
|
||||
name: CLASS_DEFINE_CHUNK_NAME.ConstructorEnd,
|
||||
content: '}',
|
||||
linkAfter: [
|
||||
CLASS_DEFINE_CHUNK_NAME.ConstructorStart,
|
||||
CLASS_DEFINE_CHUNK_NAME.ConstructorContent,
|
||||
],
|
||||
});
|
||||
|
||||
next.chunks.push({
|
||||
type: ChunkType.STRING,
|
||||
fileType: FileType.JSX,
|
||||
name: REACT_CHUNK_NAME.ClassRenderStart,
|
||||
content: 'render() {',
|
||||
linkAfter: [
|
||||
CLASS_DEFINE_CHUNK_NAME.Start,
|
||||
CLASS_DEFINE_CHUNK_NAME.ConstructorEnd,
|
||||
CLASS_DEFINE_CHUNK_NAME.InsMethod,
|
||||
],
|
||||
});
|
||||
|
||||
next.chunks.push({
|
||||
type: ChunkType.STRING,
|
||||
fileType: FileType.JSX,
|
||||
name: REACT_CHUNK_NAME.ClassRenderEnd,
|
||||
content: '}',
|
||||
linkAfter: [
|
||||
REACT_CHUNK_NAME.ClassRenderStart,
|
||||
REACT_CHUNK_NAME.ClassRenderPre,
|
||||
REACT_CHUNK_NAME.ClassRenderJSX,
|
||||
],
|
||||
});
|
||||
|
||||
next.chunks.push({
|
||||
type: ChunkType.STRING,
|
||||
fileType: FileType.JSX,
|
||||
name: COMMON_CHUNK_NAME.FileExport,
|
||||
content: `export default ${ir.moduleName};`,
|
||||
linkAfter: [
|
||||
COMMON_CHUNK_NAME.ExternalDepsImport,
|
||||
COMMON_CHUNK_NAME.InternalDepsImport,
|
||||
COMMON_CHUNK_NAME.FileVarDefine,
|
||||
COMMON_CHUNK_NAME.FileUtilDefine,
|
||||
CLASS_DEFINE_CHUNK_NAME.End,
|
||||
],
|
||||
});
|
||||
|
||||
return next;
|
||||
};
|
||||
|
||||
const ir = next.ir as IContainerInfo;
|
||||
|
||||
next.chunks.push({
|
||||
type: ChunkType.STRING,
|
||||
fileType: FileType.JSX,
|
||||
name: REACT_CHUNK_NAME.ClassStart,
|
||||
content: `class ${ir.componentName} extends React.Component {`,
|
||||
linkAfter: [
|
||||
COMMON_CHUNK_NAME.ExternalDepsImport,
|
||||
COMMON_CHUNK_NAME.InternalDepsImport,
|
||||
COMMON_CHUNK_NAME.FileVarDefine,
|
||||
COMMON_CHUNK_NAME.FileUtilDefine,
|
||||
],
|
||||
});
|
||||
|
||||
next.chunks.push({
|
||||
type: ChunkType.STRING,
|
||||
fileType: FileType.JSX,
|
||||
name: REACT_CHUNK_NAME.ClassEnd,
|
||||
content: `}`,
|
||||
linkAfter: [REACT_CHUNK_NAME.ClassStart, REACT_CHUNK_NAME.ClassRenderEnd],
|
||||
});
|
||||
|
||||
next.chunks.push({
|
||||
type: ChunkType.STRING,
|
||||
fileType: FileType.JSX,
|
||||
name: REACT_CHUNK_NAME.ClassConstructorStart,
|
||||
content: 'constructor(props, context) { super(props); ',
|
||||
linkAfter: [REACT_CHUNK_NAME.ClassStart],
|
||||
});
|
||||
|
||||
next.chunks.push({
|
||||
type: ChunkType.STRING,
|
||||
fileType: FileType.JSX,
|
||||
name: REACT_CHUNK_NAME.ClassConstructorEnd,
|
||||
content: '}',
|
||||
linkAfter: [
|
||||
REACT_CHUNK_NAME.ClassConstructorStart,
|
||||
REACT_CHUNK_NAME.ClassConstructorContent,
|
||||
],
|
||||
});
|
||||
|
||||
next.chunks.push({
|
||||
type: ChunkType.STRING,
|
||||
fileType: FileType.JSX,
|
||||
name: REACT_CHUNK_NAME.ClassRenderStart,
|
||||
content: 'render() {',
|
||||
linkAfter: [
|
||||
REACT_CHUNK_NAME.ClassStart,
|
||||
REACT_CHUNK_NAME.ClassConstructorEnd,
|
||||
REACT_CHUNK_NAME.ClassLifeCycle,
|
||||
REACT_CHUNK_NAME.ClassMethod,
|
||||
],
|
||||
});
|
||||
|
||||
next.chunks.push({
|
||||
type: ChunkType.STRING,
|
||||
fileType: FileType.JSX,
|
||||
name: REACT_CHUNK_NAME.ClassRenderEnd,
|
||||
content: '}',
|
||||
linkAfter: [
|
||||
REACT_CHUNK_NAME.ClassRenderStart,
|
||||
REACT_CHUNK_NAME.ClassRenderPre,
|
||||
REACT_CHUNK_NAME.ClassRenderJSX,
|
||||
],
|
||||
});
|
||||
|
||||
next.chunks.push({
|
||||
type: ChunkType.STRING,
|
||||
fileType: FileType.JSX,
|
||||
name: COMMON_CHUNK_NAME.FileExport,
|
||||
content: `export default ${ir.componentName};`,
|
||||
linkAfter: [
|
||||
COMMON_CHUNK_NAME.ExternalDepsImport,
|
||||
COMMON_CHUNK_NAME.InternalDepsImport,
|
||||
COMMON_CHUNK_NAME.FileVarDefine,
|
||||
COMMON_CHUNK_NAME.FileUtilDefine,
|
||||
REACT_CHUNK_NAME.ClassEnd,
|
||||
],
|
||||
});
|
||||
|
||||
return next;
|
||||
return plugin;
|
||||
};
|
||||
|
||||
export default plugin;
|
||||
export default pluginFactory;
|
||||
|
||||
@ -1,39 +1,52 @@
|
||||
import { REACT_CHUNK_NAME } from './const';
|
||||
import { CLASS_DEFINE_CHUNK_NAME } from '../../../const/generator';
|
||||
|
||||
import { generateCompositeType } from '../../utils/compositeType';
|
||||
import { generateCompositeType } from '../../../utils/compositeType';
|
||||
|
||||
import {
|
||||
BuilderComponentPlugin,
|
||||
BuilderComponentPluginFactory,
|
||||
ChunkType,
|
||||
FileType,
|
||||
ICodeStruct,
|
||||
IContainerInfo,
|
||||
} from '../../../types';
|
||||
|
||||
const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => {
|
||||
const next: ICodeStruct = {
|
||||
...pre,
|
||||
type PluginConfig = {
|
||||
fileType: string;
|
||||
}
|
||||
|
||||
const pluginFactory: BuilderComponentPluginFactory<PluginConfig> = (config?) => {
|
||||
const cfg: PluginConfig = {
|
||||
fileType: FileType.JSX,
|
||||
...config,
|
||||
};
|
||||
|
||||
const ir = next.ir as IContainerInfo;
|
||||
const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => {
|
||||
const next: ICodeStruct = {
|
||||
...pre,
|
||||
};
|
||||
|
||||
if (ir.state) {
|
||||
const state = ir.state;
|
||||
const fields = Object.keys(state).map<string>(stateName => {
|
||||
const [isString, value] = generateCompositeType(state[stateName]);
|
||||
return `${stateName}: ${isString ? `'${value}'` : value},`;
|
||||
});
|
||||
const ir = next.ir as IContainerInfo;
|
||||
|
||||
next.chunks.push({
|
||||
type: ChunkType.STRING,
|
||||
fileType: FileType.JSX,
|
||||
name: REACT_CHUNK_NAME.ClassConstructorContent,
|
||||
content: `this.state = { ${fields.join('')} };`,
|
||||
linkAfter: [REACT_CHUNK_NAME.ClassConstructorStart],
|
||||
});
|
||||
}
|
||||
if (ir.state) {
|
||||
const state = ir.state;
|
||||
const fields = Object.keys(state).map<string>(stateName => {
|
||||
const [isString, value] = generateCompositeType(state[stateName]);
|
||||
return `${stateName}: ${isString ? `'${value}'` : value},`;
|
||||
});
|
||||
|
||||
return next;
|
||||
next.chunks.push({
|
||||
type: ChunkType.STRING,
|
||||
fileType: cfg.fileType,
|
||||
name: CLASS_DEFINE_CHUNK_NAME.ConstructorContent,
|
||||
content: `this.state = { ${fields.join('')} };`,
|
||||
linkAfter: [CLASS_DEFINE_CHUNK_NAME.ConstructorStart],
|
||||
});
|
||||
}
|
||||
|
||||
return next;
|
||||
};
|
||||
return plugin;
|
||||
};
|
||||
|
||||
export default plugin;
|
||||
export default pluginFactory;
|
||||
|
||||
@ -1,39 +1,64 @@
|
||||
import { REACT_CHUNK_NAME } from './const';
|
||||
import { CLASS_DEFINE_CHUNK_NAME, DEFAULT_LINK_AFTER } from '../../../const/generator';
|
||||
|
||||
import { generateCompositeType } from '../../utils/compositeType';
|
||||
import { generateCompositeType } from '../../../utils/compositeType';
|
||||
|
||||
import {
|
||||
BuilderComponentPlugin,
|
||||
BuilderComponentPluginFactory,
|
||||
ChunkType,
|
||||
FileType,
|
||||
ICodeStruct,
|
||||
IContainerInfo,
|
||||
} from '../../../types';
|
||||
|
||||
const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => {
|
||||
const next: ICodeStruct = {
|
||||
...pre,
|
||||
type PluginConfig = {
|
||||
fileType: string;
|
||||
implementType: 'inConstructor' | 'insMember' | 'hooks';
|
||||
}
|
||||
|
||||
const pluginFactory: BuilderComponentPluginFactory<PluginConfig> = (config?) => {
|
||||
const cfg: PluginConfig = {
|
||||
fileType: FileType.JSX,
|
||||
implementType: 'inConstructor',
|
||||
...config,
|
||||
};
|
||||
|
||||
const ir = next.ir as IContainerInfo;
|
||||
const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => {
|
||||
const next: ICodeStruct = {
|
||||
...pre,
|
||||
};
|
||||
|
||||
if (ir.state) {
|
||||
const state = ir.state;
|
||||
const fields = Object.keys(state).map<string>(stateName => {
|
||||
const [isString, value] = generateCompositeType(state[stateName]);
|
||||
return `${stateName}: ${isString ? `'${value}'` : value},`;
|
||||
});
|
||||
const ir = next.ir as IContainerInfo;
|
||||
|
||||
next.chunks.push({
|
||||
type: ChunkType.STRING,
|
||||
fileType: FileType.JSX,
|
||||
name: REACT_CHUNK_NAME.ClassConstructorContent,
|
||||
content: `this.state = { ${fields.join('')} };`,
|
||||
linkAfter: [REACT_CHUNK_NAME.ClassConstructorStart],
|
||||
});
|
||||
}
|
||||
if (ir.state) {
|
||||
const state = ir.state;
|
||||
const fields = Object.keys(state).map<string>(stateName => {
|
||||
const [isString, value] = generateCompositeType(state[stateName]);
|
||||
return `${stateName}: ${isString ? `'${value}'` : value},`;
|
||||
});
|
||||
|
||||
return next;
|
||||
if (cfg.implementType === 'inConstructor') {
|
||||
next.chunks.push({
|
||||
type: ChunkType.STRING,
|
||||
fileType: cfg.fileType,
|
||||
name: CLASS_DEFINE_CHUNK_NAME.ConstructorContent,
|
||||
content: `this.state = { ${fields.join('')} };`,
|
||||
linkAfter: [...DEFAULT_LINK_AFTER[CLASS_DEFINE_CHUNK_NAME.ConstructorContent]],
|
||||
});
|
||||
} else if (cfg.implementType === 'insMember') {
|
||||
next.chunks.push({
|
||||
type: ChunkType.STRING,
|
||||
fileType: cfg.fileType,
|
||||
name: CLASS_DEFINE_CHUNK_NAME.InsVar,
|
||||
content: `state = { ${fields.join('')} };`,
|
||||
linkAfter: [...DEFAULT_LINK_AFTER[CLASS_DEFINE_CHUNK_NAME.InsVar]],
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return next;
|
||||
};
|
||||
return plugin;
|
||||
};
|
||||
|
||||
export default plugin;
|
||||
export default pluginFactory;
|
||||
|
||||
@ -1,26 +1,39 @@
|
||||
import { REACT_CHUNK_NAME } from './const';
|
||||
import { CLASS_DEFINE_CHUNK_NAME } from '../../../const/generator';
|
||||
|
||||
import {
|
||||
BuilderComponentPlugin,
|
||||
BuilderComponentPluginFactory,
|
||||
ChunkType,
|
||||
FileType,
|
||||
ICodeStruct,
|
||||
} from '../../../types';
|
||||
|
||||
const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => {
|
||||
const next: ICodeStruct = {
|
||||
...pre,
|
||||
type PluginConfig = {
|
||||
fileType: string;
|
||||
}
|
||||
|
||||
const pluginFactory: BuilderComponentPluginFactory<PluginConfig> = (config?) => {
|
||||
const cfg: PluginConfig = {
|
||||
fileType: FileType.JSX,
|
||||
...config,
|
||||
};
|
||||
|
||||
next.chunks.push({
|
||||
type: ChunkType.STRING,
|
||||
fileType: FileType.JSX,
|
||||
name: REACT_CHUNK_NAME.ClassConstructorContent,
|
||||
content: `this.utils = utils;`,
|
||||
linkAfter: [REACT_CHUNK_NAME.ClassConstructorStart],
|
||||
});
|
||||
const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => {
|
||||
const next: ICodeStruct = {
|
||||
...pre,
|
||||
};
|
||||
|
||||
return next;
|
||||
next.chunks.push({
|
||||
type: ChunkType.STRING,
|
||||
fileType: cfg.fileType,
|
||||
name: CLASS_DEFINE_CHUNK_NAME.ConstructorContent,
|
||||
content: `this.utils = utils;`,
|
||||
linkAfter: [CLASS_DEFINE_CHUNK_NAME.ConstructorStart],
|
||||
});
|
||||
|
||||
return next;
|
||||
};
|
||||
return plugin;
|
||||
};
|
||||
|
||||
export default plugin;
|
||||
export default pluginFactory;
|
||||
|
||||
@ -1,12 +1,14 @@
|
||||
import { CLASS_DEFINE_CHUNK_NAME, DEFAULT_LINK_AFTER } from '../../../const/generator';
|
||||
import { REACT_CHUNK_NAME } from './const';
|
||||
|
||||
import {
|
||||
getFuncExprBody,
|
||||
transformFuncExpr2MethodMember,
|
||||
} from '../../utils/jsExpression';
|
||||
} from '../../../utils/jsExpression';
|
||||
|
||||
import {
|
||||
BuilderComponentPlugin,
|
||||
BuilderComponentPluginFactory,
|
||||
ChunkType,
|
||||
CodeGeneratorError,
|
||||
FileType,
|
||||
@ -16,66 +18,73 @@ import {
|
||||
IJSExpression,
|
||||
} from '../../../types';
|
||||
|
||||
const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => {
|
||||
const next: ICodeStruct = {
|
||||
...pre,
|
||||
type PluginConfig = {
|
||||
fileType: string;
|
||||
exportNameMapping: Record<string, string>;
|
||||
normalizeNameMapping: Record<string, string>;
|
||||
}
|
||||
|
||||
const pluginFactory: BuilderComponentPluginFactory<PluginConfig> = (config?) => {
|
||||
const cfg: PluginConfig = {
|
||||
fileType: FileType.JSX,
|
||||
exportNameMapping: {},
|
||||
normalizeNameMapping: {},
|
||||
...config,
|
||||
};
|
||||
|
||||
const ir = next.ir as IContainerInfo;
|
||||
const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => {
|
||||
const next: ICodeStruct = {
|
||||
...pre,
|
||||
};
|
||||
|
||||
const ir = next.ir as IContainerInfo;
|
||||
|
||||
if (ir.lifeCycles) {
|
||||
const lifeCycles = ir.lifeCycles;
|
||||
const chunks = Object.keys(lifeCycles).map<ICodeChunk>(lifeCycleName => {
|
||||
const normalizeName = cfg.normalizeNameMapping[lifeCycleName] || lifeCycleName;
|
||||
const exportName = cfg.exportNameMapping[lifeCycleName] || lifeCycleName;
|
||||
if (normalizeName === 'constructor') {
|
||||
return {
|
||||
type: ChunkType.STRING,
|
||||
fileType: cfg.fileType,
|
||||
name: CLASS_DEFINE_CHUNK_NAME.ConstructorContent,
|
||||
content: getFuncExprBody(
|
||||
(lifeCycles[lifeCycleName] as IJSExpression).value,
|
||||
),
|
||||
linkAfter: [...DEFAULT_LINK_AFTER[CLASS_DEFINE_CHUNK_NAME.ConstructorStart]],
|
||||
};
|
||||
}
|
||||
if (normalizeName === 'render') {
|
||||
return {
|
||||
type: ChunkType.STRING,
|
||||
fileType: cfg.fileType,
|
||||
name: REACT_CHUNK_NAME.ClassRenderPre,
|
||||
content: getFuncExprBody(
|
||||
(lifeCycles[lifeCycleName] as IJSExpression).value,
|
||||
),
|
||||
linkAfter: [REACT_CHUNK_NAME.ClassRenderStart],
|
||||
};
|
||||
}
|
||||
|
||||
if (ir.lifeCycles) {
|
||||
const lifeCycles = ir.lifeCycles;
|
||||
const chunks = Object.keys(lifeCycles).map<ICodeChunk>(lifeCycleName => {
|
||||
if (lifeCycleName === 'constructor') {
|
||||
return {
|
||||
type: ChunkType.STRING,
|
||||
fileType: FileType.JSX,
|
||||
name: REACT_CHUNK_NAME.ClassConstructorContent,
|
||||
content: getFuncExprBody(
|
||||
(lifeCycles[lifeCycleName] as IJSExpression).value,
|
||||
),
|
||||
linkAfter: [REACT_CHUNK_NAME.ClassConstructorStart],
|
||||
};
|
||||
}
|
||||
if (lifeCycleName === 'render') {
|
||||
return {
|
||||
type: ChunkType.STRING,
|
||||
fileType: FileType.JSX,
|
||||
name: REACT_CHUNK_NAME.ClassRenderPre,
|
||||
content: getFuncExprBody(
|
||||
(lifeCycles[lifeCycleName] as IJSExpression).value,
|
||||
),
|
||||
linkAfter: [REACT_CHUNK_NAME.ClassRenderStart],
|
||||
};
|
||||
}
|
||||
if (
|
||||
lifeCycleName === 'componentDidMount' ||
|
||||
lifeCycleName === 'componentDidUpdate' ||
|
||||
lifeCycleName === 'componentWillUnmount' ||
|
||||
lifeCycleName === 'componentDidCatch'
|
||||
) {
|
||||
return {
|
||||
type: ChunkType.STRING,
|
||||
fileType: FileType.JSX,
|
||||
name: REACT_CHUNK_NAME.ClassLifeCycle,
|
||||
fileType: cfg.fileType,
|
||||
name: CLASS_DEFINE_CHUNK_NAME.InsMethod,
|
||||
content: transformFuncExpr2MethodMember(
|
||||
lifeCycleName,
|
||||
exportName,
|
||||
(lifeCycles[lifeCycleName] as IJSExpression).value,
|
||||
),
|
||||
linkAfter: [
|
||||
REACT_CHUNK_NAME.ClassStart,
|
||||
REACT_CHUNK_NAME.ClassConstructorEnd,
|
||||
],
|
||||
linkAfter: [...DEFAULT_LINK_AFTER[CLASS_DEFINE_CHUNK_NAME.InsMethod]],
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
throw new CodeGeneratorError('Unknown life cycle method name');
|
||||
});
|
||||
next.chunks.push.apply(next.chunks, chunks);
|
||||
}
|
||||
|
||||
next.chunks.push.apply(next.chunks, chunks);
|
||||
}
|
||||
|
||||
return next;
|
||||
return next;
|
||||
};
|
||||
return plugin;
|
||||
};
|
||||
|
||||
export default plugin;
|
||||
export default pluginFactory;
|
||||
|
||||
@ -1,9 +1,10 @@
|
||||
import { REACT_CHUNK_NAME } from './const';
|
||||
import { CLASS_DEFINE_CHUNK_NAME, DEFAULT_LINK_AFTER } from '../../../const/generator';
|
||||
|
||||
import { transformFuncExpr2MethodMember } from '../../utils/jsExpression';
|
||||
import { transformFuncExpr2MethodMember } from '../../../utils/jsExpression';
|
||||
|
||||
import {
|
||||
BuilderComponentPlugin,
|
||||
BuilderComponentPluginFactory,
|
||||
ChunkType,
|
||||
FileType,
|
||||
ICodeChunk,
|
||||
@ -12,34 +13,42 @@ import {
|
||||
IJSExpression,
|
||||
} from '../../../types';
|
||||
|
||||
const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => {
|
||||
const next: ICodeStruct = {
|
||||
...pre,
|
||||
type PluginConfig = {
|
||||
fileType: string;
|
||||
}
|
||||
|
||||
const pluginFactory: BuilderComponentPluginFactory<PluginConfig> = (config?) => {
|
||||
const cfg: PluginConfig = {
|
||||
fileType: FileType.JSX,
|
||||
...config,
|
||||
};
|
||||
|
||||
const ir = next.ir as IContainerInfo;
|
||||
const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => {
|
||||
const next: ICodeStruct = {
|
||||
...pre,
|
||||
};
|
||||
|
||||
if (ir.methods) {
|
||||
const methods = ir.methods;
|
||||
const chunks = Object.keys(methods).map<ICodeChunk>(methodName => ({
|
||||
type: ChunkType.STRING,
|
||||
fileType: FileType.JSX,
|
||||
name: REACT_CHUNK_NAME.ClassMethod,
|
||||
content: transformFuncExpr2MethodMember(
|
||||
methodName,
|
||||
(methods[methodName] as IJSExpression).value,
|
||||
),
|
||||
linkAfter: [
|
||||
REACT_CHUNK_NAME.ClassStart,
|
||||
REACT_CHUNK_NAME.ClassConstructorEnd,
|
||||
REACT_CHUNK_NAME.ClassLifeCycle,
|
||||
],
|
||||
}));
|
||||
const ir = next.ir as IContainerInfo;
|
||||
|
||||
next.chunks.push.apply(next.chunks, chunks);
|
||||
}
|
||||
if (ir.methods) {
|
||||
const methods = ir.methods;
|
||||
const chunks = Object.keys(methods).map<ICodeChunk>(methodName => ({
|
||||
type: ChunkType.STRING,
|
||||
fileType: cfg.fileType,
|
||||
name: CLASS_DEFINE_CHUNK_NAME.InsMethod,
|
||||
content: transformFuncExpr2MethodMember(
|
||||
methodName,
|
||||
(methods[methodName] as IJSExpression).value,
|
||||
),
|
||||
linkAfter: [...DEFAULT_LINK_AFTER[CLASS_DEFINE_CHUNK_NAME.InsMethod]],
|
||||
}));
|
||||
|
||||
return next;
|
||||
next.chunks.push.apply(next.chunks, chunks);
|
||||
}
|
||||
|
||||
return next;
|
||||
};
|
||||
return plugin;
|
||||
};
|
||||
|
||||
export default plugin;
|
||||
export default pluginFactory;
|
||||
|
||||
@ -1,149 +1,50 @@
|
||||
import {
|
||||
BuilderComponentPlugin,
|
||||
ChildNodeItem,
|
||||
ChildNodeType,
|
||||
BuilderComponentPluginFactory,
|
||||
ChunkType,
|
||||
FileType,
|
||||
ICodeStruct,
|
||||
IComponentNodeItem,
|
||||
IContainerInfo,
|
||||
IInlineStyle,
|
||||
IJSExpression,
|
||||
} from '../../../types';
|
||||
|
||||
import { handleChildren } from '../../../utils/children';
|
||||
import { generateCompositeType } from '../../utils/compositeType';
|
||||
import { REACT_CHUNK_NAME } from './const';
|
||||
|
||||
function generateInlineStyle(style: IInlineStyle): string | null {
|
||||
const attrLines = Object.keys(style).map((cssAttribute: string) => {
|
||||
const [isString, valueStr] = generateCompositeType(style[cssAttribute]);
|
||||
const valuePart = isString ? `'${valueStr}'` : valueStr;
|
||||
return `${cssAttribute}: ${valuePart},`;
|
||||
});
|
||||
import { createReactNodeGenerator } from '../../../utils/nodeToJSX';
|
||||
|
||||
if (attrLines.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return `{ ${attrLines.join('')} }`;
|
||||
type PluginConfig = {
|
||||
fileType: string;
|
||||
}
|
||||
|
||||
function generateAttr(attrName: string, attrValue: any): string {
|
||||
if (attrName === 'initValue' || attrName === 'labelCol') {
|
||||
return '';
|
||||
}
|
||||
const [isString, valueStr] = generateCompositeType(attrValue);
|
||||
return `${attrName}=${isString ? `"${valueStr}"` : `{${valueStr}}`}`;
|
||||
}
|
||||
|
||||
function mapNodeName(src: string): string {
|
||||
if (src === 'Div') {
|
||||
return 'div';
|
||||
}
|
||||
return src;
|
||||
}
|
||||
|
||||
function generateNode(nodeItem: IComponentNodeItem): string {
|
||||
const codePieces: string[] = [];
|
||||
let propLines: string[] = [];
|
||||
const { className, style, ...props } = nodeItem.props;
|
||||
|
||||
codePieces.push(`<${mapNodeName(nodeItem.componentName)}`);
|
||||
if (className) {
|
||||
propLines.push(`className="${className}"`);
|
||||
}
|
||||
if (style) {
|
||||
const inlineStyle = generateInlineStyle(style);
|
||||
if (inlineStyle !== null) {
|
||||
propLines.push(`style={${inlineStyle}}`);
|
||||
}
|
||||
}
|
||||
|
||||
propLines = propLines.concat(
|
||||
Object.keys(props).map((propName: string) =>
|
||||
generateAttr(propName, props[propName]),
|
||||
),
|
||||
);
|
||||
codePieces.push(` ${propLines.join(' ')} `);
|
||||
|
||||
if (nodeItem.children && (nodeItem.children as unknown[]).length > 0) {
|
||||
codePieces.push('>');
|
||||
const childrenLines = generateChildren(nodeItem.children);
|
||||
codePieces.push.apply(codePieces, childrenLines);
|
||||
codePieces.push(`</${mapNodeName(nodeItem.componentName)}>`);
|
||||
} else {
|
||||
codePieces.push('/>');
|
||||
}
|
||||
|
||||
if (nodeItem.loop && nodeItem.loopArgs) {
|
||||
let loopDataExp;
|
||||
if ((nodeItem.loop as IJSExpression).type === 'JSExpression') {
|
||||
loopDataExp = `(${(nodeItem.loop as IJSExpression).value})`;
|
||||
} else {
|
||||
loopDataExp = JSON.stringify(nodeItem.loop);
|
||||
}
|
||||
codePieces.unshift(
|
||||
`${loopDataExp}.map((${nodeItem.loopArgs[0]}, ${nodeItem.loopArgs[1]}) => (`,
|
||||
);
|
||||
codePieces.push('))');
|
||||
}
|
||||
|
||||
if (nodeItem.condition) {
|
||||
codePieces.unshift(`(${generateCompositeType(nodeItem.condition)}) && (`);
|
||||
codePieces.push(')');
|
||||
}
|
||||
|
||||
if (nodeItem.condition || (nodeItem.loop && nodeItem.loopArgs)) {
|
||||
codePieces.unshift('{');
|
||||
codePieces.push('}');
|
||||
}
|
||||
|
||||
return codePieces.join('');
|
||||
}
|
||||
|
||||
function generateChildren(children: ChildNodeType): string[] {
|
||||
return handleChildren<string>(children, {
|
||||
// TODO: 如果容器直接只有一个 字符串 children 呢?
|
||||
string: (input: string) => [input],
|
||||
expression: (input: IJSExpression) => [`{${input.value}}`],
|
||||
node: (input: IComponentNodeItem) => [generateNode(input)],
|
||||
});
|
||||
}
|
||||
|
||||
const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => {
|
||||
const next: ICodeStruct = {
|
||||
...pre,
|
||||
const pluginFactory: BuilderComponentPluginFactory<PluginConfig> = (config?) => {
|
||||
const cfg: PluginConfig = {
|
||||
fileType: FileType.JSX,
|
||||
...config,
|
||||
};
|
||||
|
||||
const ir = next.ir as IContainerInfo;
|
||||
const generator = createReactNodeGenerator();
|
||||
|
||||
let jsxContent: string;
|
||||
if (!ir.children || (ir.children as unknown[]).length === 0) {
|
||||
jsxContent = 'null';
|
||||
} else {
|
||||
const childrenCode = generateChildren(ir.children);
|
||||
if (childrenCode.length === 1) {
|
||||
jsxContent = `(${childrenCode[0]})`;
|
||||
} else {
|
||||
jsxContent = `(<React.Fragment>${childrenCode.join(
|
||||
'',
|
||||
)}</React.Fragment>)`;
|
||||
}
|
||||
}
|
||||
const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => {
|
||||
const next: ICodeStruct = {
|
||||
...pre,
|
||||
};
|
||||
|
||||
next.chunks.push({
|
||||
type: ChunkType.STRING,
|
||||
fileType: FileType.JSX,
|
||||
name: REACT_CHUNK_NAME.ClassRenderJSX,
|
||||
content: `return ${jsxContent};`,
|
||||
linkAfter: [
|
||||
REACT_CHUNK_NAME.ClassRenderStart,
|
||||
REACT_CHUNK_NAME.ClassRenderPre,
|
||||
],
|
||||
});
|
||||
const ir = next.ir as IContainerInfo;
|
||||
const jsxContent = generator(ir);
|
||||
|
||||
return next;
|
||||
next.chunks.push({
|
||||
type: ChunkType.STRING,
|
||||
fileType: cfg.fileType,
|
||||
name: REACT_CHUNK_NAME.ClassRenderJSX,
|
||||
content: `return ${jsxContent};`,
|
||||
linkAfter: [
|
||||
REACT_CHUNK_NAME.ClassRenderStart,
|
||||
REACT_CHUNK_NAME.ClassRenderPre,
|
||||
],
|
||||
});
|
||||
|
||||
return next;
|
||||
};
|
||||
return plugin;
|
||||
};
|
||||
|
||||
export default plugin;
|
||||
export default pluginFactory;
|
||||
|
||||
@ -2,27 +2,30 @@ import { COMMON_CHUNK_NAME } from '../../../const/generator';
|
||||
|
||||
import {
|
||||
BuilderComponentPlugin,
|
||||
BuilderComponentPluginFactory,
|
||||
ChunkType,
|
||||
FileType,
|
||||
ICodeStruct,
|
||||
IContainerInfo,
|
||||
} from '../../../types';
|
||||
|
||||
// TODO: How to merge this logic to common deps
|
||||
const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => {
|
||||
const next: ICodeStruct = {
|
||||
...pre,
|
||||
const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
|
||||
const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => {
|
||||
const next: ICodeStruct = {
|
||||
...pre,
|
||||
};
|
||||
|
||||
next.chunks.push({
|
||||
type: ChunkType.STRING,
|
||||
fileType: FileType.JSX,
|
||||
name: COMMON_CHUNK_NAME.ExternalDepsImport,
|
||||
content: `import React from 'react';`,
|
||||
linkAfter: [],
|
||||
});
|
||||
|
||||
return next;
|
||||
};
|
||||
|
||||
next.chunks.push({
|
||||
type: ChunkType.STRING,
|
||||
fileType: FileType.JSX,
|
||||
name: COMMON_CHUNK_NAME.ExternalDepsImport,
|
||||
content: `import React from 'react';`,
|
||||
linkAfter: [],
|
||||
});
|
||||
|
||||
return next;
|
||||
return plugin;
|
||||
};
|
||||
|
||||
export default plugin;
|
||||
export default pluginFactory;
|
||||
|
||||
@ -0,0 +1,3 @@
|
||||
export const RECORE_CHUNK_NAME = {
|
||||
|
||||
};
|
||||
@ -0,0 +1,67 @@
|
||||
import { CLASS_DEFINE_CHUNK_NAME, DEFAULT_LINK_AFTER } from '../../../const/generator';
|
||||
|
||||
import {
|
||||
BuilderComponentPlugin,
|
||||
BuilderComponentPluginFactory,
|
||||
ChunkType,
|
||||
FileType,
|
||||
ICodeStruct,
|
||||
IContainerInfo,
|
||||
IJSExpression,
|
||||
CompositeValue,
|
||||
} from '../../../types';
|
||||
|
||||
import { generateCompositeType, handleStringValueDefault } from '../../../utils/compositeType';
|
||||
import { generateExpression } from '../../../utils/jsExpression';
|
||||
|
||||
function packJsExpression(exp: unknown): string {
|
||||
const expression = exp as IJSExpression;
|
||||
const funcStr = generateExpression(expression);
|
||||
return `function() { return (${funcStr}); }`;
|
||||
}
|
||||
|
||||
const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
|
||||
const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => {
|
||||
const next: ICodeStruct = {
|
||||
...pre,
|
||||
};
|
||||
|
||||
const ir = next.ir as IContainerInfo;
|
||||
if (ir.dataSource) {
|
||||
const { dataSource } = ir;
|
||||
const {
|
||||
list,
|
||||
...rest
|
||||
} = dataSource;
|
||||
|
||||
let attrs: string[] = [];
|
||||
|
||||
const extConfigs = Object.keys(rest).map(extConfigName => {
|
||||
const value = (rest as Record<string, CompositeValue>)[extConfigName];
|
||||
const [isString, valueStr] = generateCompositeType(value);
|
||||
return `${extConfigName}: ${isString ? `'${valueStr}'` : valueStr}`;
|
||||
});
|
||||
|
||||
attrs = [...attrs, ...extConfigs];
|
||||
|
||||
const listProp = handleStringValueDefault(generateCompositeType(list as unknown as CompositeValue, {
|
||||
expression: packJsExpression,
|
||||
}));
|
||||
|
||||
attrs.push(`list: ${listProp}`);
|
||||
|
||||
next.chunks.push({
|
||||
type: ChunkType.STRING,
|
||||
fileType: FileType.TS,
|
||||
name: CLASS_DEFINE_CHUNK_NAME.InsVar,
|
||||
content: `dataSourceOptions = { ${attrs.join(',\n')} };`,
|
||||
linkAfter: [...DEFAULT_LINK_AFTER[CLASS_DEFINE_CHUNK_NAME.InsVar]],
|
||||
});
|
||||
}
|
||||
|
||||
return next;
|
||||
};
|
||||
return plugin;
|
||||
};
|
||||
|
||||
export default pluginFactory;
|
||||
@ -0,0 +1,81 @@
|
||||
import { COMMON_CHUNK_NAME, CLASS_DEFINE_CHUNK_NAME, DEFAULT_LINK_AFTER } from '../../../const/generator';
|
||||
|
||||
import {
|
||||
BuilderComponentPlugin,
|
||||
BuilderComponentPluginFactory,
|
||||
ChunkType,
|
||||
FileType,
|
||||
ICodeStruct,
|
||||
IContainerInfo,
|
||||
} from '../../../types';
|
||||
|
||||
const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
|
||||
const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => {
|
||||
const next: ICodeStruct = {
|
||||
...pre,
|
||||
};
|
||||
|
||||
const ir = next.ir as IContainerInfo;
|
||||
|
||||
next.chunks.push({
|
||||
type: ChunkType.STRING,
|
||||
fileType: FileType.TS,
|
||||
name: COMMON_CHUNK_NAME.ExternalDepsImport,
|
||||
content: `import { BaseController } from '@ali/recore-renderer';`,
|
||||
linkAfter: [],
|
||||
});
|
||||
|
||||
next.chunks.push({
|
||||
type: ChunkType.STRING,
|
||||
fileType: FileType.TS,
|
||||
name: CLASS_DEFINE_CHUNK_NAME.Start,
|
||||
content: `class ${ir.moduleName} extends BaseController {`,
|
||||
linkAfter: [...DEFAULT_LINK_AFTER[CLASS_DEFINE_CHUNK_NAME.Start]],
|
||||
});
|
||||
|
||||
next.chunks.push({
|
||||
type: ChunkType.STRING,
|
||||
fileType: FileType.TS,
|
||||
name: CLASS_DEFINE_CHUNK_NAME.End,
|
||||
content: `}`,
|
||||
linkAfter: [...DEFAULT_LINK_AFTER[CLASS_DEFINE_CHUNK_NAME.End]],
|
||||
});
|
||||
|
||||
next.chunks.push({
|
||||
type: ChunkType.STRING,
|
||||
fileType: FileType.TS,
|
||||
name: CLASS_DEFINE_CHUNK_NAME.ConstructorStart,
|
||||
content: 'init() {',
|
||||
linkAfter: [...DEFAULT_LINK_AFTER[CLASS_DEFINE_CHUNK_NAME.ConstructorStart]],
|
||||
});
|
||||
|
||||
next.chunks.push({
|
||||
type: ChunkType.STRING,
|
||||
fileType: FileType.TS,
|
||||
name: CLASS_DEFINE_CHUNK_NAME.ConstructorEnd,
|
||||
content: '}',
|
||||
linkAfter: [...DEFAULT_LINK_AFTER[CLASS_DEFINE_CHUNK_NAME.ConstructorEnd]],
|
||||
});
|
||||
|
||||
next.chunks.push({
|
||||
type: ChunkType.STRING,
|
||||
fileType: FileType.TS,
|
||||
name: CLASS_DEFINE_CHUNK_NAME.InsVar,
|
||||
content: 'globalProps = (window as any)?.g_config?.globalProps || {};',
|
||||
linkAfter: [...DEFAULT_LINK_AFTER[CLASS_DEFINE_CHUNK_NAME.InsVar]],
|
||||
});
|
||||
|
||||
next.chunks.push({
|
||||
type: ChunkType.STRING,
|
||||
fileType: FileType.TS,
|
||||
name: COMMON_CHUNK_NAME.FileExport,
|
||||
content: `export default ${ir.moduleName};`,
|
||||
linkAfter: [...DEFAULT_LINK_AFTER[COMMON_CHUNK_NAME.FileExport]],
|
||||
});
|
||||
|
||||
return next;
|
||||
};
|
||||
return plugin;
|
||||
};
|
||||
|
||||
export default pluginFactory;
|
||||
@ -0,0 +1,35 @@
|
||||
import { CLASS_DEFINE_CHUNK_NAME, DEFAULT_LINK_AFTER } from '../../../const/generator';
|
||||
|
||||
import {
|
||||
BuilderComponentPlugin,
|
||||
BuilderComponentPluginFactory,
|
||||
ChunkType,
|
||||
ICodeStruct,
|
||||
FileType,
|
||||
IContainerInfo,
|
||||
} from '../../../types';
|
||||
|
||||
const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
|
||||
const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => {
|
||||
const next: ICodeStruct = {
|
||||
...pre,
|
||||
};
|
||||
|
||||
const ir = next.ir as IContainerInfo;
|
||||
|
||||
if (ir.css) {
|
||||
next.chunks.push({
|
||||
type: ChunkType.STRING,
|
||||
fileType: FileType.TS,
|
||||
name: CLASS_DEFINE_CHUNK_NAME.StaticVar,
|
||||
content: `static cssText = '${ir.css.replace(/\'/g, '\\\'')}';`,
|
||||
linkAfter: [...DEFAULT_LINK_AFTER[CLASS_DEFINE_CHUNK_NAME.StaticVar]],
|
||||
});
|
||||
}
|
||||
|
||||
return next;
|
||||
};
|
||||
return plugin;
|
||||
};
|
||||
|
||||
export default pluginFactory;
|
||||
@ -0,0 +1,82 @@
|
||||
import {
|
||||
BuilderComponentPlugin,
|
||||
BuilderComponentPluginFactory,
|
||||
ChunkType,
|
||||
ICodeStruct,
|
||||
IContainerInfo,
|
||||
IComponentNodeItem,
|
||||
CodePiece,
|
||||
PIECE_TYPE,
|
||||
} from '../../../types';
|
||||
import { COMMON_CHUNK_NAME, DEFAULT_LINK_AFTER } 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 generateCtrlLine = (nodeItem: IComponentNodeItem): CodePiece[] => {
|
||||
const pieces: CodePiece[] = [];
|
||||
|
||||
if (nodeItem.loop && nodeItem.loopArgs) {
|
||||
const loopDataExp = handleStringValueDefault(generateCompositeType(nodeItem.loop));
|
||||
pieces.push({
|
||||
type: PIECE_TYPE.ATTR,
|
||||
value: `x-for={${loopDataExp}}`,
|
||||
});
|
||||
|
||||
pieces.push({
|
||||
type: PIECE_TYPE.ATTR,
|
||||
value: `x-each="${nodeItem.loopArgs[0]},${nodeItem.loopArgs[1]}"`,
|
||||
});
|
||||
}
|
||||
|
||||
if (nodeItem.condition) {
|
||||
const conditionExp = handleStringValueDefault(generateCompositeType(nodeItem.condition));
|
||||
pieces.push({
|
||||
type: PIECE_TYPE.ATTR,
|
||||
value: `x-if={${conditionExp}}`,
|
||||
});
|
||||
}
|
||||
|
||||
return pieces;
|
||||
};
|
||||
|
||||
const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
|
||||
const generator = createNodeGenerator({
|
||||
string: generateString,
|
||||
expression: (input) => [generateExpression(input)],
|
||||
}, [
|
||||
generateGlobalProps,
|
||||
generateCtrlLine,
|
||||
]);
|
||||
|
||||
const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => {
|
||||
const next: ICodeStruct = {
|
||||
...pre,
|
||||
};
|
||||
|
||||
const ir = next.ir as IContainerInfo;
|
||||
|
||||
const vxContent = generator(ir);
|
||||
|
||||
next.chunks.push({
|
||||
type: ChunkType.STRING,
|
||||
fileType: 'vx',
|
||||
name: COMMON_CHUNK_NAME.CustomContent,
|
||||
content: vxContent,
|
||||
linkAfter: [],
|
||||
});
|
||||
|
||||
return next;
|
||||
};
|
||||
return plugin;
|
||||
};
|
||||
|
||||
export default pluginFactory;
|
||||
@ -0,0 +1,29 @@
|
||||
import { COMMON_CHUNK_NAME } from '../../../const/generator';
|
||||
|
||||
import {
|
||||
BuilderComponentPlugin,
|
||||
BuilderComponentPluginFactory,
|
||||
ChunkType,
|
||||
ICodeStruct,
|
||||
} from '../../../types';
|
||||
|
||||
const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
|
||||
const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => {
|
||||
const next: ICodeStruct = {
|
||||
...pre,
|
||||
};
|
||||
|
||||
next.chunks.push({
|
||||
type: ChunkType.STRING,
|
||||
fileType: 'vx',
|
||||
name: COMMON_CHUNK_NAME.CustomContent,
|
||||
content: `<div {...globalProps.div} className="recore-loading" x-if={this.__loading} />`,
|
||||
linkAfter: [],
|
||||
});
|
||||
|
||||
return next;
|
||||
};
|
||||
return plugin;
|
||||
};
|
||||
|
||||
export default pluginFactory;
|
||||
@ -2,36 +2,51 @@ import { COMMON_CHUNK_NAME } from '../../../const/generator';
|
||||
|
||||
import {
|
||||
BuilderComponentPlugin,
|
||||
BuilderComponentPluginFactory,
|
||||
ChunkType,
|
||||
FileType,
|
||||
ICodeStruct,
|
||||
IContainerInfo,
|
||||
} from '../../../types';
|
||||
|
||||
const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => {
|
||||
const next: ICodeStruct = {
|
||||
...pre,
|
||||
type PluginConfig = {
|
||||
fileType: string;
|
||||
moduleFileType: string;
|
||||
}
|
||||
|
||||
const pluginFactory: BuilderComponentPluginFactory<PluginConfig> = (config?) => {
|
||||
const cfg: PluginConfig = {
|
||||
fileType: FileType.CSS,
|
||||
moduleFileType: FileType.JSX,
|
||||
...config,
|
||||
};
|
||||
|
||||
const ir = next.ir as IContainerInfo;
|
||||
const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => {
|
||||
const next: ICodeStruct = {
|
||||
...pre,
|
||||
};
|
||||
|
||||
next.chunks.push({
|
||||
type: ChunkType.STRING,
|
||||
fileType: FileType.CSS,
|
||||
name: COMMON_CHUNK_NAME.StyleCssContent,
|
||||
content: ir.css,
|
||||
linkAfter: [COMMON_CHUNK_NAME.StyleDepsImport],
|
||||
});
|
||||
const ir = next.ir as IContainerInfo;
|
||||
|
||||
next.chunks.push({
|
||||
type: ChunkType.STRING,
|
||||
fileType: FileType.JSX,
|
||||
name: COMMON_CHUNK_NAME.InternalDepsImport,
|
||||
content: `import './index.css';`,
|
||||
linkAfter: [COMMON_CHUNK_NAME.ExternalDepsImport],
|
||||
});
|
||||
next.chunks.push({
|
||||
type: ChunkType.STRING,
|
||||
fileType: cfg.fileType,
|
||||
name: COMMON_CHUNK_NAME.StyleCssContent,
|
||||
content: ir.css,
|
||||
linkAfter: [COMMON_CHUNK_NAME.StyleDepsImport],
|
||||
});
|
||||
|
||||
return next;
|
||||
next.chunks.push({
|
||||
type: ChunkType.STRING,
|
||||
fileType: cfg.moduleFileType,
|
||||
name: COMMON_CHUNK_NAME.InternalDepsImport,
|
||||
content: `import './index.${cfg.fileType}';`,
|
||||
linkAfter: [COMMON_CHUNK_NAME.ExternalDepsImport],
|
||||
});
|
||||
|
||||
return next;
|
||||
};
|
||||
return plugin;
|
||||
};
|
||||
|
||||
export default plugin;
|
||||
export default pluginFactory;
|
||||
|
||||
@ -1,54 +1,57 @@
|
||||
import { COMMON_CHUNK_NAME } from '../../const/generator';
|
||||
import { generateCompositeType } from '../../plugins/utils/compositeType';
|
||||
import { generateCompositeType } from '../../utils/compositeType';
|
||||
import {
|
||||
BuilderComponentPlugin,
|
||||
BuilderComponentPluginFactory,
|
||||
ChunkType,
|
||||
FileType,
|
||||
ICodeStruct,
|
||||
IProjectInfo,
|
||||
} from '../../types';
|
||||
|
||||
// TODO: How to merge this logic to common deps
|
||||
const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => {
|
||||
const next: ICodeStruct = {
|
||||
...pre,
|
||||
const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
|
||||
const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => {
|
||||
const next: ICodeStruct = {
|
||||
...pre,
|
||||
};
|
||||
|
||||
const ir = next.ir as IProjectInfo;
|
||||
if (ir.constants) {
|
||||
const [, constantStr] = generateCompositeType(ir.constants);
|
||||
|
||||
next.chunks.push({
|
||||
type: ChunkType.STRING,
|
||||
fileType: FileType.JS,
|
||||
name: COMMON_CHUNK_NAME.FileVarDefine,
|
||||
content: `
|
||||
const constantConfig = ${constantStr};
|
||||
`,
|
||||
linkAfter: [
|
||||
COMMON_CHUNK_NAME.ExternalDepsImport,
|
||||
COMMON_CHUNK_NAME.InternalDepsImport,
|
||||
],
|
||||
});
|
||||
|
||||
next.chunks.push({
|
||||
type: ChunkType.STRING,
|
||||
fileType: FileType.JS,
|
||||
name: COMMON_CHUNK_NAME.FileExport,
|
||||
content: `
|
||||
export default constantConfig;
|
||||
`,
|
||||
linkAfter: [
|
||||
COMMON_CHUNK_NAME.ExternalDepsImport,
|
||||
COMMON_CHUNK_NAME.InternalDepsImport,
|
||||
COMMON_CHUNK_NAME.FileVarDefine,
|
||||
COMMON_CHUNK_NAME.FileUtilDefine,
|
||||
COMMON_CHUNK_NAME.FileMainContent,
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
return next;
|
||||
};
|
||||
|
||||
const ir = next.ir as IProjectInfo;
|
||||
if (ir.constants) {
|
||||
const [, constantStr] = generateCompositeType(ir.constants);
|
||||
|
||||
next.chunks.push({
|
||||
type: ChunkType.STRING,
|
||||
fileType: FileType.JS,
|
||||
name: COMMON_CHUNK_NAME.FileVarDefine,
|
||||
content: `
|
||||
const constantConfig = ${constantStr};
|
||||
`,
|
||||
linkAfter: [
|
||||
COMMON_CHUNK_NAME.ExternalDepsImport,
|
||||
COMMON_CHUNK_NAME.InternalDepsImport,
|
||||
],
|
||||
});
|
||||
|
||||
next.chunks.push({
|
||||
type: ChunkType.STRING,
|
||||
fileType: FileType.JS,
|
||||
name: COMMON_CHUNK_NAME.FileExport,
|
||||
content: `
|
||||
export default constantConfig;
|
||||
`,
|
||||
linkAfter: [
|
||||
COMMON_CHUNK_NAME.ExternalDepsImport,
|
||||
COMMON_CHUNK_NAME.InternalDepsImport,
|
||||
COMMON_CHUNK_NAME.FileVarDefine,
|
||||
COMMON_CHUNK_NAME.FileUtilDefine,
|
||||
COMMON_CHUNK_NAME.FileMainContent,
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
return next;
|
||||
return plugin;
|
||||
};
|
||||
|
||||
export default plugin;
|
||||
export default pluginFactory;
|
||||
|
||||
@ -2,54 +2,57 @@ import { COMMON_CHUNK_NAME } from '../../../../../const/generator';
|
||||
|
||||
import {
|
||||
BuilderComponentPlugin,
|
||||
BuilderComponentPluginFactory,
|
||||
ChunkType,
|
||||
FileType,
|
||||
ICodeStruct,
|
||||
IProjectInfo,
|
||||
} from '../../../../../types';
|
||||
|
||||
// TODO: How to merge this logic to common deps
|
||||
const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => {
|
||||
const next: ICodeStruct = {
|
||||
...pre,
|
||||
const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
|
||||
const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => {
|
||||
const next: ICodeStruct = {
|
||||
...pre,
|
||||
};
|
||||
|
||||
const ir = next.ir as IProjectInfo;
|
||||
|
||||
next.chunks.push({
|
||||
type: ChunkType.STRING,
|
||||
fileType: FileType.JS,
|
||||
name: COMMON_CHUNK_NAME.ExternalDepsImport,
|
||||
content: `
|
||||
import { createApp } from 'ice';
|
||||
`,
|
||||
linkAfter: [],
|
||||
});
|
||||
|
||||
next.chunks.push({
|
||||
type: ChunkType.STRING,
|
||||
fileType: FileType.JS,
|
||||
name: COMMON_CHUNK_NAME.FileMainContent,
|
||||
content: `
|
||||
const appConfig = {
|
||||
app: {
|
||||
rootId: '${ir.config.targetRootID}',
|
||||
},
|
||||
router: {
|
||||
type: '${ir.config.historyMode}',
|
||||
},
|
||||
};
|
||||
createApp(appConfig);
|
||||
`,
|
||||
linkAfter: [
|
||||
COMMON_CHUNK_NAME.ExternalDepsImport,
|
||||
COMMON_CHUNK_NAME.InternalDepsImport,
|
||||
COMMON_CHUNK_NAME.FileVarDefine,
|
||||
COMMON_CHUNK_NAME.FileUtilDefine,
|
||||
],
|
||||
});
|
||||
|
||||
return next;
|
||||
};
|
||||
|
||||
const ir = next.ir as IProjectInfo;
|
||||
|
||||
next.chunks.push({
|
||||
type: ChunkType.STRING,
|
||||
fileType: FileType.JS,
|
||||
name: COMMON_CHUNK_NAME.ExternalDepsImport,
|
||||
content: `
|
||||
import { createApp } from 'ice';
|
||||
`,
|
||||
linkAfter: [],
|
||||
});
|
||||
|
||||
next.chunks.push({
|
||||
type: ChunkType.STRING,
|
||||
fileType: FileType.JS,
|
||||
name: COMMON_CHUNK_NAME.FileMainContent,
|
||||
content: `
|
||||
const appConfig = {
|
||||
app: {
|
||||
rootId: '${ir.config.targetRootID}',
|
||||
},
|
||||
router: {
|
||||
type: '${ir.config.historyMode}',
|
||||
},
|
||||
};
|
||||
createApp(appConfig);
|
||||
`,
|
||||
linkAfter: [
|
||||
COMMON_CHUNK_NAME.ExternalDepsImport,
|
||||
COMMON_CHUNK_NAME.InternalDepsImport,
|
||||
COMMON_CHUNK_NAME.FileVarDefine,
|
||||
COMMON_CHUNK_NAME.FileUtilDefine,
|
||||
],
|
||||
});
|
||||
|
||||
return next;
|
||||
return plugin;
|
||||
};
|
||||
|
||||
export default plugin;
|
||||
export default pluginFactory;
|
||||
|
||||
@ -2,42 +2,45 @@ import { COMMON_CHUNK_NAME } from '../../../../../const/generator';
|
||||
|
||||
import {
|
||||
BuilderComponentPlugin,
|
||||
BuilderComponentPluginFactory,
|
||||
ChunkType,
|
||||
FileType,
|
||||
ICodeStruct,
|
||||
IProjectInfo,
|
||||
} from '../../../../../types';
|
||||
|
||||
// TODO: How to merge this logic to common deps
|
||||
const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => {
|
||||
const next: ICodeStruct = {
|
||||
...pre,
|
||||
const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
|
||||
const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => {
|
||||
const next: ICodeStruct = {
|
||||
...pre,
|
||||
};
|
||||
|
||||
const ir = next.ir as IProjectInfo;
|
||||
|
||||
next.chunks.push({
|
||||
type: ChunkType.STRING,
|
||||
fileType: FileType.HTML,
|
||||
name: COMMON_CHUNK_NAME.HtmlContent,
|
||||
content: `
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta http-equiv="x-ua-compatible" content="ie=edge,chrome=1" />
|
||||
<meta name="viewport" content="width=device-width" />
|
||||
<title>${ir.meta.name}</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="${ir.config.targetRootID}"></div>
|
||||
</body>
|
||||
</html>
|
||||
`,
|
||||
linkAfter: [],
|
||||
});
|
||||
|
||||
return next;
|
||||
};
|
||||
|
||||
const ir = next.ir as IProjectInfo;
|
||||
|
||||
next.chunks.push({
|
||||
type: ChunkType.STRING,
|
||||
fileType: FileType.HTML,
|
||||
name: COMMON_CHUNK_NAME.HtmlContent,
|
||||
content: `
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta http-equiv="x-ua-compatible" content="ie=edge,chrome=1" />
|
||||
<meta name="viewport" content="width=device-width" />
|
||||
<title>${ir.meta.name}</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="${ir.config.targetRootID}"></div>
|
||||
</body>
|
||||
</html>
|
||||
`,
|
||||
linkAfter: [],
|
||||
});
|
||||
|
||||
return next;
|
||||
return plugin;
|
||||
};
|
||||
|
||||
export default plugin;
|
||||
export default pluginFactory;
|
||||
|
||||
@ -2,52 +2,55 @@ import { COMMON_CHUNK_NAME } from '../../../../../const/generator';
|
||||
|
||||
import {
|
||||
BuilderComponentPlugin,
|
||||
BuilderComponentPluginFactory,
|
||||
ChunkType,
|
||||
FileType,
|
||||
ICodeStruct,
|
||||
IProjectInfo,
|
||||
} from '../../../../../types';
|
||||
|
||||
// TODO: How to merge this logic to common deps
|
||||
const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => {
|
||||
const next: ICodeStruct = {
|
||||
...pre,
|
||||
const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
|
||||
const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => {
|
||||
const next: ICodeStruct = {
|
||||
...pre,
|
||||
};
|
||||
|
||||
const ir = next.ir as IProjectInfo;
|
||||
|
||||
next.chunks.push({
|
||||
type: ChunkType.STRING,
|
||||
fileType: FileType.SCSS,
|
||||
name: COMMON_CHUNK_NAME.StyleDepsImport,
|
||||
content: `
|
||||
// 引入默认全局样式
|
||||
@import '@alifd/next/reset.scss';
|
||||
`,
|
||||
linkAfter: [],
|
||||
});
|
||||
|
||||
next.chunks.push({
|
||||
type: ChunkType.STRING,
|
||||
fileType: FileType.SCSS,
|
||||
name: COMMON_CHUNK_NAME.StyleCssContent,
|
||||
content: `
|
||||
body {
|
||||
-webkit-font-smoothing: antialiased;
|
||||
}
|
||||
`,
|
||||
linkAfter: [COMMON_CHUNK_NAME.StyleDepsImport],
|
||||
});
|
||||
|
||||
next.chunks.push({
|
||||
type: ChunkType.STRING,
|
||||
fileType: FileType.SCSS,
|
||||
name: COMMON_CHUNK_NAME.StyleCssContent,
|
||||
content: ir.css || '',
|
||||
linkAfter: [COMMON_CHUNK_NAME.StyleDepsImport],
|
||||
});
|
||||
|
||||
return next;
|
||||
};
|
||||
|
||||
const ir = next.ir as IProjectInfo;
|
||||
|
||||
next.chunks.push({
|
||||
type: ChunkType.STRING,
|
||||
fileType: FileType.SCSS,
|
||||
name: COMMON_CHUNK_NAME.StyleDepsImport,
|
||||
content: `
|
||||
// 引入默认全局样式
|
||||
@import '@alifd/next/reset.scss';
|
||||
`,
|
||||
linkAfter: [],
|
||||
});
|
||||
|
||||
next.chunks.push({
|
||||
type: ChunkType.STRING,
|
||||
fileType: FileType.SCSS,
|
||||
name: COMMON_CHUNK_NAME.StyleCssContent,
|
||||
content: `
|
||||
body {
|
||||
-webkit-font-smoothing: antialiased;
|
||||
}
|
||||
`,
|
||||
linkAfter: [COMMON_CHUNK_NAME.StyleDepsImport],
|
||||
});
|
||||
|
||||
next.chunks.push({
|
||||
type: ChunkType.STRING,
|
||||
fileType: FileType.SCSS,
|
||||
name: COMMON_CHUNK_NAME.StyleCssContent,
|
||||
content: ir.css || '',
|
||||
linkAfter: [COMMON_CHUNK_NAME.StyleDepsImport],
|
||||
});
|
||||
|
||||
return next;
|
||||
return plugin;
|
||||
};
|
||||
|
||||
export default plugin;
|
||||
export default pluginFactory;
|
||||
|
||||
@ -2,6 +2,7 @@ import { COMMON_CHUNK_NAME } from '../../../../../const/generator';
|
||||
|
||||
import {
|
||||
BuilderComponentPlugin,
|
||||
BuilderComponentPluginFactory,
|
||||
ChunkType,
|
||||
FileType,
|
||||
ICodeStruct,
|
||||
@ -20,67 +21,69 @@ interface IIceJsPackageJSON extends IPackageJSON {
|
||||
originTemplate: string;
|
||||
}
|
||||
|
||||
// TODO: How to merge this logic to common deps
|
||||
const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => {
|
||||
const next: ICodeStruct = {
|
||||
...pre,
|
||||
const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
|
||||
const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => {
|
||||
const next: ICodeStruct = {
|
||||
...pre,
|
||||
};
|
||||
|
||||
const ir = next.ir as IProjectInfo;
|
||||
|
||||
const packageJson: IIceJsPackageJSON = {
|
||||
name: '@alifd/scaffold-lite-js',
|
||||
version: '0.1.5',
|
||||
description: '轻量级模板,使用 JavaScript,仅包含基础的 Layout。',
|
||||
dependencies: {
|
||||
moment: '^2.24.0',
|
||||
react: '^16.4.1',
|
||||
'react-dom': '^16.4.1',
|
||||
'@alifd/theme-design-pro': '^0.x',
|
||||
},
|
||||
devDependencies: {
|
||||
'@ice/spec': '^1.0.0',
|
||||
'build-plugin-fusion': '^0.1.0',
|
||||
'build-plugin-moment-locales': '^0.1.0',
|
||||
eslint: '^6.0.1',
|
||||
'ice.js': '^1.0.0',
|
||||
stylelint: '^13.2.0',
|
||||
'@ali/build-plugin-ice-def': '^0.1.0',
|
||||
},
|
||||
scripts: {
|
||||
start: 'icejs start',
|
||||
build: 'icejs build',
|
||||
lint: 'npm run eslint && npm run stylelint',
|
||||
eslint: 'eslint --cache --ext .js,.jsx ./',
|
||||
stylelint: 'stylelint ./**/*.scss',
|
||||
},
|
||||
ideMode: {
|
||||
name: 'ice-react',
|
||||
},
|
||||
iceworks: {
|
||||
type: 'react',
|
||||
adapter: 'adapter-react-v3',
|
||||
},
|
||||
engines: {
|
||||
node: '>=8.0.0',
|
||||
},
|
||||
repository: {
|
||||
type: 'git',
|
||||
url: 'http://gitlab.alibaba-inc.com/msd/leak-scan/tree/master',
|
||||
},
|
||||
private: true,
|
||||
originTemplate: '@alifd/scaffold-lite-js',
|
||||
};
|
||||
|
||||
next.chunks.push({
|
||||
type: ChunkType.JSON,
|
||||
fileType: FileType.JSON,
|
||||
name: COMMON_CHUNK_NAME.FileMainContent,
|
||||
content: packageJson,
|
||||
linkAfter: [],
|
||||
});
|
||||
|
||||
return next;
|
||||
};
|
||||
|
||||
const ir = next.ir as IProjectInfo;
|
||||
|
||||
const packageJson: IIceJsPackageJSON = {
|
||||
name: '@alifd/scaffold-lite-js',
|
||||
version: '0.1.5',
|
||||
description: '轻量级模板,使用 JavaScript,仅包含基础的 Layout。',
|
||||
dependencies: {
|
||||
moment: '^2.24.0',
|
||||
react: '^16.4.1',
|
||||
'react-dom': '^16.4.1',
|
||||
'@alifd/theme-design-pro': '^0.x',
|
||||
},
|
||||
devDependencies: {
|
||||
'@ice/spec': '^1.0.0',
|
||||
'build-plugin-fusion': '^0.1.0',
|
||||
'build-plugin-moment-locales': '^0.1.0',
|
||||
eslint: '^6.0.1',
|
||||
'ice.js': '^1.0.0',
|
||||
stylelint: '^13.2.0',
|
||||
'@ali/build-plugin-ice-def': '^0.1.0',
|
||||
},
|
||||
scripts: {
|
||||
start: 'icejs start',
|
||||
build: 'icejs build',
|
||||
lint: 'npm run eslint && npm run stylelint',
|
||||
eslint: 'eslint --cache --ext .js,.jsx ./',
|
||||
stylelint: 'stylelint ./**/*.scss',
|
||||
},
|
||||
ideMode: {
|
||||
name: 'ice-react',
|
||||
},
|
||||
iceworks: {
|
||||
type: 'react',
|
||||
adapter: 'adapter-react-v3',
|
||||
},
|
||||
engines: {
|
||||
node: '>=8.0.0',
|
||||
},
|
||||
repository: {
|
||||
type: 'git',
|
||||
url: 'http://gitlab.alibaba-inc.com/msd/leak-scan/tree/master',
|
||||
},
|
||||
private: true,
|
||||
originTemplate: '@alifd/scaffold-lite-js',
|
||||
};
|
||||
|
||||
next.chunks.push({
|
||||
type: ChunkType.JSON,
|
||||
fileType: FileType.JSON,
|
||||
name: COMMON_CHUNK_NAME.FileMainContent,
|
||||
content: packageJson,
|
||||
linkAfter: [],
|
||||
});
|
||||
|
||||
return next;
|
||||
return plugin;
|
||||
};
|
||||
|
||||
export default plugin;
|
||||
export default pluginFactory;
|
||||
|
||||
@ -2,78 +2,81 @@ import { COMMON_CHUNK_NAME } from '../../../../../const/generator';
|
||||
|
||||
import {
|
||||
BuilderComponentPlugin,
|
||||
BuilderComponentPluginFactory,
|
||||
ChunkType,
|
||||
FileType,
|
||||
ICodeStruct,
|
||||
IRouterInfo,
|
||||
} from '../../../../../types';
|
||||
|
||||
// TODO: How to merge this logic to common deps
|
||||
const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => {
|
||||
const next: ICodeStruct = {
|
||||
...pre,
|
||||
const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
|
||||
const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => {
|
||||
const next: ICodeStruct = {
|
||||
...pre,
|
||||
};
|
||||
|
||||
const ir = next.ir as IRouterInfo;
|
||||
|
||||
next.chunks.push({
|
||||
type: ChunkType.STRING,
|
||||
fileType: FileType.JS,
|
||||
name: COMMON_CHUNK_NAME.InternalDepsImport,
|
||||
content: `
|
||||
import BasicLayout from '@/layouts/BasicLayout';
|
||||
`,
|
||||
linkAfter: [COMMON_CHUNK_NAME.ExternalDepsImport],
|
||||
});
|
||||
|
||||
next.chunks.push({
|
||||
type: ChunkType.STRING,
|
||||
fileType: FileType.JS,
|
||||
name: COMMON_CHUNK_NAME.FileVarDefine,
|
||||
content: `
|
||||
const routerConfig = [
|
||||
{
|
||||
path: '/',
|
||||
component: BasicLayout,
|
||||
children: [
|
||||
${ir.routes
|
||||
.map(
|
||||
route => `
|
||||
{
|
||||
path: '${route.path}',
|
||||
component: ${route.componentName},
|
||||
}
|
||||
`,
|
||||
)
|
||||
.join(',')}
|
||||
],
|
||||
},
|
||||
];
|
||||
`,
|
||||
linkAfter: [
|
||||
COMMON_CHUNK_NAME.ExternalDepsImport,
|
||||
COMMON_CHUNK_NAME.InternalDepsImport,
|
||||
COMMON_CHUNK_NAME.FileUtilDefine,
|
||||
],
|
||||
});
|
||||
|
||||
next.chunks.push({
|
||||
type: ChunkType.STRING,
|
||||
fileType: FileType.JS,
|
||||
name: COMMON_CHUNK_NAME.FileExport,
|
||||
content: `
|
||||
export default routerConfig;
|
||||
`,
|
||||
linkAfter: [
|
||||
COMMON_CHUNK_NAME.ExternalDepsImport,
|
||||
COMMON_CHUNK_NAME.InternalDepsImport,
|
||||
COMMON_CHUNK_NAME.FileUtilDefine,
|
||||
COMMON_CHUNK_NAME.FileVarDefine,
|
||||
COMMON_CHUNK_NAME.FileMainContent,
|
||||
],
|
||||
});
|
||||
|
||||
return next;
|
||||
};
|
||||
|
||||
const ir = next.ir as IRouterInfo;
|
||||
|
||||
next.chunks.push({
|
||||
type: ChunkType.STRING,
|
||||
fileType: FileType.JS,
|
||||
name: COMMON_CHUNK_NAME.InternalDepsImport,
|
||||
content: `
|
||||
import BasicLayout from '@/layouts/BasicLayout';
|
||||
`,
|
||||
linkAfter: [COMMON_CHUNK_NAME.ExternalDepsImport],
|
||||
});
|
||||
|
||||
next.chunks.push({
|
||||
type: ChunkType.STRING,
|
||||
fileType: FileType.JS,
|
||||
name: COMMON_CHUNK_NAME.FileVarDefine,
|
||||
content: `
|
||||
const routerConfig = [
|
||||
{
|
||||
path: '/',
|
||||
component: BasicLayout,
|
||||
children: [
|
||||
${ir.routes
|
||||
.map(
|
||||
route => `
|
||||
{
|
||||
path: '${route.path}',
|
||||
component: ${route.componentName},
|
||||
}
|
||||
`,
|
||||
)
|
||||
.join(',')}
|
||||
],
|
||||
},
|
||||
];
|
||||
`,
|
||||
linkAfter: [
|
||||
COMMON_CHUNK_NAME.ExternalDepsImport,
|
||||
COMMON_CHUNK_NAME.InternalDepsImport,
|
||||
COMMON_CHUNK_NAME.FileUtilDefine,
|
||||
],
|
||||
});
|
||||
|
||||
next.chunks.push({
|
||||
type: ChunkType.STRING,
|
||||
fileType: FileType.JS,
|
||||
name: COMMON_CHUNK_NAME.FileExport,
|
||||
content: `
|
||||
export default routerConfig;
|
||||
`,
|
||||
linkAfter: [
|
||||
COMMON_CHUNK_NAME.ExternalDepsImport,
|
||||
COMMON_CHUNK_NAME.InternalDepsImport,
|
||||
COMMON_CHUNK_NAME.FileUtilDefine,
|
||||
COMMON_CHUNK_NAME.FileVarDefine,
|
||||
COMMON_CHUNK_NAME.FileMainContent,
|
||||
],
|
||||
});
|
||||
|
||||
return next;
|
||||
return plugin;
|
||||
};
|
||||
|
||||
export default plugin;
|
||||
export default pluginFactory;
|
||||
|
||||
@ -2,8 +2,8 @@ import ResultDir from '../../../../../model/ResultDir';
|
||||
import {
|
||||
IProjectTemplate,
|
||||
IResultDir,
|
||||
IResultFile,
|
||||
} from '../../../../../types';
|
||||
import { runFileGenerator } from '../../../../../utils/templateHelper';
|
||||
|
||||
import file12 from './files/abc.json';
|
||||
import file11 from './files/build.json';
|
||||
@ -26,29 +26,6 @@ import file3 from './files/stylelintignore';
|
||||
import file2 from './files/stylelintrc.js';
|
||||
import file1 from './files/tsconfig.json';
|
||||
|
||||
type FuncFileGenerator = () => [string[], IResultFile];
|
||||
|
||||
function insertFile(root: IResultDir, path: string[], file: IResultFile) {
|
||||
let current: IResultDir = root;
|
||||
path.forEach(pathNode => {
|
||||
const dir = current.dirs.find(d => d.name === pathNode);
|
||||
if (dir) {
|
||||
current = dir;
|
||||
} else {
|
||||
const newDir = new ResultDir(pathNode);
|
||||
current.addDirectory(newDir);
|
||||
current = newDir;
|
||||
}
|
||||
});
|
||||
|
||||
current.addFile(file);
|
||||
}
|
||||
|
||||
function runFileGenerator(root: IResultDir, fun: FuncFileGenerator) {
|
||||
const [path, file] = fun();
|
||||
insertFile(root, path, file);
|
||||
}
|
||||
|
||||
const icejsTemplate: IProjectTemplate = {
|
||||
slots: {
|
||||
components: {
|
||||
|
||||
@ -0,0 +1,32 @@
|
||||
|
||||
import ResultFile from '../../../../../../model/ResultFile';
|
||||
import { IResultFile } from '../../../../../../types';
|
||||
|
||||
export default function getFile(): [string[], IResultFile] {
|
||||
const file = new ResultFile(
|
||||
'.editorconfig',
|
||||
'',
|
||||
`
|
||||
# EditorConfig is awesome: http://EditorConfig.org
|
||||
|
||||
# top-most EditorConfig file
|
||||
root = true
|
||||
|
||||
# Tab indentation
|
||||
[*]
|
||||
charset = utf-8
|
||||
end_of_line = lf
|
||||
indent_size = 2
|
||||
indent_style = space
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[*.md]
|
||||
trim_trailing_whitespace = false
|
||||
|
||||
`,
|
||||
);
|
||||
|
||||
return [[], file];
|
||||
}
|
||||
|
||||
@ -0,0 +1,26 @@
|
||||
|
||||
import ResultFile from '../../../../../../model/ResultFile';
|
||||
import { IResultFile } from '../../../../../../types';
|
||||
|
||||
export default function getFile(): [string[], IResultFile] {
|
||||
const file = new ResultFile(
|
||||
'.eslintignore',
|
||||
'',
|
||||
`
|
||||
.idea
|
||||
.vscode
|
||||
.theia
|
||||
.recore
|
||||
build/
|
||||
.*
|
||||
~*
|
||||
node_modules
|
||||
|
||||
packages/solution
|
||||
|
||||
`,
|
||||
);
|
||||
|
||||
return [[], file];
|
||||
}
|
||||
|
||||
@ -0,0 +1,57 @@
|
||||
|
||||
import ResultFile from '../../../../../../model/ResultFile';
|
||||
import { IResultFile } from '../../../../../../types';
|
||||
|
||||
export default function getFile(): [string[], IResultFile] {
|
||||
const file = new ResultFile(
|
||||
'.gitignore',
|
||||
'',
|
||||
`
|
||||
node_modules/
|
||||
coverage/
|
||||
build/
|
||||
dist/
|
||||
.idea/
|
||||
.vscode/
|
||||
.theia/
|
||||
.recore/
|
||||
.Trash-*/
|
||||
~*
|
||||
package-lock.json
|
||||
|
||||
# Packages #
|
||||
############
|
||||
# it's better to unpack these files and commit the raw source
|
||||
# git has its own built in compression methods
|
||||
*.7z
|
||||
*.dmg
|
||||
*.gz
|
||||
*.iso
|
||||
*.jar
|
||||
*.rar
|
||||
*.tar
|
||||
*.zip
|
||||
|
||||
# Logs and databases #
|
||||
######################
|
||||
*.log
|
||||
*.sql
|
||||
*.sqlite
|
||||
|
||||
# OS generated files #
|
||||
######################
|
||||
.DS_Store
|
||||
*.swp
|
||||
.DS_Store?
|
||||
._*
|
||||
.Spotlight-V100
|
||||
.Trashes
|
||||
ehthumbs.db
|
||||
Thumbs.db
|
||||
|
||||
`,
|
||||
);
|
||||
|
||||
return [[], file];
|
||||
}
|
||||
|
||||
@ -0,0 +1,22 @@
|
||||
|
||||
import ResultFile from '../../../../../../model/ResultFile';
|
||||
import { IResultFile } from '../../../../../../types';
|
||||
|
||||
export default function getFile(): [string[], IResultFile] {
|
||||
const file = new ResultFile(
|
||||
'.prettierrc',
|
||||
'',
|
||||
`
|
||||
{
|
||||
"semi": true,
|
||||
"singleQuote": true,
|
||||
"printWidth": 120,
|
||||
"trailingComma": "all"
|
||||
}
|
||||
|
||||
`,
|
||||
);
|
||||
|
||||
return [[], file];
|
||||
}
|
||||
|
||||
@ -0,0 +1,35 @@
|
||||
|
||||
import ResultFile from '../../../../../../model/ResultFile';
|
||||
import { IResultFile } from '../../../../../../types';
|
||||
|
||||
export default function getFile(): [string[], IResultFile] {
|
||||
const file = new ResultFile(
|
||||
'README',
|
||||
'md',
|
||||
`
|
||||
# runtime-code
|
||||
|
||||
乐高接出码模块测试项目
|
||||
|
||||
|
||||
## 安装运行
|
||||
|
||||
\`\`\`bash
|
||||
# install dependencies
|
||||
tnpm install
|
||||
|
||||
# serve with hot reload at localhost:8080
|
||||
npm start
|
||||
|
||||
# test projects
|
||||
npm test
|
||||
|
||||
# local build
|
||||
npm run build
|
||||
\`\`\`
|
||||
|
||||
`,
|
||||
);
|
||||
|
||||
return [[], file];
|
||||
}
|
||||
@ -0,0 +1,28 @@
|
||||
|
||||
import ResultFile from '../../../../../../model/ResultFile';
|
||||
import { IResultFile } from '../../../../../../types';
|
||||
|
||||
export default function getFile(): [string[], IResultFile] {
|
||||
const file = new ResultFile(
|
||||
'abc',
|
||||
'json',
|
||||
`
|
||||
{
|
||||
"name": "test",
|
||||
"assets": {
|
||||
"type": "command",
|
||||
"command": {
|
||||
"cmd": [
|
||||
"tnpm ii",
|
||||
"tnpm run build"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
`,
|
||||
);
|
||||
|
||||
return [[], file];
|
||||
}
|
||||
|
||||
@ -0,0 +1,32 @@
|
||||
|
||||
import ResultFile from '../../../../../../model/ResultFile';
|
||||
import { IResultFile } from '../../../../../../types';
|
||||
|
||||
export default function getFile(): [string[], IResultFile] {
|
||||
const file = new ResultFile(
|
||||
'build',
|
||||
'json',
|
||||
`
|
||||
{
|
||||
"entry": "src/index",
|
||||
"alias": {
|
||||
"@": "./src"
|
||||
},
|
||||
"publicPath": "./",
|
||||
"outputAssetsPath": {
|
||||
"js": "",
|
||||
"css": ""
|
||||
},
|
||||
"plugins": [
|
||||
"build-plugin-react-app",
|
||||
"@ali/build-plugin-recore-lowcode"
|
||||
],
|
||||
"externals": { "react": "window.React", "react-dom": "window.ReactDOM", "@ali/recore": "window.Recore" }
|
||||
}
|
||||
|
||||
`,
|
||||
);
|
||||
|
||||
return [[], file];
|
||||
}
|
||||
|
||||
@ -0,0 +1,66 @@
|
||||
|
||||
import ResultFile from '../../../../../../model/ResultFile';
|
||||
import { IResultFile } from '../../../../../../types';
|
||||
|
||||
export default function getFile(): [string[], IResultFile] {
|
||||
const file = new ResultFile(
|
||||
'package',
|
||||
'json',
|
||||
`
|
||||
{
|
||||
"name": "test",
|
||||
"version": "1.0.0",
|
||||
"description": "test",
|
||||
"scripts": {
|
||||
"start": "build-scripts start",
|
||||
"build": "build-scripts build",
|
||||
"test": "build-scripts test"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 8.9.0",
|
||||
"npm": ">=6.1.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@ali/lowcode-runtime": "^0.8.0",
|
||||
"@ali/recore": "^1.6.10",
|
||||
"@ali/recore-renderer": "^0.0.3",
|
||||
"@ali/vc-block": "^3.0.3-beta.1",
|
||||
"@ali/vc-deep": "1.2.38",
|
||||
"@ali/vc-div": "^1.0.1",
|
||||
"@ali/vc-page": "^1.0.5",
|
||||
"@ali/vc-shell": "1.3.1",
|
||||
"@ali/vc-slot": "^2.0.1",
|
||||
"@ali/vc-text": "^4.0.1",
|
||||
"@ali/vu-dataSource": "^1.0.4",
|
||||
"@ali/vu-formatter": "^2.0.0",
|
||||
"@ali/vu-fusion": "^2.0.1-beta.0",
|
||||
"@ali/vu-legao-builtin": "^1.4.0-beta.2",
|
||||
"@ali/vu-toolkit": "^1.0.5",
|
||||
"react": "^16"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@ali/build-plugin-recore-lowcode": "^0.0.3",
|
||||
"@ali/recore-lowcode-loader": "^0.0.4",
|
||||
"@alib/build-scripts": "^0.1.0",
|
||||
"@types/node": "^7",
|
||||
"@types/react": "^16",
|
||||
"build-plugin-react-app": "^1.0.15",
|
||||
"eslint": "^6.5.1",
|
||||
"prettier": "^1.18.2",
|
||||
"tslib": "^1.9.3",
|
||||
"typescript": "^3.1.3"
|
||||
},
|
||||
"lint-staged": {
|
||||
"./src/**/*.{ts,tsx}": [
|
||||
"tslint --fix",
|
||||
"git add"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
`,
|
||||
);
|
||||
|
||||
return [[], file];
|
||||
}
|
||||
|
||||
@ -0,0 +1,51 @@
|
||||
|
||||
import ResultFile from '../../../../../../../model/ResultFile';
|
||||
import { IResultFile } from '../../../../../../../types';
|
||||
|
||||
export default function getFile(): [string[], IResultFile] {
|
||||
const file = new ResultFile(
|
||||
'index',
|
||||
'html',
|
||||
`
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, maximum-scale=1.0, user-scalable=no" />
|
||||
<title>lowcode-runtime-test</title>
|
||||
<link rel="shortcut icon" type="image/png" href="https://img.alicdn.com/tfs/TB1zgoCemrqK1RjSZK9XXXyypXa-96-96.png" />
|
||||
<link rel="stylesheet" id="" href="//g.alicdn.com/legao-comp/csxs/1.0.2/web.css?t=1f">
|
||||
<script
|
||||
src="https://g.alicdn.com/code/lib/??react/16.9.0/umd/react.production.min.js,react-dom/16.9.0/umd/react-dom.production.min.js,prop-types/15.7.2/prop-types.js"></script>
|
||||
<!-- React 非压缩版代码,可根据需要替换或通过代理替换后方便调试 -->
|
||||
<!-- <script src="https://g.alicdn.com/code/lib/??react/16.9.0/umd/react.development.js,react-dom/16.9.0/umd/react-dom.development.js,prop-types/15.7.2/prop-types.js"></script> -->
|
||||
<script src="https://g.alicdn.com/mylib/@ali/recore/1.6.8/umd/recore.min.js"></script>
|
||||
<script>
|
||||
React.PropTypes = PropTypes;
|
||||
</script>
|
||||
<style type="text/css">
|
||||
body {
|
||||
-webkit-overflow-scrolling: touch;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<script>
|
||||
window.g_config = {
|
||||
appKey: 'test', // 乐高应用的 AppKey
|
||||
// isSectionalRender: true, // 必填,标记当前为局部使用
|
||||
// autoRender: true,
|
||||
// index: 'search_form',
|
||||
};
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
`,
|
||||
);
|
||||
|
||||
return [['public'], file];
|
||||
}
|
||||
|
||||
@ -0,0 +1,77 @@
|
||||
|
||||
import ResultFile from '../../../../../../../../model/ResultFile';
|
||||
import { IResultFile } from '../../../../../../../../types';
|
||||
|
||||
export default function getFile(): [string[], IResultFile] {
|
||||
const file = new ResultFile(
|
||||
'app',
|
||||
'ts',
|
||||
`
|
||||
export default {
|
||||
"sdkVersion": "1.0.3",
|
||||
"history": "hash", // 浏览器路由:brower 哈希路由:hash
|
||||
"containerId": "app",
|
||||
"layout": {
|
||||
"componentName": "BasicLayout",
|
||||
"props": {
|
||||
"navConfig": {
|
||||
"showLanguageChange": true,
|
||||
"data": [
|
||||
{
|
||||
"hidden": false,
|
||||
"navUuid": "FORM-CP5669B1-3AW9DCLHZAY8EIY6WE6X1-GFZM3V1K-6",
|
||||
"children": [],
|
||||
"icon": "",
|
||||
"targetNew": false,
|
||||
"title": "测试基础表格",
|
||||
"inner": true,
|
||||
"relateUuid": "FORM-CP5669B1-3AW9DCLHZAY8EIY6WE6X1-GFZM3V1K-6",
|
||||
"slug": "qihfg"
|
||||
},
|
||||
{
|
||||
"hidden": false,
|
||||
"navUuid": "FORM-CP5669B1-8AW9XCUT4PCH15SMDWUM3-ZPQP3V1K-1",
|
||||
"children": [],
|
||||
"icon": "",
|
||||
"targetNew": false,
|
||||
"title": "测试查询表格",
|
||||
"inner": true,
|
||||
"relateUuid": "zqhej",
|
||||
"slug": "zqhej"
|
||||
}
|
||||
],
|
||||
"systemLink": "/my_dev_center_code/0.1.0",
|
||||
"appName": "乐高转码demo",
|
||||
"isFoldHorizontal": "n",
|
||||
"showAppTitle": true,
|
||||
"isFold": "n",
|
||||
"searchBarType": "icon",
|
||||
"singletons": {},
|
||||
"navTheme": "default",
|
||||
"type": "top_side_fold",
|
||||
"navStyle": "orange",
|
||||
"layout": "auto",
|
||||
"bgColor": "white",
|
||||
"languageChangeUrl": "/common/account/changeAccountLanguage.json",
|
||||
"showSearch": "n",
|
||||
"openSubMode": false,
|
||||
"showCrumb": true,
|
||||
"isFixed": "y",
|
||||
"showIcon": false,
|
||||
"showNav": true
|
||||
}
|
||||
},
|
||||
},
|
||||
"theme": {
|
||||
"package": "@alife/theme-fusion",
|
||||
"version": "^0.1.0"
|
||||
},
|
||||
"compDependencies": []
|
||||
}
|
||||
|
||||
`,
|
||||
);
|
||||
|
||||
return [['src','config'], file];
|
||||
}
|
||||
|
||||
@ -0,0 +1,43 @@
|
||||
|
||||
import ResultFile from '../../../../../../../../model/ResultFile';
|
||||
import { IResultFile } from '../../../../../../../../types';
|
||||
|
||||
export default function getFile(): [string[], IResultFile] {
|
||||
const file = new ResultFile(
|
||||
'components',
|
||||
'ts',
|
||||
`
|
||||
/**
|
||||
* 乐高组件
|
||||
*/
|
||||
import Div from '@ali/vc-div/build/view';
|
||||
import Text from '@ali/vc-text/build/view';
|
||||
import Slot from '@ali/vc-slot/build/view';
|
||||
import Deep from '@ali/vc-deep/build/view';
|
||||
import Page from '@ali/vc-page/build/view';
|
||||
import Block from '@ali/vc-block/build/view';
|
||||
|
||||
const components = [Div, Text, Slot, Deep, Page, Block];
|
||||
const componentsMap = {
|
||||
};
|
||||
|
||||
const processComponents = (deps) => {
|
||||
deps.forEach((dep) => {
|
||||
if (Array.isArray(dep)) {
|
||||
processComponents(dep);
|
||||
} else {
|
||||
componentsMap[dep.displayName] = dep;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
processComponents(components);
|
||||
|
||||
export default componentsMap;
|
||||
|
||||
`,
|
||||
);
|
||||
|
||||
return [['src','config'], file];
|
||||
}
|
||||
|
||||
@ -0,0 +1,29 @@
|
||||
|
||||
import ResultFile from '../../../../../../../../model/ResultFile';
|
||||
import { IResultFile } from '../../../../../../../../types';
|
||||
|
||||
export default function getFile(): [string[], IResultFile] {
|
||||
const file = new ResultFile(
|
||||
'utils',
|
||||
'ts',
|
||||
`
|
||||
import toolkit from '@ali/vu-toolkit';
|
||||
import fusion from '@ali/vu-fusion';
|
||||
import dataSource from '@ali/vu-dataSource';
|
||||
import legaoBuiltin from '@ali/vu-legao-builtin';
|
||||
import formatter from '@ali/vu-formatter';
|
||||
|
||||
export default {
|
||||
...toolkit,
|
||||
...fusion,
|
||||
legaoBuiltin,
|
||||
dataSource,
|
||||
formatter
|
||||
}
|
||||
|
||||
`,
|
||||
);
|
||||
|
||||
return [['src','config'], file];
|
||||
}
|
||||
|
||||
@ -0,0 +1,101 @@
|
||||
|
||||
import ResultFile from '../../../../../../../model/ResultFile';
|
||||
import { IResultFile } from '../../../../../../../types';
|
||||
|
||||
export default function getFile(): [string[], IResultFile] {
|
||||
const file = new ResultFile(
|
||||
'index',
|
||||
'ts',
|
||||
`
|
||||
import { app } from '@ali/lowcode-runtime';
|
||||
import { ReactProvider } from '@ali/lowcode-runtime';
|
||||
import Shell from '@ali/vc-shell';
|
||||
import StaticRender from './plugins/provider';
|
||||
import Router from '@/router';
|
||||
import appConfig from '@/config/app';
|
||||
import components from '@/config/components';
|
||||
import utils from '@/config/utils';
|
||||
|
||||
// 定制加载应用配置的逻辑
|
||||
class StaticRender extends ReactProvider {
|
||||
// 初始化时调用,如可以在这里注入全局API
|
||||
init() {
|
||||
const gConfig = (window as any).g_config || {};
|
||||
const LeGao = {
|
||||
__ctx__: {},
|
||||
createContext: (cfg: any) => {
|
||||
const { schema } = cfg || {};
|
||||
// 1. 根据参数拉取schema
|
||||
if (schema && typeof schema === 'string') {
|
||||
this.setHomePage(schema);
|
||||
}
|
||||
const { isSectionalRender, autoRender } = gConfig || {};
|
||||
if (isSectionalRender && !autoRender) {
|
||||
// 2. 渲染
|
||||
this.setSectionalRender();
|
||||
this.ready();
|
||||
}
|
||||
const provider = this;
|
||||
class Context {
|
||||
get utils() {
|
||||
return provider.getUtils();
|
||||
}
|
||||
get components() {
|
||||
return provider.getComponents();
|
||||
}
|
||||
}
|
||||
const ctx = new Context();
|
||||
(LeGao.__ctx__ as any)[this.getContainerId()] = ctx;
|
||||
return ctx;
|
||||
},
|
||||
getContext: (id: string) => {
|
||||
if (!id) {
|
||||
for (id in LeGao.__ctx__) {
|
||||
return (LeGao.__ctx__ as any)[id];
|
||||
}
|
||||
}
|
||||
return (LeGao.__ctx__ as any)[id];
|
||||
}
|
||||
};
|
||||
(window as any).LeGao = LeGao;
|
||||
if (gConfig.index) {
|
||||
this.setHomePage(gConfig.index);
|
||||
}
|
||||
if (gConfig.isSectionalRender) {
|
||||
this.setSectionalRender();
|
||||
if (!gConfig.autoRender) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
this.ready();
|
||||
}
|
||||
|
||||
// 定制获取、处理应用配置(组件、插件、路由模式、布局等)的逻辑
|
||||
getAppData() {
|
||||
return {
|
||||
...appConfig,
|
||||
components,
|
||||
utils: utils,
|
||||
}
|
||||
}
|
||||
|
||||
getRouterView() {
|
||||
return Router;
|
||||
}
|
||||
}
|
||||
|
||||
// 注册布局组件,可注册多个
|
||||
app.registerLayout(Shell, {
|
||||
componentName: 'BasicLayout',
|
||||
});
|
||||
|
||||
app.registerProvider(StaticRender);
|
||||
|
||||
app.run();
|
||||
|
||||
`,
|
||||
);
|
||||
|
||||
return [['src'], file];
|
||||
}
|
||||
|
||||
@ -0,0 +1,21 @@
|
||||
|
||||
import ResultFile from '../../../../../../../model/ResultFile';
|
||||
import { IResultFile } from '../../../../../../../types';
|
||||
|
||||
export default function getFile(): [string[], IResultFile] {
|
||||
const file = new ResultFile(
|
||||
'router',
|
||||
'ts',
|
||||
`
|
||||
export default {
|
||||
baseDir: './pages',
|
||||
exact: true,
|
||||
routes: [
|
||||
{ main: './page_index', path: '/' },
|
||||
],
|
||||
};
|
||||
`,
|
||||
);
|
||||
|
||||
return [['src'], file];
|
||||
}
|
||||
@ -0,0 +1,53 @@
|
||||
|
||||
import ResultFile from '../../../../../../model/ResultFile';
|
||||
import { IResultFile } from '../../../../../../types';
|
||||
|
||||
export default function getFile(): [string[], IResultFile] {
|
||||
const file = new ResultFile(
|
||||
'tsconfig',
|
||||
'json',
|
||||
`
|
||||
{
|
||||
"compilerOptions": {
|
||||
"lib": ["es2015", "dom"],
|
||||
// Target latest version of ECMAScript.
|
||||
"target": "esnext",
|
||||
// Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'.
|
||||
"module": "esnext",
|
||||
// Search under node_modules for non-relative imports.
|
||||
"moduleResolution": "node",
|
||||
// Process & infer types from .js files.
|
||||
"allowJs": true,
|
||||
// Report errors in .js files.
|
||||
"checkJs": false,
|
||||
// Don't emit; allow Babel to transform files.
|
||||
"noEmit": true,
|
||||
// Enable strictest settings like strictNullChecks & noImplicitAny.
|
||||
"strict": true,
|
||||
// Allow default imports from modules with no default export. This does not affect code emit, just typechecking.
|
||||
"allowSyntheticDefaultImports": true,
|
||||
// Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'.
|
||||
"esModuleInterop": true,
|
||||
// Specify JSX code generation: 'preserve', 'react-native', or 'react'.
|
||||
"jsx": "preserve",
|
||||
// Import emit helpers (e.g. __extends, __rest, etc..) from tslib
|
||||
"importHelpers": true,
|
||||
// Enables experimental support for ES7 decorators.
|
||||
"experimentalDecorators": true,
|
||||
// Generates corresponding .map file.
|
||||
"sourceMap": true,
|
||||
// Disallow inconsistently-cased references to the same file.
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
// Allow json import
|
||||
"resolveJsonModule": true,
|
||||
// skip type checking of declaration files
|
||||
"skipLibCheck": true,
|
||||
}
|
||||
}
|
||||
|
||||
`,
|
||||
);
|
||||
|
||||
return [[], file];
|
||||
}
|
||||
|
||||
@ -0,0 +1,54 @@
|
||||
import ResultDir from '../../../../../model/ResultDir';
|
||||
import {
|
||||
IProjectTemplate,
|
||||
IResultDir,
|
||||
} from '../../../../../types';
|
||||
import { runFileGenerator } from '../../../../../utils/templateHelper';
|
||||
|
||||
import file1 from './files/abc.json';
|
||||
import file2 from './files/build.json';
|
||||
import file3 from './files/.editorconfig';
|
||||
import file4 from './files/.eslintignore';
|
||||
import file5 from './files/.gitignore';
|
||||
import file6 from './files/.prettierrc';
|
||||
import file7 from './files/README.md';
|
||||
import file8 from './files/package.json';
|
||||
import file9 from './files/public/index.html';
|
||||
import file10 from './files/src/index.ts';
|
||||
import file11 from './files/src/router.ts';
|
||||
import file13 from './files/src/config/app.ts';
|
||||
import file14 from './files/src/config/components.ts';
|
||||
import file15 from './files/src/config/utils.ts';
|
||||
import file16 from './files/tsconfig.json';
|
||||
|
||||
const icejsTemplate: IProjectTemplate = {
|
||||
slots: {
|
||||
pages: {
|
||||
path: ['src', 'pages'],
|
||||
},
|
||||
},
|
||||
|
||||
generateTemplate(): IResultDir {
|
||||
const root = new ResultDir('.');
|
||||
|
||||
runFileGenerator(root, file1);
|
||||
runFileGenerator(root, file2);
|
||||
runFileGenerator(root, file3);
|
||||
runFileGenerator(root, file4);
|
||||
runFileGenerator(root, file5);
|
||||
runFileGenerator(root, file6);
|
||||
runFileGenerator(root, file7);
|
||||
runFileGenerator(root, file8);
|
||||
runFileGenerator(root, file9);
|
||||
runFileGenerator(root, file10);
|
||||
runFileGenerator(root, file11);
|
||||
runFileGenerator(root, file13);
|
||||
runFileGenerator(root, file14);
|
||||
runFileGenerator(root, file15);
|
||||
runFileGenerator(root, file16);
|
||||
|
||||
return root;
|
||||
},
|
||||
};
|
||||
|
||||
export default icejsTemplate;
|
||||
@ -1,66 +1,69 @@
|
||||
import { COMMON_CHUNK_NAME } from '../../const/generator';
|
||||
import { generateCompositeType } from '../../plugins/utils/compositeType';
|
||||
import { generateCompositeType } from '../../utils/compositeType';
|
||||
import {
|
||||
BuilderComponentPlugin,
|
||||
BuilderComponentPluginFactory,
|
||||
ChunkType,
|
||||
FileType,
|
||||
ICodeStruct,
|
||||
IProjectInfo,
|
||||
} from '../../types';
|
||||
|
||||
// TODO: How to merge this logic to common deps
|
||||
const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => {
|
||||
const next: ICodeStruct = {
|
||||
...pre,
|
||||
const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
|
||||
const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => {
|
||||
const next: ICodeStruct = {
|
||||
...pre,
|
||||
};
|
||||
|
||||
const ir = next.ir as IProjectInfo;
|
||||
if (ir.i18n) {
|
||||
const [, i18nStr] = generateCompositeType(ir.i18n);
|
||||
|
||||
next.chunks.push({
|
||||
type: ChunkType.STRING,
|
||||
fileType: FileType.JS,
|
||||
name: COMMON_CHUNK_NAME.FileMainContent,
|
||||
content: `
|
||||
const i18nConfig = ${i18nStr};
|
||||
let locale = 'en_US';
|
||||
|
||||
const changeLocale = (target) => {
|
||||
locale = target;
|
||||
};
|
||||
|
||||
const i18n = key => i18nConfig && i18nConfig[locale] && i18nConfig[locale][key] || '';
|
||||
`,
|
||||
linkAfter: [
|
||||
COMMON_CHUNK_NAME.ExternalDepsImport,
|
||||
COMMON_CHUNK_NAME.InternalDepsImport,
|
||||
COMMON_CHUNK_NAME.FileVarDefine,
|
||||
COMMON_CHUNK_NAME.FileUtilDefine,
|
||||
],
|
||||
});
|
||||
|
||||
next.chunks.push({
|
||||
type: ChunkType.STRING,
|
||||
fileType: FileType.JS,
|
||||
name: COMMON_CHUNK_NAME.FileExport,
|
||||
content: `
|
||||
export {
|
||||
changeLocale,
|
||||
i18n,
|
||||
};
|
||||
`,
|
||||
linkAfter: [
|
||||
COMMON_CHUNK_NAME.ExternalDepsImport,
|
||||
COMMON_CHUNK_NAME.InternalDepsImport,
|
||||
COMMON_CHUNK_NAME.FileVarDefine,
|
||||
COMMON_CHUNK_NAME.FileUtilDefine,
|
||||
COMMON_CHUNK_NAME.FileMainContent,
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
return next;
|
||||
};
|
||||
|
||||
const ir = next.ir as IProjectInfo;
|
||||
if (ir.i18n) {
|
||||
const [, i18nStr] = generateCompositeType(ir.i18n);
|
||||
|
||||
next.chunks.push({
|
||||
type: ChunkType.STRING,
|
||||
fileType: FileType.JS,
|
||||
name: COMMON_CHUNK_NAME.FileMainContent,
|
||||
content: `
|
||||
const i18nConfig = ${i18nStr};
|
||||
let locale = 'en_US';
|
||||
|
||||
const changeLocale = (target) => {
|
||||
locale = target;
|
||||
};
|
||||
|
||||
const i18n = key => i18nConfig && i18nConfig[locale] && i18nConfig[locale][key] || '';
|
||||
`,
|
||||
linkAfter: [
|
||||
COMMON_CHUNK_NAME.ExternalDepsImport,
|
||||
COMMON_CHUNK_NAME.InternalDepsImport,
|
||||
COMMON_CHUNK_NAME.FileVarDefine,
|
||||
COMMON_CHUNK_NAME.FileUtilDefine,
|
||||
],
|
||||
});
|
||||
|
||||
next.chunks.push({
|
||||
type: ChunkType.STRING,
|
||||
fileType: FileType.JS,
|
||||
name: COMMON_CHUNK_NAME.FileExport,
|
||||
content: `
|
||||
export {
|
||||
changeLocale,
|
||||
i18n,
|
||||
};
|
||||
`,
|
||||
linkAfter: [
|
||||
COMMON_CHUNK_NAME.ExternalDepsImport,
|
||||
COMMON_CHUNK_NAME.InternalDepsImport,
|
||||
COMMON_CHUNK_NAME.FileVarDefine,
|
||||
COMMON_CHUNK_NAME.FileUtilDefine,
|
||||
COMMON_CHUNK_NAME.FileMainContent,
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
return next;
|
||||
return plugin;
|
||||
};
|
||||
|
||||
export default plugin;
|
||||
export default pluginFactory;
|
||||
|
||||
@ -2,59 +2,28 @@ import { COMMON_CHUNK_NAME } from '../../const/generator';
|
||||
|
||||
import {
|
||||
BuilderComponentPlugin,
|
||||
BuilderComponentPluginFactory,
|
||||
ChunkType,
|
||||
FileType,
|
||||
ICodeStruct,
|
||||
IUtilInfo,
|
||||
} from '../../types';
|
||||
|
||||
// TODO: How to merge this logic to common deps
|
||||
const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => {
|
||||
const next: ICodeStruct = {
|
||||
...pre,
|
||||
};
|
||||
const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
|
||||
const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => {
|
||||
const next: ICodeStruct = {
|
||||
...pre,
|
||||
};
|
||||
|
||||
const ir = next.ir as IUtilInfo;
|
||||
|
||||
if (ir.utils) {
|
||||
next.chunks.push({
|
||||
type: ChunkType.STRING,
|
||||
fileType: FileType.JS,
|
||||
name: COMMON_CHUNK_NAME.FileExport,
|
||||
content: `
|
||||
export default {
|
||||
`,
|
||||
linkAfter: [
|
||||
COMMON_CHUNK_NAME.ExternalDepsImport,
|
||||
COMMON_CHUNK_NAME.InternalDepsImport,
|
||||
COMMON_CHUNK_NAME.FileVarDefine,
|
||||
COMMON_CHUNK_NAME.FileUtilDefine,
|
||||
COMMON_CHUNK_NAME.FileMainContent,
|
||||
],
|
||||
});
|
||||
|
||||
ir.utils.forEach(util => {
|
||||
if (util.type === 'function') {
|
||||
next.chunks.push({
|
||||
type: ChunkType.STRING,
|
||||
fileType: FileType.JS,
|
||||
name: COMMON_CHUNK_NAME.FileVarDefine,
|
||||
content: `
|
||||
const ${util.name} = ${util.content};
|
||||
`,
|
||||
linkAfter: [
|
||||
COMMON_CHUNK_NAME.ExternalDepsImport,
|
||||
COMMON_CHUNK_NAME.InternalDepsImport,
|
||||
],
|
||||
});
|
||||
}
|
||||
const ir = next.ir as IUtilInfo;
|
||||
|
||||
if (ir.utils) {
|
||||
next.chunks.push({
|
||||
type: ChunkType.STRING,
|
||||
fileType: FileType.JS,
|
||||
name: COMMON_CHUNK_NAME.FileExport,
|
||||
content: `
|
||||
${util.name},
|
||||
export default {
|
||||
`,
|
||||
linkAfter: [
|
||||
COMMON_CHUNK_NAME.ExternalDepsImport,
|
||||
@ -64,26 +33,60 @@ const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => {
|
||||
COMMON_CHUNK_NAME.FileMainContent,
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
next.chunks.push({
|
||||
type: ChunkType.STRING,
|
||||
fileType: FileType.JS,
|
||||
name: COMMON_CHUNK_NAME.FileExport,
|
||||
content: `
|
||||
};
|
||||
`,
|
||||
linkAfter: [
|
||||
COMMON_CHUNK_NAME.ExternalDepsImport,
|
||||
COMMON_CHUNK_NAME.InternalDepsImport,
|
||||
COMMON_CHUNK_NAME.FileVarDefine,
|
||||
COMMON_CHUNK_NAME.FileUtilDefine,
|
||||
COMMON_CHUNK_NAME.FileMainContent,
|
||||
],
|
||||
});
|
||||
}
|
||||
ir.utils.forEach(util => {
|
||||
if (util.type === 'function') {
|
||||
next.chunks.push({
|
||||
type: ChunkType.STRING,
|
||||
fileType: FileType.JS,
|
||||
name: COMMON_CHUNK_NAME.FileVarDefine,
|
||||
content: `
|
||||
const ${util.name} = ${util.content};
|
||||
`,
|
||||
linkAfter: [
|
||||
COMMON_CHUNK_NAME.ExternalDepsImport,
|
||||
COMMON_CHUNK_NAME.InternalDepsImport,
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
return next;
|
||||
next.chunks.push({
|
||||
type: ChunkType.STRING,
|
||||
fileType: FileType.JS,
|
||||
name: COMMON_CHUNK_NAME.FileExport,
|
||||
content: `
|
||||
${util.name},
|
||||
`,
|
||||
linkAfter: [
|
||||
COMMON_CHUNK_NAME.ExternalDepsImport,
|
||||
COMMON_CHUNK_NAME.InternalDepsImport,
|
||||
COMMON_CHUNK_NAME.FileVarDefine,
|
||||
COMMON_CHUNK_NAME.FileUtilDefine,
|
||||
COMMON_CHUNK_NAME.FileMainContent,
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
next.chunks.push({
|
||||
type: ChunkType.STRING,
|
||||
fileType: FileType.JS,
|
||||
name: COMMON_CHUNK_NAME.FileExport,
|
||||
content: `
|
||||
};
|
||||
`,
|
||||
linkAfter: [
|
||||
COMMON_CHUNK_NAME.ExternalDepsImport,
|
||||
COMMON_CHUNK_NAME.InternalDepsImport,
|
||||
COMMON_CHUNK_NAME.FileVarDefine,
|
||||
COMMON_CHUNK_NAME.FileUtilDefine,
|
||||
COMMON_CHUNK_NAME.FileMainContent,
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
return next;
|
||||
};
|
||||
return plugin;
|
||||
};
|
||||
|
||||
export default plugin;
|
||||
export default pluginFactory;
|
||||
|
||||
@ -1,45 +0,0 @@
|
||||
import { CompositeArray, CompositeValue, ICompositeObject } from '../../types';
|
||||
import { generateValue, isJsExpression } from './jsExpression';
|
||||
|
||||
function generateArray(value: CompositeArray): string {
|
||||
const body = value.map(v => generateUnknownType(v)).join(',');
|
||||
return `[${body}]`;
|
||||
}
|
||||
|
||||
function generateObject(value: ICompositeObject): string {
|
||||
if (isJsExpression(value)) {
|
||||
return generateValue(value);
|
||||
}
|
||||
|
||||
const body = Object.keys(value)
|
||||
.map(key => {
|
||||
const v = generateUnknownType(value[key]);
|
||||
return `${key}: ${v}`;
|
||||
})
|
||||
.join(',');
|
||||
|
||||
return `{${body}}`;
|
||||
}
|
||||
|
||||
function generateUnknownType(value: CompositeValue): string {
|
||||
if (Array.isArray(value)) {
|
||||
return generateArray(value as CompositeArray);
|
||||
} else if (typeof value === 'object') {
|
||||
return generateObject(value as ICompositeObject);
|
||||
} else if (typeof value === 'string') {
|
||||
return `'${value}'`;
|
||||
}
|
||||
return `${value}`;
|
||||
}
|
||||
|
||||
export function generateCompositeType(
|
||||
value: CompositeValue,
|
||||
): [boolean, string] {
|
||||
const result = generateUnknownType(value);
|
||||
|
||||
if (result.substr(0, 1) === "'" && result.substr(-1, 1) === "'") {
|
||||
return [true, result.substring(1, result.length - 1)];
|
||||
}
|
||||
|
||||
return [false, result];
|
||||
}
|
||||
@ -1,39 +0,0 @@
|
||||
import { CodeGeneratorError, IJSExpression } from '../../types';
|
||||
|
||||
export function transformFuncExpr2MethodMember(
|
||||
methodName: string,
|
||||
functionBody: string,
|
||||
): string {
|
||||
if (functionBody.indexOf('function') < 8) {
|
||||
return functionBody.replace('function', methodName);
|
||||
}
|
||||
return functionBody;
|
||||
}
|
||||
|
||||
export function getFuncExprBody(functionBody: string) {
|
||||
const start = functionBody.indexOf('{');
|
||||
const end = functionBody.lastIndexOf('}');
|
||||
|
||||
if (start < 0 || end < 0 || end < start) {
|
||||
throw new CodeGeneratorError('JSExpression has no valid body.');
|
||||
}
|
||||
|
||||
const body = functionBody.slice(start + 1, end);
|
||||
return body;
|
||||
}
|
||||
|
||||
export function generateValue(value: any): string {
|
||||
if (value && (value as IJSExpression).type === 'JSExpression') {
|
||||
return (value as IJSExpression).value;
|
||||
}
|
||||
|
||||
throw new CodeGeneratorError('Not a JSExpression');
|
||||
}
|
||||
|
||||
export function isJsExpression(value: any): boolean {
|
||||
return (
|
||||
value &&
|
||||
typeof value === 'object' &&
|
||||
(value as IJSExpression).type === 'JSExpression'
|
||||
);
|
||||
}
|
||||
@ -1,22 +1,42 @@
|
||||
import prettier from 'prettier';
|
||||
import mypretter from '@ali/my-prettier';
|
||||
|
||||
import { PostProcessor } from '../../types';
|
||||
import { PostProcessor, PostProcessorFactory } from '../../types';
|
||||
|
||||
const PARSERS = ['css', 'scss', 'less', 'json', 'html', 'vue'];
|
||||
|
||||
const codePrettier: PostProcessor = (content: string, fileType: string) => {
|
||||
let parser: prettier.BuiltInParserName;
|
||||
if (fileType === 'js' || fileType === 'jsx') {
|
||||
parser = 'babel';
|
||||
} else if (PARSERS.indexOf(fileType) >= 0) {
|
||||
parser = fileType as prettier.BuiltInParserName;
|
||||
} else {
|
||||
return content;
|
||||
}
|
||||
interface ProcessorConfig {
|
||||
customFileTypeParser: Record<string, string>;
|
||||
}
|
||||
|
||||
return prettier.format(content, {
|
||||
parser,
|
||||
});
|
||||
const factory: PostProcessorFactory<ProcessorConfig> = (config?: ProcessorConfig) => {
|
||||
const cfg: ProcessorConfig = {
|
||||
customFileTypeParser: {},
|
||||
...config,
|
||||
};
|
||||
|
||||
const codePrettier: PostProcessor = (content: string, fileType: string) => {
|
||||
let parser: prettier.BuiltInParserName;
|
||||
if (fileType === 'js' || fileType === 'jsx') {
|
||||
parser = 'babel';
|
||||
} else if (fileType === 'ts' || fileType === 'tsx') {
|
||||
parser = 'typescript';
|
||||
} else if (PARSERS.indexOf(fileType) >= 0) {
|
||||
parser = fileType as prettier.BuiltInParserName;
|
||||
} else if (cfg.customFileTypeParser[fileType]){
|
||||
parser = cfg.customFileTypeParser[fileType] as prettier.BuiltInParserName;
|
||||
} else if (fileType === 'vx') {
|
||||
return mypretter(content, fileType);
|
||||
} else {
|
||||
return content;
|
||||
}
|
||||
|
||||
return prettier.format(content, {
|
||||
parser,
|
||||
});
|
||||
};
|
||||
|
||||
return codePrettier;
|
||||
};
|
||||
|
||||
export default codePrettier;
|
||||
export default factory;
|
||||
|
||||
@ -28,36 +28,40 @@ export default function createIceJsProjectBuilder(): IProjectBuilder {
|
||||
template,
|
||||
plugins: {
|
||||
components: [
|
||||
reactCommonDeps,
|
||||
esmodule,
|
||||
containerClass,
|
||||
containerInjectUtils,
|
||||
containerInitState,
|
||||
containerLifeCycle,
|
||||
containerMethod,
|
||||
jsx,
|
||||
css,
|
||||
reactCommonDeps(),
|
||||
esmodule({
|
||||
fileType: 'jsx',
|
||||
}),
|
||||
containerClass(),
|
||||
containerInjectUtils(),
|
||||
containerInitState(),
|
||||
containerLifeCycle(),
|
||||
containerMethod(),
|
||||
jsx(),
|
||||
css(),
|
||||
],
|
||||
pages: [
|
||||
reactCommonDeps,
|
||||
esmodule,
|
||||
containerClass,
|
||||
containerInjectUtils,
|
||||
containerInitState,
|
||||
containerLifeCycle,
|
||||
containerMethod,
|
||||
jsx,
|
||||
css,
|
||||
reactCommonDeps(),
|
||||
esmodule({
|
||||
fileType: 'jsx',
|
||||
}),
|
||||
containerClass(),
|
||||
containerInjectUtils(),
|
||||
containerInitState(),
|
||||
containerLifeCycle(),
|
||||
containerMethod(),
|
||||
jsx(),
|
||||
css(),
|
||||
],
|
||||
router: [esmodule, iceJsRouter],
|
||||
entry: [iceJsEntry],
|
||||
constants: [constants],
|
||||
utils: [esmodule, utils],
|
||||
i18n: [i18n],
|
||||
globalStyle: [iceJsGlobalStyle],
|
||||
htmlEntry: [iceJsEntryHtml],
|
||||
packageJSON: [iceJsPackageJSON],
|
||||
router: [esmodule(), iceJsRouter()],
|
||||
entry: [iceJsEntry()],
|
||||
constants: [constants()],
|
||||
utils: [esmodule(), utils()],
|
||||
i18n: [i18n()],
|
||||
globalStyle: [iceJsGlobalStyle()],
|
||||
htmlEntry: [iceJsEntryHtml()],
|
||||
packageJSON: [iceJsPackageJSON()],
|
||||
},
|
||||
postProcessors: [prettier],
|
||||
postProcessors: [prettier()],
|
||||
});
|
||||
}
|
||||
|
||||
51
packages/code-generator/src/solutions/recore.ts
Normal file
51
packages/code-generator/src/solutions/recore.ts
Normal file
@ -0,0 +1,51 @@
|
||||
import { IProjectBuilder } from '../types';
|
||||
|
||||
import { createProjectBuilder } from '../generator/ProjectBuilder';
|
||||
|
||||
// import esmodule from '../plugins/common/esmodule';
|
||||
import containerInitState from '../plugins/component/react/containerInitState';
|
||||
import containerLifeCycle from '../plugins/component/react/containerLifeCycle';
|
||||
import containerMethod from '../plugins/component/react/containerMethod';
|
||||
import pageFrame from '../plugins/component/recore/pageFrame';
|
||||
import pageStyle from '../plugins/component/recore/pageStyle';
|
||||
import pageVmHeader from '../plugins/component/recore/pageVmHeader';
|
||||
import pageVmBody from '../plugins/component/recore/pageVmBody';
|
||||
import pageDataSource from '../plugins/component/recore/pageDataSource';
|
||||
import template from '../plugins/project/framework/recore/template';
|
||||
|
||||
import { prettier } from '../postprocessor';
|
||||
|
||||
export default function createRecoreProjectBuilder(): IProjectBuilder {
|
||||
return createProjectBuilder({
|
||||
template,
|
||||
plugins: {
|
||||
pages: [
|
||||
pageFrame(),
|
||||
pageStyle(),
|
||||
containerInitState({
|
||||
fileType: 'ts',
|
||||
implementType: 'insMember',
|
||||
}),
|
||||
containerLifeCycle({
|
||||
fileType: 'ts',
|
||||
exportNameMapping: {
|
||||
constructor: 'init',
|
||||
componentDidMount: 'didMount',
|
||||
willUnmount: 'willUnMount',
|
||||
componentWillUnmount: 'willUnMount',
|
||||
},
|
||||
normalizeNameMapping: {
|
||||
init: 'constructor',
|
||||
},
|
||||
}),
|
||||
containerMethod({
|
||||
fileType: 'ts',
|
||||
}),
|
||||
pageDataSource(),
|
||||
pageVmHeader(),
|
||||
pageVmBody(),
|
||||
],
|
||||
},
|
||||
postProcessors: [prettier()],
|
||||
});
|
||||
}
|
||||
@ -4,6 +4,8 @@ import {
|
||||
IProjectSchema,
|
||||
IResultDir,
|
||||
IResultFile,
|
||||
IComponentNodeItem,
|
||||
IJSExpression,
|
||||
} from './index';
|
||||
|
||||
export enum FileType {
|
||||
@ -12,6 +14,8 @@ export enum FileType {
|
||||
HTML = 'html',
|
||||
JS = 'js',
|
||||
JSX = 'jsx',
|
||||
TS = 'ts',
|
||||
TSX = 'tsx',
|
||||
JSON = 'json',
|
||||
}
|
||||
|
||||
@ -32,7 +36,7 @@ export type CodeGeneratorFunction<T> = (content: T) => string;
|
||||
|
||||
export interface ICodeChunk {
|
||||
type: ChunkType;
|
||||
fileType: FileType;
|
||||
fileType: string;
|
||||
name: string;
|
||||
subModule?: string;
|
||||
content: ChunkContent;
|
||||
@ -53,6 +57,8 @@ export type BuilderComponentPlugin = (
|
||||
initStruct: ICodeStruct,
|
||||
) => Promise<ICodeStruct>;
|
||||
|
||||
export type BuilderComponentPluginFactory<T> = (config?: T) => BuilderComponentPlugin;
|
||||
|
||||
export interface IChunkBuilder {
|
||||
run(
|
||||
ir: any,
|
||||
@ -72,12 +78,13 @@ export interface ICompiledModule {
|
||||
}
|
||||
|
||||
export interface IModuleBuilder {
|
||||
generateModule: (input: unknown) => Promise<ICompiledModule>;
|
||||
linkCodeChunks: (
|
||||
generateModule(input: unknown): Promise<ICompiledModule>;
|
||||
generateModuleCode(schema: IBasicSchema | string): Promise<IResultDir>;
|
||||
linkCodeChunks(
|
||||
chunks: Record<string, ICodeChunk[]>,
|
||||
fileName: string,
|
||||
) => IResultFile[];
|
||||
addPlugin: (plugin: BuilderComponentPlugin) => void;
|
||||
): IResultFile[];
|
||||
addPlugin(plugin: BuilderComponentPlugin): void;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -99,11 +106,11 @@ export interface ICodeGenerator {
|
||||
|
||||
export interface ISchemaParser {
|
||||
validate(schema: IBasicSchema): boolean;
|
||||
parse(schema: IBasicSchema): IParseResult;
|
||||
parse(schema: IBasicSchema | string): IParseResult;
|
||||
}
|
||||
|
||||
export interface IProjectTemplate {
|
||||
slots: IProjectSlots;
|
||||
slots: Record<string, IProjectSlot>;
|
||||
generateTemplate(): IResultDir;
|
||||
}
|
||||
|
||||
@ -112,39 +119,59 @@ export interface IProjectSlot {
|
||||
fileName?: string;
|
||||
}
|
||||
|
||||
export interface IProjectSlots {
|
||||
components: IProjectSlot;
|
||||
pages: IProjectSlot;
|
||||
router: IProjectSlot;
|
||||
entry: IProjectSlot;
|
||||
constants?: IProjectSlot;
|
||||
utils?: IProjectSlot;
|
||||
i18n?: IProjectSlot;
|
||||
globalStyle: IProjectSlot;
|
||||
htmlEntry: IProjectSlot;
|
||||
packageJSON: IProjectSlot;
|
||||
}
|
||||
// export interface IProjectSlots {
|
||||
// components: IProjectSlot;
|
||||
// pages: IProjectSlot;
|
||||
// router: IProjectSlot;
|
||||
// entry: IProjectSlot;
|
||||
// constants?: IProjectSlot;
|
||||
// utils?: IProjectSlot;
|
||||
// i18n?: IProjectSlot;
|
||||
// globalStyle: IProjectSlot;
|
||||
// htmlEntry: IProjectSlot;
|
||||
// packageJSON: IProjectSlot;
|
||||
// }
|
||||
|
||||
export interface IProjectPlugins {
|
||||
components: BuilderComponentPlugin[];
|
||||
pages: BuilderComponentPlugin[];
|
||||
router: BuilderComponentPlugin[];
|
||||
entry: BuilderComponentPlugin[];
|
||||
constants?: BuilderComponentPlugin[];
|
||||
utils?: BuilderComponentPlugin[];
|
||||
i18n?: BuilderComponentPlugin[];
|
||||
globalStyle: BuilderComponentPlugin[];
|
||||
htmlEntry: BuilderComponentPlugin[];
|
||||
packageJSON: BuilderComponentPlugin[];
|
||||
[slotName: string]: BuilderComponentPlugin[];
|
||||
}
|
||||
|
||||
export interface IProjectBuilder {
|
||||
generateProject(schema: IProjectSchema): Promise<IResultDir>;
|
||||
generateProject(schema: IProjectSchema | string): Promise<IResultDir>;
|
||||
}
|
||||
|
||||
export type PostProcessorFactory<T> = (config?: T) => PostProcessor;
|
||||
export type PostProcessor = (content: string, fileType: string) => string;
|
||||
|
||||
// TODO: temp interface, need modify
|
||||
export interface IPluginOptions {
|
||||
fileDirDepth: number;
|
||||
}
|
||||
|
||||
export enum PIECE_TYPE {
|
||||
BEFORE = 'NodeCodePieceBefore',
|
||||
TAG = 'NodeCodePieceTag',
|
||||
ATTR = 'NodeCodePieceAttr',
|
||||
CHILDREN = 'NodeCodePieceChildren',
|
||||
AFTER = 'NodeCodePieceAfter',
|
||||
};
|
||||
|
||||
export interface CodePiece {
|
||||
value: string;
|
||||
type: PIECE_TYPE;
|
||||
}
|
||||
|
||||
export interface HandlerSet<T> {
|
||||
string?: (input: string) => T[];
|
||||
expression?: (input: IJSExpression) => T[];
|
||||
node?: (input: IComponentNodeItem) => T[];
|
||||
common?: (input: unknown) => T[];
|
||||
}
|
||||
|
||||
export type ExtGeneratorPlugin = (nodeItem: IComponentNodeItem) => CodePiece[];
|
||||
|
||||
// export interface InteratorScope {
|
||||
// [$item: string]: string; // $item 默认取值 "item"
|
||||
// [$index: string]: string | number; // $index 默认取值 "index"
|
||||
// __proto__: BlockInstance;
|
||||
// }
|
||||
|
||||
@ -17,8 +17,8 @@ export interface IParseResult {
|
||||
}
|
||||
|
||||
export interface IContainerInfo extends IContainerNodeItem, IWithDependency {
|
||||
componentName: string;
|
||||
containerType: string;
|
||||
moduleName: string;
|
||||
}
|
||||
|
||||
export interface IWithDependency {
|
||||
|
||||
@ -10,6 +10,7 @@ import { IExternalDependency } from './index';
|
||||
export interface IJSExpression {
|
||||
type: 'JSExpression';
|
||||
value: string;
|
||||
[extConfigName: string]: any;
|
||||
}
|
||||
|
||||
// JSON 基本类型
|
||||
@ -87,10 +88,6 @@ export interface IUtilItem {
|
||||
content: IExternalDependency | IJSExpression;
|
||||
}
|
||||
|
||||
export interface IInlineStyle {
|
||||
[cssAttribute: string]: string | number | IJSExpression;
|
||||
}
|
||||
|
||||
export type ChildNodeItem = string | IJSExpression | IComponentNodeItem;
|
||||
export type ChildNodeType = ChildNodeItem | ChildNodeItem[];
|
||||
|
||||
@ -106,9 +103,7 @@ export interface IComponentNodeItem {
|
||||
id?: string;
|
||||
componentName: string; // 组件名称 必填、首字母大写
|
||||
props: {
|
||||
className?: string; // 组件样式类名
|
||||
style?: IInlineStyle; // 组件内联样式
|
||||
[propName: string]: any; // 业务属性
|
||||
[propName: string]: CompositeValue; // 业务属性
|
||||
}; // 组件属性对象
|
||||
condition?: CompositeValue; // 渲染条件
|
||||
loop?: CompositeValue; // 循环数据
|
||||
@ -124,15 +119,12 @@ export interface IComponentNodeItem {
|
||||
* @extends {IComponentNodeItem}
|
||||
*/
|
||||
export interface IContainerNodeItem extends IComponentNodeItem {
|
||||
componentName: string; // 'Page' | 'Block' | 'Component' 组件类型 必填、首字母大写
|
||||
componentName: 'Page' | 'Block' | 'Component'; // 'Page' | 'Block' | 'Component' 组件类型 必填、首字母大写
|
||||
fileName: string; // 文件名称 必填、英文
|
||||
defaultProps?: {
|
||||
[propName: string]: any; // 业务属性
|
||||
};
|
||||
state?: {
|
||||
[stateName: string]: any; // 容器初始数据
|
||||
[stateName: string]: CompositeValue; // 容器初始数据
|
||||
};
|
||||
css: string; // 样式文件 用于描述容器组件内部节点的样式,对应生成一个独立的样式文件,在对应容器组件生成的 .jsx 文件中 import 引入;
|
||||
css?: string; // 样式文件 用于描述容器组件内部节点的样式,对应生成一个独立的样式文件,在对应容器组件生成的 .jsx 文件中 import 引入;
|
||||
/**
|
||||
* LifeCycle
|
||||
* • constructor(props, context)
|
||||
@ -144,37 +136,14 @@ export interface IContainerNodeItem extends IComponentNodeItem {
|
||||
* • componentWillUnmount()
|
||||
* • componentDidCatch(error, info)
|
||||
*/
|
||||
lifeCycles?: {
|
||||
constructor?: IJSExpression;
|
||||
render?: IJSExpression;
|
||||
componentDidMount?: IJSExpression;
|
||||
componentDidUpdate?: IJSExpression;
|
||||
componentWillUnmount?: IJSExpression;
|
||||
componentDidCatch?: IJSExpression;
|
||||
}; // 生命周期Hook方法
|
||||
methods?: {
|
||||
[methodName: string]: IJSExpression;
|
||||
}; // 自定义方法设置
|
||||
dataSource?: IDataSource; // 异步数据源配置
|
||||
lifeCycles?: Record<string, IJSExpression>; // 生命周期Hook方法
|
||||
methods?: Record<string, IJSExpression>; // 自定义方法设置
|
||||
dataSource?: {
|
||||
list: IDataSourceConfig[];
|
||||
}; // 异步数据源配置
|
||||
meta?: IBasicMeta | IPageMeta;
|
||||
}
|
||||
|
||||
/**
|
||||
* 搭建基础协议 - 数据源
|
||||
*
|
||||
* @export
|
||||
* @interface IDataSource
|
||||
*/
|
||||
export interface IDataSource {
|
||||
list: IDataSourceConfig[]; // 成为为单个请求配置
|
||||
/**
|
||||
* 参数:为dataMap对象,key:数据id, value: 单个请求结果
|
||||
* 返回值:数据对象data,将会在渲染引擎和schemaToCode中通过调用this.setState(...)将返回的数据对象生效到state中;
|
||||
* 支持返回一个Promise,通过resolve(返回数据),常用于串型发送请求场景,配合this.dataSourceMap[oneRequest.id].load()使用;
|
||||
*/
|
||||
dataHandler?: IJSExpression;
|
||||
}
|
||||
|
||||
/**
|
||||
* 搭建基础协议 - 数据源单个配置
|
||||
*
|
||||
@ -184,7 +153,7 @@ export interface IDataSource {
|
||||
export interface IDataSourceConfig {
|
||||
id: string; // 数据请求ID标识
|
||||
isInit: boolean; // 是否为初始数据 支持表达式 值为true时,将在组件初始化渲染时自动发送当前数据请求
|
||||
type: 'fetch' | 'mtop' | 'jsonp' | 'custom' | 'doServer'; // 数据请求类型
|
||||
type: string; // 数据请求类型 'fetch' | 'mtop' | 'jsonp' | 'custom'
|
||||
requestHandler?: IJSExpression; // 自定义扩展的外部请求处理器 仅type='custom'时生效
|
||||
options?: IFetchOptions; // 请求参数配置 每种请求类型对应不同参数
|
||||
dataHandler?: IJSExpression; // 数据结果处理函数,形如:(data, err) => Object
|
||||
@ -197,7 +166,7 @@ export interface IDataSourceConfig {
|
||||
* @interface IFetchOptions
|
||||
*/
|
||||
export interface IFetchOptions {
|
||||
uri: string; // 请求地址 支持表达式
|
||||
url: string; // 请求地址 支持表达式
|
||||
params?: {
|
||||
// 请求参数
|
||||
[key: string]: any;
|
||||
@ -209,6 +178,7 @@ export interface IFetchOptions {
|
||||
// 自定义请求头
|
||||
[key: string]: string;
|
||||
};
|
||||
[extConfigName: string]: any;
|
||||
}
|
||||
|
||||
export interface IBasicMeta {
|
||||
@ -252,4 +222,5 @@ export interface IAppMeta {
|
||||
description?: string; // 应用描述
|
||||
spma?: string; // 应用spma A位信息
|
||||
creator?: string; // author
|
||||
[otherAttrName: string]: any;
|
||||
}
|
||||
|
||||
@ -1,35 +0,0 @@
|
||||
import {
|
||||
ChildNodeItem,
|
||||
ChildNodeType,
|
||||
IComponentNodeItem,
|
||||
IJSExpression,
|
||||
} from '../types';
|
||||
|
||||
// tslint:disable-next-line: no-empty
|
||||
const noop = () => [];
|
||||
|
||||
export function handleChildren<T>(
|
||||
children: ChildNodeType,
|
||||
handlers: {
|
||||
string?: (input: string) => T[];
|
||||
expression?: (input: IJSExpression) => T[];
|
||||
node?: (input: IComponentNodeItem) => T[];
|
||||
common?: (input: unknown) => T[];
|
||||
},
|
||||
): T[] {
|
||||
if (Array.isArray(children)) {
|
||||
const list: ChildNodeItem[] = children as ChildNodeItem[];
|
||||
return list
|
||||
.map(child => handleChildren(child, handlers))
|
||||
.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') {
|
||||
const handler = handlers.expression || handlers.common || noop;
|
||||
return handler(children as IJSExpression);
|
||||
} else {
|
||||
const handler = handlers.node || handlers.common || noop;
|
||||
return handler(children as IComponentNodeItem);
|
||||
}
|
||||
}
|
||||
88
packages/code-generator/src/utils/compositeType.ts
Normal file
88
packages/code-generator/src/utils/compositeType.ts
Normal file
@ -0,0 +1,88 @@
|
||||
import { CompositeArray, CompositeValue, ICompositeObject } from '../types';
|
||||
import { generateExpression, isJsExpression } from './jsExpression';
|
||||
|
||||
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(',');
|
||||
return `[${body}]`;
|
||||
}
|
||||
|
||||
function generateObject(
|
||||
value: ICompositeObject,
|
||||
handlers: CustomHandlerSet = {},
|
||||
): string {
|
||||
if (isJsExpression(value)) {
|
||||
if (handlers.expression) {
|
||||
return handlers.expression(value);
|
||||
}
|
||||
return generateExpression(value);
|
||||
}
|
||||
|
||||
const body = Object.keys(value)
|
||||
.map(key => {
|
||||
const v = generateUnknownType(value[key], handlers);
|
||||
return `${key}: ${v}`;
|
||||
})
|
||||
.join(',\n');
|
||||
|
||||
return `{${body}}`;
|
||||
}
|
||||
|
||||
export function generateUnknownType(
|
||||
value: CompositeValue,
|
||||
handlers: CustomHandlerSet = {},
|
||||
): string {
|
||||
if (Array.isArray(value)) {
|
||||
if (handlers.array) {
|
||||
return handlers.array(value);
|
||||
}
|
||||
return generateArray(value as CompositeArray, handlers);
|
||||
} else if (typeof value === 'object') {
|
||||
if (handlers.object) {
|
||||
return handlers.object(value);
|
||||
}
|
||||
return generateObject(value as ICompositeObject, handlers);
|
||||
} else if (typeof value === 'string') {
|
||||
if (handlers.string) {
|
||||
return 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);
|
||||
}
|
||||
return `${value}`;
|
||||
}
|
||||
|
||||
export function generateCompositeType(
|
||||
value: CompositeValue,
|
||||
handlers: CustomHandlerSet = {},
|
||||
): [boolean, string] {
|
||||
const result = generateUnknownType(value, handlers);
|
||||
|
||||
if (result.substr(0, 1) === "'" && result.substr(-1, 1) === "'") {
|
||||
return [true, result.substring(1, result.length - 1)];
|
||||
}
|
||||
|
||||
return [false, result];
|
||||
}
|
||||
|
||||
export function handleStringValueDefault([isString, result]: [boolean, string]) {
|
||||
if (isString) {
|
||||
return `'${result}'`;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
85
packages/code-generator/src/utils/jsExpression.ts
Normal file
85
packages/code-generator/src/utils/jsExpression.ts
Normal file
@ -0,0 +1,85 @@
|
||||
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);
|
||||
|
||||
const args = getFuncExprArguments(functionBody);
|
||||
const body = getFuncExprBody(functionBody);
|
||||
|
||||
return `${methodName}(${args}) { ${body} }`;
|
||||
}
|
||||
|
||||
export function getFuncExprArguments(functionBody: string) {
|
||||
const start = functionBody.indexOf('(');
|
||||
const end = functionBody.indexOf(')');
|
||||
|
||||
if (start < 0 || end < 0 || end < start) {
|
||||
throw new CodeGeneratorError('JSExpression has no valid arguments.');
|
||||
}
|
||||
|
||||
const args = functionBody.slice(start + 1, end);
|
||||
return args;
|
||||
}
|
||||
|
||||
export function getFuncExprBody(functionBody: string) {
|
||||
const start = functionBody.indexOf('{');
|
||||
const end = functionBody.lastIndexOf('}');
|
||||
|
||||
// test(functionBody);
|
||||
|
||||
if (start < 0 || end < 0 || end < start) {
|
||||
throw new CodeGeneratorError('JSExpression has no valid body.');
|
||||
}
|
||||
|
||||
const body = functionBody.slice(start + 1, end);
|
||||
return body;
|
||||
}
|
||||
|
||||
export function generateExpression(value: any): string {
|
||||
if (value && (value as IJSExpression).type === 'JSExpression') {
|
||||
// test((value as IJSExpression).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'
|
||||
);
|
||||
}
|
||||
191
packages/code-generator/src/utils/nodeToJSX.ts
Normal file
191
packages/code-generator/src/utils/nodeToJSX.ts
Normal file
@ -0,0 +1,191 @@
|
||||
import {
|
||||
ChildNodeType,
|
||||
IComponentNodeItem,
|
||||
IJSExpression,
|
||||
ChildNodeItem,
|
||||
CodeGeneratorError,
|
||||
PIECE_TYPE,
|
||||
CodePiece,
|
||||
HandlerSet,
|
||||
ExtGeneratorPlugin,
|
||||
} from '../types';
|
||||
import { generateCompositeType } from './compositeType';
|
||||
import { generateExpression } from './jsExpression';
|
||||
|
||||
// tslint:disable-next-line: no-empty
|
||||
const noop = () => [];
|
||||
|
||||
export function handleChildren<T>(
|
||||
children: ChildNodeType,
|
||||
handlers: HandlerSet<T>,
|
||||
): T[] {
|
||||
if (Array.isArray(children)) {
|
||||
const list: ChildNodeItem[] = children as ChildNodeItem[];
|
||||
return list
|
||||
.map(child => handleChildren(child, handlers))
|
||||
.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') {
|
||||
const handler = handlers.expression || handlers.common || noop;
|
||||
return handler(children as IJSExpression);
|
||||
} else {
|
||||
const handler = handlers.node || handlers.common || noop;
|
||||
return handler(children as IComponentNodeItem);
|
||||
}
|
||||
}
|
||||
|
||||
export function generateAttr(attrName: string, attrValue: any): CodePiece[] {
|
||||
if (attrName === 'initValue' || attrName === 'labelCol') {
|
||||
return [];
|
||||
}
|
||||
const [isString, valueStr] = generateCompositeType(attrValue);
|
||||
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])),
|
||||
);
|
||||
|
||||
return pieces;
|
||||
}
|
||||
|
||||
export function mapNodeName(src: string): string {
|
||||
if (src === 'Div') {
|
||||
return 'div';
|
||||
}
|
||||
return src;
|
||||
}
|
||||
|
||||
export function generateBasicNode(nodeItem: IComponentNodeItem): CodePiece[] {
|
||||
const pieces: CodePiece[] = [];
|
||||
pieces.push({
|
||||
value: mapNodeName(nodeItem.componentName),
|
||||
type: PIECE_TYPE.TAG,
|
||||
});
|
||||
|
||||
return pieces;
|
||||
}
|
||||
|
||||
export function generateReactCtrlLine(nodeItem: IComponentNodeItem): CodePiece[] {
|
||||
const pieces: CodePiece[] = [];
|
||||
|
||||
if (nodeItem.loop && nodeItem.loopArgs) {
|
||||
let loopDataExp;
|
||||
if ((nodeItem.loop as IJSExpression).type === 'JSExpression') {
|
||||
loopDataExp = `(${(nodeItem.loop as IJSExpression).value})`;
|
||||
} else {
|
||||
loopDataExp = JSON.stringify(nodeItem.loop);
|
||||
}
|
||||
pieces.unshift({
|
||||
value: `${loopDataExp}.map((${nodeItem.loopArgs[0]}, ${nodeItem.loopArgs[1]}) => (`,
|
||||
type: PIECE_TYPE.BEFORE,
|
||||
});
|
||||
pieces.push({
|
||||
value: '))',
|
||||
type: PIECE_TYPE.AFTER,
|
||||
});
|
||||
}
|
||||
|
||||
if (nodeItem.condition) {
|
||||
pieces.unshift({
|
||||
value: `(${generateCompositeType(nodeItem.condition)}) && (`,
|
||||
type: PIECE_TYPE.BEFORE,
|
||||
});
|
||||
pieces.push({
|
||||
value: ')',
|
||||
type: PIECE_TYPE.AFTER,
|
||||
});
|
||||
}
|
||||
|
||||
if (nodeItem.condition || (nodeItem.loop && nodeItem.loopArgs)) {
|
||||
pieces.unshift({
|
||||
value: '{',
|
||||
type: PIECE_TYPE.BEFORE,
|
||||
});
|
||||
pieces.push({
|
||||
value: '}',
|
||||
type: PIECE_TYPE.AFTER,
|
||||
});
|
||||
}
|
||||
|
||||
return pieces;
|
||||
}
|
||||
|
||||
export function linkPieces(pieces: CodePiece[]): string {
|
||||
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 beforeParts = pieces
|
||||
.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)
|
||||
.join('');
|
||||
|
||||
const childrenParts = pieces
|
||||
.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)
|
||||
.join(' ');
|
||||
|
||||
attrsParts = !!attrsParts ? ` ${attrsParts}` : '';
|
||||
|
||||
if (childrenParts) {
|
||||
return `${beforeParts}<${tagName}${attrsParts}>${childrenParts}</${tagName}>${afterParts}`;
|
||||
}
|
||||
|
||||
return `${beforeParts}<${tagName}${attrsParts} />${afterParts}`;
|
||||
}
|
||||
|
||||
export function createNodeGenerator(handlers: HandlerSet<string>, plugins: ExtGeneratorPlugin[]) {
|
||||
const generateNode = (nodeItem: IComponentNodeItem): string => {
|
||||
let pieces: CodePiece[] = [];
|
||||
|
||||
plugins.forEach(p => {
|
||||
pieces = pieces.concat(p(nodeItem));
|
||||
});
|
||||
pieces = pieces.concat(generateBasicNode(nodeItem));
|
||||
pieces = pieces.concat(generateAttrs(nodeItem));
|
||||
if (nodeItem.children && (nodeItem.children as unknown[]).length > 0) {
|
||||
pieces = pieces.concat(handleChildren<string>(nodeItem.children, handlers).map(l => ({
|
||||
type: PIECE_TYPE.CHILDREN,
|
||||
value: l,
|
||||
})));
|
||||
}
|
||||
|
||||
return linkPieces(pieces);
|
||||
};
|
||||
|
||||
handlers.node = (input: IComponentNodeItem) => [generateNode(input)];
|
||||
|
||||
return generateNode;
|
||||
}
|
||||
|
||||
export const generateString = (input: string) => [input];
|
||||
|
||||
export function createReactNodeGenerator() {
|
||||
return createNodeGenerator({
|
||||
string: generateString,
|
||||
expression: (input) => [generateExpression(input)],
|
||||
}, [
|
||||
generateReactCtrlLine,
|
||||
]);
|
||||
}
|
||||
25
packages/code-generator/src/utils/templateHelper.ts
Normal file
25
packages/code-generator/src/utils/templateHelper.ts
Normal file
@ -0,0 +1,25 @@
|
||||
import { IResultFile, IResultDir } from '../types';
|
||||
import ResultDir from '../model/ResultDir';
|
||||
|
||||
type FuncFileGenerator = () => [string[], IResultFile];
|
||||
|
||||
export function insertFile(root: IResultDir, path: string[], file: IResultFile) {
|
||||
let current: IResultDir = root;
|
||||
path.forEach(pathNode => {
|
||||
const dir = current.dirs.find(d => d.name === pathNode);
|
||||
if (dir) {
|
||||
current = dir;
|
||||
} else {
|
||||
const newDir = new ResultDir(pathNode);
|
||||
current.addDirectory(newDir);
|
||||
current = newDir;
|
||||
}
|
||||
});
|
||||
|
||||
current.addFile(file);
|
||||
}
|
||||
|
||||
export function runFileGenerator(root: IResultDir, fun: FuncFileGenerator) {
|
||||
const [path, file] = fun();
|
||||
insertFile(root, path, file);
|
||||
}
|
||||
85
packages/code-generator/tools/createTemplate.js
Normal file
85
packages/code-generator/tools/createTemplate.js
Normal file
@ -0,0 +1,85 @@
|
||||
const fs = require("fs");
|
||||
const path = require('path');
|
||||
|
||||
console.log(process.argv);
|
||||
let root = '';
|
||||
const pathArgIndex = process.argv.indexOf('--path');
|
||||
if (pathArgIndex >= 0) {
|
||||
root = process.argv[pathArgIndex + 1];
|
||||
}
|
||||
|
||||
if (!root) {
|
||||
throw new Error('Can\'t find path argument');
|
||||
}
|
||||
|
||||
function cloneStr(str, times) {
|
||||
let count = times;
|
||||
const arr = [];
|
||||
while(count > 0) {
|
||||
arr.push(str);
|
||||
count -= 1;
|
||||
}
|
||||
return arr.join('');
|
||||
}
|
||||
|
||||
function createTemplateFile(root, internalPath, fileName) {
|
||||
//不是文件夹,则添加type属性为文件后缀名
|
||||
const fileTypeSrc = path.extname(fileName);
|
||||
const fileType = fileTypeSrc.substring(1);
|
||||
const baseName = path.basename(fileName, fileTypeSrc);
|
||||
|
||||
const filePath = path.join(root, internalPath);
|
||||
const pieces = filePath.split(path.sep);
|
||||
const depPrefix = cloneStr('../', pieces.length - 1);
|
||||
const content = fs.readFileSync(path.join(filePath, fileName), {
|
||||
encoding: 'utf8',
|
||||
});
|
||||
const pathList = (internalPath.split(path.sep) || []).filter(p => !!p);
|
||||
const modulePathStr = JSON.stringify(pathList).replace(/\"/g, '\'');
|
||||
|
||||
const templateContent = `
|
||||
import ResultFile from '${depPrefix}model/ResultFile';
|
||||
import { IResultFile } from '${depPrefix}types';
|
||||
|
||||
export default function getFile(): [string[], IResultFile] {
|
||||
const file = new ResultFile(
|
||||
'${baseName}',
|
||||
'${fileType || ''}',
|
||||
\`
|
||||
${content}
|
||||
\`,
|
||||
);
|
||||
|
||||
return [${modulePathStr}, file];
|
||||
}
|
||||
`;
|
||||
|
||||
const targetFile = path.join(filePath, `${fileName}.ts`);
|
||||
console.log(`=== Create File: ${targetFile}`);
|
||||
fs.writeFileSync(targetFile, templateContent);
|
||||
}
|
||||
|
||||
function fileDisplay(root, internalPath) {
|
||||
const dirPath = path.join(root, internalPath);
|
||||
const filesList = fs.readdirSync(dirPath);
|
||||
for(let i = 0; i < filesList.length; i++){
|
||||
//描述此文件/文件夹的对象
|
||||
const fileName = filesList[i];
|
||||
//拼接当前文件的路径(上一层路径+当前file的名字)
|
||||
const filePath = path.join(dirPath, fileName);
|
||||
//根据文件路径获取文件信息,返回一个fs.Stats对象
|
||||
const stats = fs.statSync(filePath);
|
||||
if(stats.isDirectory()){
|
||||
//递归调用
|
||||
fileDisplay(root, path.join(internalPath, fileName));
|
||||
}else{
|
||||
createTemplateFile(root, internalPath, fileName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//调用函数遍历根目录,同时传递 文件夹路径和对应的数组
|
||||
//请使用同步读取
|
||||
fileDisplay(root, '');
|
||||
//读取完毕则写入到txt文件中
|
||||
// fs.writeFileSync('./data.txt', JSON.stringify(arr));
|
||||
@ -5,6 +5,7 @@
|
||||
"lib": [
|
||||
"es6"
|
||||
],
|
||||
"module": "commonjs",
|
||||
"types": ["node"],
|
||||
"baseUrl": ".", /* Base directory to resolve non-absolute module names. */
|
||||
},
|
||||
|
||||
@ -154,6 +154,9 @@ export default class Panel implements IWidget {
|
||||
}
|
||||
this.emitter.emit('activechange', true);
|
||||
} else if (this.inited) {
|
||||
if (this.parent?.name && this.name.startsWith(this.parent.name)) {
|
||||
this.inited = false;
|
||||
}
|
||||
this._actived = false;
|
||||
this.parent?.unactive(this);
|
||||
this.emitter.emit('activechange', false);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user