mirror of
https://github.com/alibaba/lowcode-engine.git
synced 2026-03-10 01:48:18 +00:00
Merge branch refactor/merge-rax-generator into release/1.0.0
Title: refactor: merge rax code generator & refactor Link: https://code.aone.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/codereview/3770366
This commit is contained in:
commit
ac72d71339
13
.vscode/launch.json
vendored
13
.vscode/launch.json
vendored
@ -9,7 +9,16 @@
|
|||||||
"type": "node",
|
"type": "node",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"runtimeExecutable": "${workspaceFolder}/packages/material-parser/node_modules/.bin/ava",
|
"runtimeExecutable": "${workspaceFolder}/packages/material-parser/node_modules/.bin/ava",
|
||||||
"runtimeArgs": ["debug", "--break", "${workspaceFolder}/packages/material-parser/test/antd.ts"]
|
"runtimeArgs": ["debug", "--break", "${file}"]
|
||||||
}
|
},
|
||||||
|
{
|
||||||
|
"name": "ava code-gen",
|
||||||
|
"type": "node",
|
||||||
|
"request": "launch",
|
||||||
|
"runtimeExecutable": "node",
|
||||||
|
"runtimeArgs": ["${workspaceFolder}/node_modules/.bin/ava", "--serial", "${file}"],
|
||||||
|
"cwd": "${workspaceFolder}/packages/code-generator",
|
||||||
|
"outputCapture": "std"
|
||||||
|
},
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@ -25,13 +25,13 @@
|
|||||||
},
|
},
|
||||||
"husky": {
|
"husky": {
|
||||||
"hooks": {
|
"hooks": {
|
||||||
"commit-msg": "xima exec commitlint -E HUSKY_GIT_PARAMS",
|
"pre-commit": "xima exec lint-staged",
|
||||||
"pre-commit": "xima exec lint-staged"
|
"commit-msg": "xima exec commitlint -E HUSKY_GIT_PARAMS"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"lint-staged": {
|
"lint-staged": {
|
||||||
"**/*.{js,jsx,ts,tsx}": "xima exec eslint",
|
"**/*.{css,scss,less}": "xima exec stylelint",
|
||||||
"**/*.{css,scss,less}": "xima exec stylelint"
|
"**/*.{js,jsx,ts,tsx}": "xima exec eslint"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"ava": "^1.0.1",
|
"ava": "^1.0.1",
|
||||||
|
|||||||
1
packages/code-generator/.eslintignore
Normal file
1
packages/code-generator/.eslintignore
Normal file
@ -0,0 +1 @@
|
|||||||
|
test-cases/
|
||||||
@ -1,9 +1,31 @@
|
|||||||
# 出码模块
|
# 出码模块
|
||||||
|
|
||||||
|
详细介绍看这里:<https://yuque.antfin-inc.com/docs/share/2b342641-6e01-4c77-b8e0-30421f55f69b>
|
||||||
|
|
||||||
## 安装接入
|
## 安装接入
|
||||||
|
|
||||||
|
|
||||||
## 自定义导出
|
## 自定义导出
|
||||||
|
|
||||||
|
|
||||||
## 开始开发
|
## 开始开发
|
||||||
|
|
||||||
|
本项目隶属于 [ali-lowcode-engine](http://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine), 需要和整个 [ali-lowcode-engine](http://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine) 一起开发。
|
||||||
|
|
||||||
|
所以先要初始化整个 [ali-lowcode-engine](http://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine) 的环境:
|
||||||
|
|
||||||
|
1. 克隆 [ali-lowcode-engine](http://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine): `git clone git@gitlab.alibaba-inc.com:ali-lowcode/ali-lowcode-engine.git`
|
||||||
|
2. 运行 `setup` 脚本,初始化环境: `npm run setup`
|
||||||
|
|
||||||
|
然后,因为本项目依赖 `@ali/lowcode-types` 所以需要先构建下 `type`,即执行: `lerna run build --scope @ali/lowcode-types`
|
||||||
|
|
||||||
|
最后,可以运行 `npm start` 命令启动本地调试(本项目通过 `ava` 进行单元测试,故 `start` 脚本其实就是 `watch` 模式的 `ava`):
|
||||||
|
|
||||||
|
```sh
|
||||||
|
# 到本项目目录下执行:(推荐)
|
||||||
|
npm start
|
||||||
|
|
||||||
|
# 或直接执行 ava:
|
||||||
|
npx ava --watch
|
||||||
|
|
||||||
|
# 或在 ali-lowcode-engine 工程根目录下执行: (不推荐,因为命令太长而且没法响应输入)
|
||||||
|
lerna run start --stream --scope @ali/lowcode-code-generator
|
||||||
|
```
|
||||||
|
|||||||
5
packages/code-generator/build.json
Normal file
5
packages/code-generator/build.json
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"plugins": [
|
||||||
|
"build-plugin-component"
|
||||||
|
]
|
||||||
|
}
|
||||||
@ -91,6 +91,33 @@ function demo() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function demo() {
|
||||||
|
const schemaJson = fs.readFileSync('./demo/schema.json', { encoding: 'utf8' });
|
||||||
|
const createIceJsProjectBuilder = CodeGenerator.solutions.icejs;
|
||||||
|
const builder = createIceJsProjectBuilder();
|
||||||
|
|
||||||
|
const componentsMap = getComponentsMap();
|
||||||
|
const root = JSON.parse(schemaJson);
|
||||||
|
|
||||||
|
const fullSchema = {
|
||||||
|
version: '1.0.0',
|
||||||
|
config: {
|
||||||
|
historyMode: 'hash',
|
||||||
|
targetRootID: 'J_Container',
|
||||||
|
},
|
||||||
|
meta: {
|
||||||
|
name: 'demoproject',
|
||||||
|
},
|
||||||
|
componentsTree: [root],
|
||||||
|
componentsMap,
|
||||||
|
};
|
||||||
|
|
||||||
|
builder.generateProject(fullSchema).then((result) => {
|
||||||
|
displayResultInConsole(result);
|
||||||
|
return result;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function exportModule() {
|
function exportModule() {
|
||||||
const schemaJson = fs.readFileSync('./demo/shenmaSample.json', { encoding: 'utf8' });
|
const schemaJson = fs.readFileSync('./demo/shenmaSample.json', { encoding: 'utf8' });
|
||||||
const moduleBuilder = CodeGenerator.createModuleBuilder({
|
const moduleBuilder = CodeGenerator.createModuleBuilder({
|
||||||
|
|||||||
@ -3,18 +3,25 @@
|
|||||||
"version": "1.0.8-0",
|
"version": "1.0.8-0",
|
||||||
"description": "出码引擎 for LowCode Engine",
|
"description": "出码引擎 for LowCode Engine",
|
||||||
"main": "lib/index.js",
|
"main": "lib/index.js",
|
||||||
|
"module": "es/index.js",
|
||||||
|
"typings": "es/index.d.ts",
|
||||||
"files": [
|
"files": [
|
||||||
"lib",
|
"lib",
|
||||||
|
"es",
|
||||||
"demo"
|
"demo"
|
||||||
],
|
],
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "rimraf lib && tsc",
|
"start": "ava --watch",
|
||||||
|
"build": "npm run build:bs",
|
||||||
|
"build:bs": "rimraf lib && rimraf es && build-scripts build --skip-demo",
|
||||||
|
"build:tsc": "rimraf lib && tsc",
|
||||||
"demo": "node ./demo/demo.js",
|
"demo": "node ./demo/demo.js",
|
||||||
"test": "ava",
|
"test": "ava",
|
||||||
"template": "node ./tools/createTemplate.js"
|
"template": "node ./tools/createTemplate.js"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ali/am-eslint-config": "*",
|
"@ali/am-eslint-config": "*",
|
||||||
|
"@ali/lowcode-types": "^1.0.0",
|
||||||
"@ali/my-prettier": "^1.0.0",
|
"@ali/my-prettier": "^1.0.0",
|
||||||
"@babel/generator": "^7.9.5",
|
"@babel/generator": "^7.9.5",
|
||||||
"@babel/parser": "^7.9.4",
|
"@babel/parser": "^7.9.4",
|
||||||
@ -24,24 +31,34 @@
|
|||||||
"change-case": "^3.1.0",
|
"change-case": "^3.1.0",
|
||||||
"jszip": "^3.5.0",
|
"jszip": "^3.5.0",
|
||||||
"prettier": "^2.0.2",
|
"prettier": "^2.0.2",
|
||||||
|
"semver": "^7.3.2",
|
||||||
"short-uuid": "^3.1.1"
|
"short-uuid": "^3.1.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@alib/build-scripts": "^0.1.18",
|
||||||
"@types/babel__traverse": "^7.0.10",
|
"@types/babel__traverse": "^7.0.10",
|
||||||
"ava": "^1.0.1",
|
"ava": "^1.0.1",
|
||||||
"rimraf": "^3.0.2",
|
"rimraf": "^3.0.2",
|
||||||
"ts-loader": "^6.2.2",
|
"ts-loader": "^6.2.2",
|
||||||
"ts-node": "^7.0.1",
|
"ts-node": "^8.10.2",
|
||||||
"tsconfig-paths": "^3.9.0"
|
"tsconfig-paths": "^3.9.0"
|
||||||
},
|
},
|
||||||
"ava": {
|
"ava": {
|
||||||
"compileEnhancements": false,
|
"compileEnhancements": false,
|
||||||
"snapshotDir": "test/fixtures/__snapshots__",
|
"snapshotDir": "test/fixtures/__snapshots__",
|
||||||
|
"files": [
|
||||||
|
"test/**/*.test.ts"
|
||||||
|
],
|
||||||
"extensions": [
|
"extensions": [
|
||||||
"ts"
|
"ts"
|
||||||
],
|
],
|
||||||
"require": [
|
"require": [
|
||||||
"ts-node/register"
|
"ts-node/register/transpile-only"
|
||||||
|
],
|
||||||
|
"sources": [
|
||||||
|
"src/**/*",
|
||||||
|
"test/**/*",
|
||||||
|
"test-cases/**/expected/**/*"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"publishConfig": {
|
"publishConfig": {
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
export const COMMON_CHUNK_NAME = {
|
export const COMMON_CHUNK_NAME = {
|
||||||
ExternalDepsImport: 'CommonExternalDependencyImport',
|
ExternalDepsImport: 'CommonExternalDependencyImport',
|
||||||
InternalDepsImport: 'CommonInternalDependencyImport',
|
InternalDepsImport: 'CommonInternalDependencyImport',
|
||||||
|
ImportAliasDefine: 'CommonImportAliasDefine',
|
||||||
FileVarDefine: 'CommonFileScopeVarDefine',
|
FileVarDefine: 'CommonFileScopeVarDefine',
|
||||||
FileUtilDefine: 'CommonFileScopeMethodDefine',
|
FileUtilDefine: 'CommonFileScopeMethodDefine',
|
||||||
FileMainContent: 'CommonFileMainContent',
|
FileMainContent: 'CommonFileMainContent',
|
||||||
@ -21,24 +22,29 @@ export const CLASS_DEFINE_CHUNK_NAME = {
|
|||||||
InsVar: 'CommonClassDefineInsVar',
|
InsVar: 'CommonClassDefineInsVar',
|
||||||
InsVarMethod: 'CommonClassDefineInsVarMethod',
|
InsVarMethod: 'CommonClassDefineInsVarMethod',
|
||||||
InsMethod: 'CommonClassDefineInsMethod',
|
InsMethod: 'CommonClassDefineInsMethod',
|
||||||
|
InsPrivateMethod: 'CommonClassDefineInsPrivateMethod',
|
||||||
End: 'CommonClassDefineEnd',
|
End: 'CommonClassDefineEnd',
|
||||||
};
|
};
|
||||||
|
|
||||||
export const DEFAULT_LINK_AFTER = {
|
export const DEFAULT_LINK_AFTER = {
|
||||||
[COMMON_CHUNK_NAME.ExternalDepsImport]: [],
|
[COMMON_CHUNK_NAME.ExternalDepsImport]: [],
|
||||||
[COMMON_CHUNK_NAME.InternalDepsImport]: [COMMON_CHUNK_NAME.ExternalDepsImport],
|
[COMMON_CHUNK_NAME.InternalDepsImport]: [COMMON_CHUNK_NAME.ExternalDepsImport],
|
||||||
|
[COMMON_CHUNK_NAME.ImportAliasDefine]: [COMMON_CHUNK_NAME.ExternalDepsImport, COMMON_CHUNK_NAME.InternalDepsImport],
|
||||||
[COMMON_CHUNK_NAME.FileVarDefine]: [
|
[COMMON_CHUNK_NAME.FileVarDefine]: [
|
||||||
COMMON_CHUNK_NAME.ExternalDepsImport,
|
COMMON_CHUNK_NAME.ExternalDepsImport,
|
||||||
COMMON_CHUNK_NAME.InternalDepsImport,
|
COMMON_CHUNK_NAME.InternalDepsImport,
|
||||||
|
COMMON_CHUNK_NAME.ImportAliasDefine,
|
||||||
],
|
],
|
||||||
[COMMON_CHUNK_NAME.FileUtilDefine]: [
|
[COMMON_CHUNK_NAME.FileUtilDefine]: [
|
||||||
COMMON_CHUNK_NAME.ExternalDepsImport,
|
COMMON_CHUNK_NAME.ExternalDepsImport,
|
||||||
COMMON_CHUNK_NAME.InternalDepsImport,
|
COMMON_CHUNK_NAME.InternalDepsImport,
|
||||||
|
COMMON_CHUNK_NAME.ImportAliasDefine,
|
||||||
COMMON_CHUNK_NAME.FileVarDefine,
|
COMMON_CHUNK_NAME.FileVarDefine,
|
||||||
],
|
],
|
||||||
[CLASS_DEFINE_CHUNK_NAME.Start]: [
|
[CLASS_DEFINE_CHUNK_NAME.Start]: [
|
||||||
COMMON_CHUNK_NAME.ExternalDepsImport,
|
COMMON_CHUNK_NAME.ExternalDepsImport,
|
||||||
COMMON_CHUNK_NAME.InternalDepsImport,
|
COMMON_CHUNK_NAME.InternalDepsImport,
|
||||||
|
COMMON_CHUNK_NAME.ImportAliasDefine,
|
||||||
COMMON_CHUNK_NAME.FileVarDefine,
|
COMMON_CHUNK_NAME.FileVarDefine,
|
||||||
COMMON_CHUNK_NAME.FileUtilDefine,
|
COMMON_CHUNK_NAME.FileUtilDefine,
|
||||||
],
|
],
|
||||||
@ -49,20 +55,13 @@ export const DEFAULT_LINK_AFTER = {
|
|||||||
CLASS_DEFINE_CHUNK_NAME.InsVar,
|
CLASS_DEFINE_CHUNK_NAME.InsVar,
|
||||||
CLASS_DEFINE_CHUNK_NAME.InsVarMethod,
|
CLASS_DEFINE_CHUNK_NAME.InsVarMethod,
|
||||||
],
|
],
|
||||||
[CLASS_DEFINE_CHUNK_NAME.ConstructorContent]: [
|
[CLASS_DEFINE_CHUNK_NAME.ConstructorContent]: [CLASS_DEFINE_CHUNK_NAME.ConstructorStart],
|
||||||
CLASS_DEFINE_CHUNK_NAME.ConstructorStart,
|
|
||||||
],
|
|
||||||
[CLASS_DEFINE_CHUNK_NAME.ConstructorEnd]: [
|
[CLASS_DEFINE_CHUNK_NAME.ConstructorEnd]: [
|
||||||
CLASS_DEFINE_CHUNK_NAME.ConstructorStart,
|
CLASS_DEFINE_CHUNK_NAME.ConstructorStart,
|
||||||
CLASS_DEFINE_CHUNK_NAME.ConstructorContent,
|
CLASS_DEFINE_CHUNK_NAME.ConstructorContent,
|
||||||
],
|
],
|
||||||
[CLASS_DEFINE_CHUNK_NAME.StaticVar]: [
|
[CLASS_DEFINE_CHUNK_NAME.StaticVar]: [CLASS_DEFINE_CHUNK_NAME.Start],
|
||||||
CLASS_DEFINE_CHUNK_NAME.Start,
|
[CLASS_DEFINE_CHUNK_NAME.StaticMethod]: [CLASS_DEFINE_CHUNK_NAME.Start, CLASS_DEFINE_CHUNK_NAME.StaticVar],
|
||||||
],
|
|
||||||
[CLASS_DEFINE_CHUNK_NAME.StaticMethod]: [
|
|
||||||
CLASS_DEFINE_CHUNK_NAME.Start,
|
|
||||||
CLASS_DEFINE_CHUNK_NAME.StaticVar,
|
|
||||||
],
|
|
||||||
[CLASS_DEFINE_CHUNK_NAME.InsVar]: [
|
[CLASS_DEFINE_CHUNK_NAME.InsVar]: [
|
||||||
CLASS_DEFINE_CHUNK_NAME.Start,
|
CLASS_DEFINE_CHUNK_NAME.Start,
|
||||||
CLASS_DEFINE_CHUNK_NAME.StaticVar,
|
CLASS_DEFINE_CHUNK_NAME.StaticVar,
|
||||||
@ -82,7 +81,7 @@ export const DEFAULT_LINK_AFTER = {
|
|||||||
CLASS_DEFINE_CHUNK_NAME.InsVarMethod,
|
CLASS_DEFINE_CHUNK_NAME.InsVarMethod,
|
||||||
CLASS_DEFINE_CHUNK_NAME.ConstructorEnd,
|
CLASS_DEFINE_CHUNK_NAME.ConstructorEnd,
|
||||||
],
|
],
|
||||||
[CLASS_DEFINE_CHUNK_NAME.End]: [
|
[CLASS_DEFINE_CHUNK_NAME.InsPrivateMethod]: [
|
||||||
CLASS_DEFINE_CHUNK_NAME.Start,
|
CLASS_DEFINE_CHUNK_NAME.Start,
|
||||||
CLASS_DEFINE_CHUNK_NAME.StaticVar,
|
CLASS_DEFINE_CHUNK_NAME.StaticVar,
|
||||||
CLASS_DEFINE_CHUNK_NAME.StaticMethod,
|
CLASS_DEFINE_CHUNK_NAME.StaticMethod,
|
||||||
@ -91,9 +90,20 @@ export const DEFAULT_LINK_AFTER = {
|
|||||||
CLASS_DEFINE_CHUNK_NAME.InsMethod,
|
CLASS_DEFINE_CHUNK_NAME.InsMethod,
|
||||||
CLASS_DEFINE_CHUNK_NAME.ConstructorEnd,
|
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.InsPrivateMethod,
|
||||||
|
CLASS_DEFINE_CHUNK_NAME.ConstructorEnd,
|
||||||
|
],
|
||||||
[COMMON_CHUNK_NAME.FileMainContent]: [
|
[COMMON_CHUNK_NAME.FileMainContent]: [
|
||||||
COMMON_CHUNK_NAME.ExternalDepsImport,
|
COMMON_CHUNK_NAME.ExternalDepsImport,
|
||||||
COMMON_CHUNK_NAME.InternalDepsImport,
|
COMMON_CHUNK_NAME.InternalDepsImport,
|
||||||
|
COMMON_CHUNK_NAME.ImportAliasDefine,
|
||||||
COMMON_CHUNK_NAME.FileVarDefine,
|
COMMON_CHUNK_NAME.FileVarDefine,
|
||||||
COMMON_CHUNK_NAME.FileUtilDefine,
|
COMMON_CHUNK_NAME.FileUtilDefine,
|
||||||
CLASS_DEFINE_CHUNK_NAME.End,
|
CLASS_DEFINE_CHUNK_NAME.End,
|
||||||
@ -101,6 +111,7 @@ export const DEFAULT_LINK_AFTER = {
|
|||||||
[COMMON_CHUNK_NAME.FileExport]: [
|
[COMMON_CHUNK_NAME.FileExport]: [
|
||||||
COMMON_CHUNK_NAME.ExternalDepsImport,
|
COMMON_CHUNK_NAME.ExternalDepsImport,
|
||||||
COMMON_CHUNK_NAME.InternalDepsImport,
|
COMMON_CHUNK_NAME.InternalDepsImport,
|
||||||
|
COMMON_CHUNK_NAME.ImportAliasDefine,
|
||||||
COMMON_CHUNK_NAME.FileVarDefine,
|
COMMON_CHUNK_NAME.FileVarDefine,
|
||||||
COMMON_CHUNK_NAME.FileUtilDefine,
|
COMMON_CHUNK_NAME.FileUtilDefine,
|
||||||
CLASS_DEFINE_CHUNK_NAME.End,
|
CLASS_DEFINE_CHUNK_NAME.End,
|
||||||
|
|||||||
@ -1,11 +1,4 @@
|
|||||||
import {
|
import { ChunkContent, ChunkType, CodeGeneratorError, CodeGeneratorFunction, ICodeBuilder, ICodeChunk } from '../types';
|
||||||
ChunkContent,
|
|
||||||
ChunkType,
|
|
||||||
CodeGeneratorError,
|
|
||||||
CodeGeneratorFunction,
|
|
||||||
ICodeBuilder,
|
|
||||||
ICodeChunk,
|
|
||||||
} from '../types';
|
|
||||||
|
|
||||||
export default class Builder implements ICodeBuilder {
|
export default class Builder implements ICodeBuilder {
|
||||||
private chunkDefinitions: ICodeChunk[] = [];
|
private chunkDefinitions: ICodeChunk[] = [];
|
||||||
@ -23,13 +16,13 @@ export default class Builder implements ICodeBuilder {
|
|||||||
* Links all chunks together based on their requirements. Returns an array
|
* Links all chunks together based on their requirements. Returns an array
|
||||||
* of ordered chunk names which need to be compiled and glued together.
|
* of ordered chunk names which need to be compiled and glued together.
|
||||||
*/
|
*/
|
||||||
public link(chunkDefinitions: ICodeChunk[] = []): string {
|
link(chunkDefinitions: ICodeChunk[] = []): string {
|
||||||
const chunks = chunkDefinitions || this.chunkDefinitions;
|
const chunks = chunkDefinitions || this.chunkDefinitions;
|
||||||
if (chunks.length <= 0) {
|
if (chunks.length <= 0) {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
const unprocessedChunks = chunks.map(chunk => {
|
const unprocessedChunks = chunks.map((chunk) => {
|
||||||
return {
|
return {
|
||||||
name: chunk.name,
|
name: chunk.name,
|
||||||
type: chunk.type,
|
type: chunk.type,
|
||||||
@ -50,9 +43,7 @@ export default class Builder implements ICodeBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (unprocessedChunks[indexToRemove].linkAfter.length > 0) {
|
if (unprocessedChunks[indexToRemove].linkAfter.length > 0) {
|
||||||
throw new CodeGeneratorError(
|
throw new CodeGeneratorError('Operation aborted. Reason: cyclic dependency between chunks.');
|
||||||
'Operation aborted. Reason: cyclic dependency between chunks.',
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const { type, content, name } = unprocessedChunks[indexToRemove];
|
const { type, content, name } = unprocessedChunks[indexToRemove];
|
||||||
@ -62,11 +53,13 @@ export default class Builder implements ICodeBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
unprocessedChunks.splice(indexToRemove, 1);
|
unprocessedChunks.splice(indexToRemove, 1);
|
||||||
if (!unprocessedChunks.some(ch => ch.name === name)) {
|
if (!unprocessedChunks.some((ch) => ch.name === name)) {
|
||||||
unprocessedChunks.forEach(
|
unprocessedChunks.forEach(
|
||||||
// remove the processed chunk from all the linkAfter arrays from the remaining chunks
|
// remove the processed chunk from all the linkAfter arrays from the remaining chunks
|
||||||
// eslint-disable-next-line no-param-reassign
|
(ch) => {
|
||||||
ch => { ch.linkAfter = ch.linkAfter.filter(after => after !== name); },
|
// eslint-disable-next-line no-param-reassign
|
||||||
|
ch.linkAfter = ch.linkAfter.filter((after) => after !== name);
|
||||||
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -74,14 +67,12 @@ export default class Builder implements ICodeBuilder {
|
|||||||
return resultingString.join('\n');
|
return resultingString.join('\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
public generateByType(type: string, content: unknown): string {
|
generateByType(type: string, content: unknown): string {
|
||||||
if (!content) {
|
if (!content) {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
if (Array.isArray(content)) {
|
if (Array.isArray(content)) {
|
||||||
return content
|
return content.map((contentItem) => this.generateByType(type, contentItem)).join('\n');
|
||||||
.map(contentItem => this.generateByType(type, contentItem))
|
|
||||||
.join('\n');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this.generators[type]) {
|
if (!this.generators[type]) {
|
||||||
@ -96,6 +87,6 @@ export default class Builder implements ICodeBuilder {
|
|||||||
// remove invalid chunks (which did not end up being created) from the linkAfter fields
|
// remove invalid chunks (which did not end up being created) from the linkAfter fields
|
||||||
// one use-case is when you want to remove the import plugin
|
// one use-case is when you want to remove the import plugin
|
||||||
private cleanupInvalidChunks(linkAfter: string[], chunks: ICodeChunk[]) {
|
private cleanupInvalidChunks(linkAfter: string[], chunks: ICodeChunk[]) {
|
||||||
return linkAfter.filter(chunkName => chunks.some(chunk => chunk.name === chunkName));
|
return linkAfter.filter((chunkName) => chunks.some((chunk) => chunk.name === chunkName));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,13 +1,12 @@
|
|||||||
|
import { ProjectSchema, ResultFile, ResultDir } from '@ali/lowcode-types';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
BuilderComponentPlugin,
|
BuilderComponentPlugin,
|
||||||
CodeGeneratorError,
|
CodeGeneratorError,
|
||||||
IBasicSchema,
|
|
||||||
ICodeChunk,
|
ICodeChunk,
|
||||||
ICompiledModule,
|
ICompiledModule,
|
||||||
IModuleBuilder,
|
IModuleBuilder,
|
||||||
IParseResult,
|
IParseResult,
|
||||||
IResultDir,
|
|
||||||
IResultFile,
|
|
||||||
ISchemaParser,
|
ISchemaParser,
|
||||||
PostProcessor,
|
PostProcessor,
|
||||||
} from '../types';
|
} from '../types';
|
||||||
@ -17,9 +16,7 @@ import { COMMON_SUB_MODULE_NAME } from '../const/generator';
|
|||||||
import SchemaParser from '../parser/SchemaParser';
|
import SchemaParser from '../parser/SchemaParser';
|
||||||
import ChunkBuilder from './ChunkBuilder';
|
import ChunkBuilder from './ChunkBuilder';
|
||||||
import CodeBuilder from './CodeBuilder';
|
import CodeBuilder from './CodeBuilder';
|
||||||
|
import { createResultFile, createResultDir, addFile } from '../utils/resultHelper';
|
||||||
import ResultDir from '../model/ResultDir';
|
|
||||||
import ResultFile from '../model/ResultFile';
|
|
||||||
|
|
||||||
export function createModuleBuilder(
|
export function createModuleBuilder(
|
||||||
options: {
|
options: {
|
||||||
@ -40,12 +37,12 @@ export function createModuleBuilder(
|
|||||||
throw new CodeGeneratorError('No plugins found. Component generation cannot work without any plugins!');
|
throw new CodeGeneratorError('No plugins found. Component generation cannot work without any plugins!');
|
||||||
}
|
}
|
||||||
|
|
||||||
let files: IResultFile[] = [];
|
let files: ResultFile[] = [];
|
||||||
|
|
||||||
const { chunks } = await chunkGenerator.run(input);
|
const { chunks } = await chunkGenerator.run(input);
|
||||||
chunks.forEach((fileChunkList) => {
|
chunks.forEach((fileChunkList) => {
|
||||||
const content = linker.link(fileChunkList);
|
const content = linker.link(fileChunkList);
|
||||||
const file = new ResultFile(fileChunkList[0].subModule || moduleMainName, fileChunkList[0].fileType, content);
|
const file = createResultFile(fileChunkList[0].subModule || moduleMainName, fileChunkList[0].fileType, content);
|
||||||
files.push(file);
|
files.push(file);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -57,7 +54,7 @@ export function createModuleBuilder(
|
|||||||
content = processer(content, type);
|
content = processer(content, type);
|
||||||
});
|
});
|
||||||
|
|
||||||
return new ResultFile(file.name, type, content);
|
return createResultFile(file.name, type, content);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -66,7 +63,7 @@ export function createModuleBuilder(
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
const generateModuleCode = async (schema: IBasicSchema | string): Promise<IResultDir> => {
|
const generateModuleCode = async (schema: ProjectSchema | string): Promise<ResultDir> => {
|
||||||
// Init
|
// Init
|
||||||
const schemaParser: ISchemaParser = new SchemaParser();
|
const schemaParser: ISchemaParser = new SchemaParser();
|
||||||
const parseResult: IParseResult = schemaParser.parse(schema);
|
const parseResult: IParseResult = schemaParser.parse(schema);
|
||||||
@ -74,19 +71,19 @@ export function createModuleBuilder(
|
|||||||
const containerInfo = parseResult.containers[0];
|
const containerInfo = parseResult.containers[0];
|
||||||
const { files } = await generateModule(containerInfo);
|
const { files } = await generateModule(containerInfo);
|
||||||
|
|
||||||
const dir = new ResultDir(containerInfo.moduleName);
|
const dir = createResultDir(containerInfo.moduleName);
|
||||||
files.forEach((file) => dir.addFile(file));
|
files.forEach((file) => addFile(dir, file));
|
||||||
|
|
||||||
return dir;
|
return dir;
|
||||||
};
|
};
|
||||||
|
|
||||||
const linkCodeChunks = (chunks: Record<string, ICodeChunk[]>, fileName: string) => {
|
const linkCodeChunks = (chunks: Record<string, ICodeChunk[]>, fileName: string) => {
|
||||||
const files: IResultFile[] = [];
|
const files: ResultFile[] = [];
|
||||||
|
|
||||||
Object.keys(chunks).forEach((fileKey) => {
|
Object.keys(chunks).forEach((fileKey) => {
|
||||||
const fileChunkList = chunks[fileKey];
|
const fileChunkList = chunks[fileKey];
|
||||||
const content = linker.link(fileChunkList);
|
const content = linker.link(fileChunkList);
|
||||||
const file = new ResultFile(fileChunkList[0].subModule || fileName, fileChunkList[0].fileType, content);
|
const file = createResultFile(fileChunkList[0].subModule || fileName, fileChunkList[0].fileType, content);
|
||||||
files.push(file);
|
files.push(file);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -1,36 +1,35 @@
|
|||||||
|
import { ResultDir, ResultFile, ProjectSchema } from '@ali/lowcode-types';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
IModuleBuilder,
|
IModuleBuilder,
|
||||||
IParseResult,
|
IParseResult,
|
||||||
IProjectBuilder,
|
IProjectBuilder,
|
||||||
IProjectPlugins,
|
IProjectPlugins,
|
||||||
IProjectSchema,
|
|
||||||
IProjectTemplate,
|
IProjectTemplate,
|
||||||
IResultDir,
|
|
||||||
IResultFile,
|
|
||||||
ISchemaParser,
|
ISchemaParser,
|
||||||
PostProcessor,
|
PostProcessor,
|
||||||
} from '../types';
|
} from '../types';
|
||||||
|
|
||||||
import ResultDir from '../model/ResultDir';
|
|
||||||
import SchemaParser from '../parser/SchemaParser';
|
import SchemaParser from '../parser/SchemaParser';
|
||||||
|
import { createResultDir, addDirectory, addFile } from '../utils/resultHelper';
|
||||||
|
|
||||||
import { createModuleBuilder } from '../generator/ModuleBuilder';
|
import { createModuleBuilder } from '../generator/ModuleBuilder';
|
||||||
|
|
||||||
interface IModuleInfo {
|
interface IModuleInfo {
|
||||||
moduleName?: string;
|
moduleName?: string;
|
||||||
path: string[];
|
path: string[];
|
||||||
files: IResultFile[];
|
files: ResultFile[];
|
||||||
}
|
}
|
||||||
|
|
||||||
function getDirFromRoot(root: IResultDir, path: string[]): IResultDir {
|
function getDirFromRoot(root: ResultDir, path: string[]): ResultDir {
|
||||||
let current: IResultDir = root;
|
let current: ResultDir = root;
|
||||||
path.forEach((p) => {
|
path.forEach((p) => {
|
||||||
const exist = current.dirs.find((d) => d.name === p);
|
const exist = current.dirs.find((d) => d.name === p);
|
||||||
if (exist) {
|
if (exist) {
|
||||||
current = exist;
|
current = exist;
|
||||||
} else {
|
} else {
|
||||||
const newDir = new ResultDir(p);
|
const newDir = createResultDir(p);
|
||||||
current.addDirectory(newDir);
|
addDirectory(current, newDir);
|
||||||
current = newDir;
|
current = newDir;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -59,7 +58,7 @@ export class ProjectBuilder implements IProjectBuilder {
|
|||||||
this.postProcessors = postProcessors;
|
this.postProcessors = postProcessors;
|
||||||
}
|
}
|
||||||
|
|
||||||
async generateProject(schema: IProjectSchema | string): Promise<IResultDir> {
|
async generateProject(schema: ProjectSchema | string): Promise<ResultDir> {
|
||||||
// Init
|
// Init
|
||||||
const schemaParser: ISchemaParser = new SchemaParser();
|
const schemaParser: ISchemaParser = new SchemaParser();
|
||||||
const builders = this.createModuleBuilders();
|
const builders = this.createModuleBuilders();
|
||||||
@ -119,6 +118,27 @@ export class ProjectBuilder implements IProjectBuilder {
|
|||||||
files,
|
files,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// appConfig
|
||||||
|
if (builders.appConfig) {
|
||||||
|
const { files } = await builders.appConfig.generateModule(parseResult);
|
||||||
|
|
||||||
|
buildResult.push({
|
||||||
|
path: this.template.slots.appConfig.path,
|
||||||
|
files,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// buildConfig
|
||||||
|
if (builders.buildConfig) {
|
||||||
|
const { files } = await builders.buildConfig.generateModule(parseResult);
|
||||||
|
|
||||||
|
buildResult.push({
|
||||||
|
path: this.template.slots.buildConfig.path,
|
||||||
|
files,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// constants?
|
// constants?
|
||||||
if (parseResult.project && builders.constants && this.template.slots.constants) {
|
if (parseResult.project && builders.constants && this.template.slots.constants) {
|
||||||
const { files } = await builders.constants.generateModule(parseResult.project);
|
const { files } = await builders.constants.generateModule(parseResult.project);
|
||||||
@ -128,6 +148,7 @@ export class ProjectBuilder implements IProjectBuilder {
|
|||||||
files,
|
files,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// utils?
|
// utils?
|
||||||
if (parseResult.globalUtils && builders.utils && this.template.slots.utils) {
|
if (parseResult.globalUtils && builders.utils && this.template.slots.utils) {
|
||||||
const { files } = await builders.utils.generateModule(parseResult.globalUtils);
|
const { files } = await builders.utils.generateModule(parseResult.globalUtils);
|
||||||
@ -137,15 +158,17 @@ export class ProjectBuilder implements IProjectBuilder {
|
|||||||
files,
|
files,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// i18n?
|
// i18n?
|
||||||
if (parseResult.globalI18n && builders.i18n && this.template.slots.i18n) {
|
if (builders.i18n && this.template.slots.i18n) {
|
||||||
const { files } = await builders.i18n.generateModule(parseResult.globalI18n);
|
const { files } = await builders.i18n.generateModule(parseResult.project);
|
||||||
|
|
||||||
buildResult.push({
|
buildResult.push({
|
||||||
path: this.template.slots.i18n.path,
|
path: this.template.slots.i18n.path,
|
||||||
files,
|
files,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// globalStyle
|
// globalStyle
|
||||||
if (parseResult.project && builders.globalStyle) {
|
if (parseResult.project && builders.globalStyle) {
|
||||||
const { files } = await builders.globalStyle.generateModule(parseResult.project);
|
const { files } = await builders.globalStyle.generateModule(parseResult.project);
|
||||||
@ -155,6 +178,7 @@ export class ProjectBuilder implements IProjectBuilder {
|
|||||||
files,
|
files,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// htmlEntry
|
// htmlEntry
|
||||||
if (parseResult.project && builders.htmlEntry) {
|
if (parseResult.project && builders.htmlEntry) {
|
||||||
const { files } = await builders.htmlEntry.generateModule(parseResult.project);
|
const { files } = await builders.htmlEntry.generateModule(parseResult.project);
|
||||||
@ -164,6 +188,7 @@ export class ProjectBuilder implements IProjectBuilder {
|
|||||||
files,
|
files,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// packageJSON
|
// packageJSON
|
||||||
if (parseResult.project && builders.packageJSON) {
|
if (parseResult.project && builders.packageJSON) {
|
||||||
const { files } = await builders.packageJSON.generateModule(parseResult.project);
|
const { files } = await builders.packageJSON.generateModule(parseResult.project);
|
||||||
@ -174,17 +199,19 @@ export class ProjectBuilder implements IProjectBuilder {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: 更多 slots 的处理??是不是可以考虑把 template 中所有的 slots 都处理下?
|
||||||
|
|
||||||
// Post Process
|
// Post Process
|
||||||
|
|
||||||
// Combine Modules
|
// Combine Modules
|
||||||
buildResult.forEach((moduleInfo) => {
|
buildResult.forEach((moduleInfo) => {
|
||||||
let targetDir = getDirFromRoot(projectRoot, moduleInfo.path);
|
let targetDir = getDirFromRoot(projectRoot, moduleInfo.path);
|
||||||
if (moduleInfo.moduleName) {
|
if (moduleInfo.moduleName) {
|
||||||
const dir = new ResultDir(moduleInfo.moduleName);
|
const dir = createResultDir(moduleInfo.moduleName);
|
||||||
targetDir.addDirectory(dir);
|
addDirectory(targetDir, dir);
|
||||||
targetDir = dir;
|
targetDir = dir;
|
||||||
}
|
}
|
||||||
moduleInfo.files.forEach((file) => targetDir.addFile(file));
|
moduleInfo.files.forEach((file) => addFile(targetDir, file));
|
||||||
});
|
});
|
||||||
|
|
||||||
return projectRoot;
|
return projectRoot;
|
||||||
|
|||||||
@ -7,7 +7,8 @@ import { createModuleBuilder } from './generator/ModuleBuilder';
|
|||||||
import { createDiskPublisher } from './publisher/disk';
|
import { createDiskPublisher } from './publisher/disk';
|
||||||
import { createZipPublisher } from './publisher/zip';
|
import { createZipPublisher } from './publisher/zip';
|
||||||
import createIceJsProjectBuilder from './solutions/icejs';
|
import createIceJsProjectBuilder from './solutions/icejs';
|
||||||
import createRecoreProjectBuilder from './solutions/recore';
|
// import createRecoreProjectBuilder from './solutions/recore';
|
||||||
|
import createRaxAppProjectBuilder from './solutions/rax-app';
|
||||||
|
|
||||||
// 引入说明
|
// 引入说明
|
||||||
import { REACT_CHUNK_NAME } from './plugins/component/react/const';
|
import { REACT_CHUNK_NAME } from './plugins/component/react/const';
|
||||||
@ -34,11 +35,15 @@ import prettier from './postprocessor/prettier';
|
|||||||
import * as utilsCommon from './utils/common';
|
import * as utilsCommon from './utils/common';
|
||||||
import * as utilsCompositeType from './utils/compositeType';
|
import * as utilsCompositeType from './utils/compositeType';
|
||||||
import * as utilsJsExpression from './utils/jsExpression';
|
import * as utilsJsExpression from './utils/jsExpression';
|
||||||
|
import * as utilsJsSlot from './utils/jsSlot';
|
||||||
import * as utilsNodeToJSX from './utils/nodeToJSX';
|
import * as utilsNodeToJSX from './utils/nodeToJSX';
|
||||||
|
import * as utilsResultHelper from './utils/resultHelper';
|
||||||
import * as utilsTemplateHelper from './utils/templateHelper';
|
import * as utilsTemplateHelper from './utils/templateHelper';
|
||||||
|
import * as utilsValidate from './utils/validate';
|
||||||
|
|
||||||
// 引入内置解决方案模块
|
// 引入内置解决方案模块
|
||||||
import icejs from './plugins/project/framework/icejs';
|
import icejs from './plugins/project/framework/icejs';
|
||||||
|
import rax from './plugins/project/framework/rax';
|
||||||
|
|
||||||
export * from './types';
|
export * from './types';
|
||||||
|
|
||||||
@ -47,10 +52,12 @@ export default {
|
|||||||
createModuleBuilder,
|
createModuleBuilder,
|
||||||
solutions: {
|
solutions: {
|
||||||
icejs: createIceJsProjectBuilder,
|
icejs: createIceJsProjectBuilder,
|
||||||
recore: createRecoreProjectBuilder,
|
// recore: createRecoreProjectBuilder,
|
||||||
|
rax: createRaxAppProjectBuilder,
|
||||||
},
|
},
|
||||||
solutionParts: {
|
solutionParts: {
|
||||||
icejs,
|
icejs,
|
||||||
|
rax,
|
||||||
},
|
},
|
||||||
publishers: {
|
publishers: {
|
||||||
disk: createDiskPublisher,
|
disk: createDiskPublisher,
|
||||||
@ -87,8 +94,11 @@ export default {
|
|||||||
common: utilsCommon,
|
common: utilsCommon,
|
||||||
compositeType: utilsCompositeType,
|
compositeType: utilsCompositeType,
|
||||||
jsExpression: utilsJsExpression,
|
jsExpression: utilsJsExpression,
|
||||||
|
jsSlot: utilsJsSlot,
|
||||||
nodeToJSX: utilsNodeToJSX,
|
nodeToJSX: utilsNodeToJSX,
|
||||||
|
resultHelper: utilsResultHelper,
|
||||||
templateHelper: utilsTemplateHelper,
|
templateHelper: utilsTemplateHelper,
|
||||||
|
validate: utilsValidate,
|
||||||
},
|
},
|
||||||
chunkNames: {
|
chunkNames: {
|
||||||
COMMON_CHUNK_NAME,
|
COMMON_CHUNK_NAME,
|
||||||
|
|||||||
@ -1,33 +0,0 @@
|
|||||||
import { CodeGeneratorError, IResultDir, IResultFile } from '../types';
|
|
||||||
|
|
||||||
export default class ResultDir implements IResultDir {
|
|
||||||
public name: string;
|
|
||||||
|
|
||||||
public dirs: IResultDir[];
|
|
||||||
|
|
||||||
public files: IResultFile[];
|
|
||||||
|
|
||||||
constructor(name: string) {
|
|
||||||
this.name = name;
|
|
||||||
this.dirs = [];
|
|
||||||
this.files = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
public addDirectory(dir: IResultDir): void {
|
|
||||||
if (this.dirs.findIndex(d => d.name === dir.name) < 0) {
|
|
||||||
this.dirs.push(dir);
|
|
||||||
} else {
|
|
||||||
throw new CodeGeneratorError('Adding same directory to one directory');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public addFile(file: IResultFile): void {
|
|
||||||
if (
|
|
||||||
this.files.findIndex(f => f.name === file.name && f.ext === file.ext) < 0
|
|
||||||
) {
|
|
||||||
this.files.push(file);
|
|
||||||
} else {
|
|
||||||
throw new CodeGeneratorError('Adding same file to one directory');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,15 +0,0 @@
|
|||||||
import { IResultFile } from '../types';
|
|
||||||
|
|
||||||
export default class ResultFile implements IResultFile {
|
|
||||||
public name: string;
|
|
||||||
|
|
||||||
public ext: string;
|
|
||||||
|
|
||||||
public content: string;
|
|
||||||
|
|
||||||
constructor(name: string, ext = 'jsx', content = '') {
|
|
||||||
this.name = name;
|
|
||||||
this.ext = ext;
|
|
||||||
this.content = content;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -2,31 +2,29 @@
|
|||||||
* 解析器是对输入的固定格式数据做拆解,使其符合引擎后续步骤预期,完成统一处理逻辑的步骤。
|
* 解析器是对输入的固定格式数据做拆解,使其符合引擎后续步骤预期,完成统一处理逻辑的步骤。
|
||||||
* 本解析器面向的是标准 schema 协议。
|
* 本解析器面向的是标准 schema 协议。
|
||||||
*/
|
*/
|
||||||
|
import changeCase from 'change-case';
|
||||||
import { SUPPORT_SCHEMA_VERSION_LIST } from '../const';
|
import { UtilItem, NodeDataType, NodeSchema, ContainerSchema, ProjectSchema, PropsMap } from '@ali/lowcode-types';
|
||||||
|
import { IPageMeta,
|
||||||
import { handleSubNodes } from '../utils/nodeToJSX';
|
|
||||||
import { uniqueArray } from '../utils/common';
|
|
||||||
|
|
||||||
import {
|
|
||||||
ChildNodeType,
|
|
||||||
CodeGeneratorError,
|
CodeGeneratorError,
|
||||||
CompatibilityError,
|
CompatibilityError,
|
||||||
DependencyType,
|
DependencyType,
|
||||||
IBasicSchema,
|
|
||||||
IComponentNodeItem,
|
|
||||||
IContainerInfo,
|
IContainerInfo,
|
||||||
IContainerNodeItem,
|
IDependency,
|
||||||
IExternalDependency,
|
IExternalDependency,
|
||||||
IInternalDependency,
|
IInternalDependency,
|
||||||
InternalDependencyType,
|
InternalDependencyType,
|
||||||
IParseResult,
|
IParseResult,
|
||||||
IProjectSchema,
|
|
||||||
ISchemaParser,
|
ISchemaParser,
|
||||||
IUtilItem,
|
|
||||||
INpmPackage,
|
INpmPackage,
|
||||||
|
IRouterInfo,
|
||||||
} from '../types';
|
} from '../types';
|
||||||
|
|
||||||
|
import { SUPPORT_SCHEMA_VERSION_LIST } from '../const';
|
||||||
|
|
||||||
|
import { handleSubNodes } from '../utils/schema';
|
||||||
|
import { uniqueArray } from '../utils/common';
|
||||||
|
|
||||||
|
|
||||||
const defaultContainer: IContainerInfo = {
|
const defaultContainer: IContainerInfo = {
|
||||||
containerType: 'Component',
|
containerType: 'Component',
|
||||||
componentName: 'Component',
|
componentName: 'Component',
|
||||||
@ -36,8 +34,20 @@ const defaultContainer: IContainerInfo = {
|
|||||||
props: {},
|
props: {},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function getRootComponentName(typeName: string, maps: Record<string, IExternalDependency>): string {
|
||||||
|
if (maps[typeName]) {
|
||||||
|
const rec = maps[typeName];
|
||||||
|
const peerName = Object.keys(maps).find((depName: string) => {
|
||||||
|
const depInfo = maps[depName];
|
||||||
|
return depName !== typeName && depInfo.package === rec.package && depInfo.version === rec.version;
|
||||||
|
});
|
||||||
|
return peerName || typeName;
|
||||||
|
}
|
||||||
|
return typeName;
|
||||||
|
}
|
||||||
|
|
||||||
class SchemaParser implements ISchemaParser {
|
class SchemaParser implements ISchemaParser {
|
||||||
validate(schema: IBasicSchema): boolean {
|
validate(schema: ProjectSchema): boolean {
|
||||||
if (SUPPORT_SCHEMA_VERSION_LIST.indexOf(schema.version) < 0) {
|
if (SUPPORT_SCHEMA_VERSION_LIST.indexOf(schema.version) < 0) {
|
||||||
throw new CompatibilityError(`Not support schema with version [${schema.version}]`);
|
throw new CompatibilityError(`Not support schema with version [${schema.version}]`);
|
||||||
}
|
}
|
||||||
@ -45,13 +55,13 @@ class SchemaParser implements ISchemaParser {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
parse(schemaSrc: IProjectSchema | string): IParseResult {
|
parse(schemaSrc: ProjectSchema | string): IParseResult {
|
||||||
// TODO: collect utils depends in JSExpression
|
// TODO: collect utils depends in JSExpression
|
||||||
const compDeps: Record<string, IExternalDependency> = {};
|
const compDeps: Record<string, IExternalDependency> = {};
|
||||||
const internalDeps: Record<string, IInternalDependency> = {};
|
const internalDeps: Record<string, IInternalDependency> = {};
|
||||||
let utilsDeps: IExternalDependency[] = [];
|
let utilsDeps: IExternalDependency[] = [];
|
||||||
|
|
||||||
let schema: IProjectSchema;
|
let schema: ProjectSchema;
|
||||||
if (typeof schemaSrc === 'string') {
|
if (typeof schemaSrc === 'string') {
|
||||||
try {
|
try {
|
||||||
schema = JSON.parse(schemaSrc);
|
schema = JSON.parse(schemaSrc);
|
||||||
@ -64,31 +74,39 @@ class SchemaParser implements ISchemaParser {
|
|||||||
|
|
||||||
// 解析三方组件依赖
|
// 解析三方组件依赖
|
||||||
schema.componentsMap.forEach((info) => {
|
schema.componentsMap.forEach((info) => {
|
||||||
info.dependencyType = DependencyType.External;
|
if (info.componentName) {
|
||||||
info.importName = info.componentName;
|
compDeps[info.componentName] = {
|
||||||
compDeps[info.componentName] = info;
|
...info,
|
||||||
|
dependencyType: DependencyType.External,
|
||||||
|
componentName: info.componentName,
|
||||||
|
exportName: info.exportName ?? info.componentName,
|
||||||
|
version: info.version || '*',
|
||||||
|
destructuring: info.destructuring ?? false,
|
||||||
|
};
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
let containers: IContainerInfo[];
|
let containers: IContainerInfo[];
|
||||||
// Test if this is a lowcode component without container
|
// Test if this is a lowcode component without container
|
||||||
if (schema.componentsTree.length > 0) {
|
if (schema.componentsTree.length > 0) {
|
||||||
const firstRoot: IContainerNodeItem = schema.componentsTree[0] as IContainerNodeItem;
|
const firstRoot: ContainerSchema = schema.componentsTree[0] as ContainerSchema;
|
||||||
|
|
||||||
if (!firstRoot.fileName) {
|
if (!('fileName' in firstRoot) || !firstRoot.fileName) {
|
||||||
// 整个 schema 描述一个容器,且无根节点定义
|
// 整个 schema 描述一个容器,且无根节点定义
|
||||||
const container: IContainerInfo = {
|
const container: IContainerInfo = {
|
||||||
...defaultContainer,
|
...defaultContainer,
|
||||||
children: schema.componentsTree as IComponentNodeItem[],
|
children: schema.componentsTree as NodeSchema[],
|
||||||
};
|
};
|
||||||
containers = [container];
|
containers = [container];
|
||||||
} else {
|
} else {
|
||||||
// 普通带 1 到多个容器的 schema
|
// 普通带 1 到多个容器的 schema
|
||||||
containers = schema.componentsTree.map((n) => {
|
containers = schema.componentsTree.map((n) => {
|
||||||
const subRoot = n as IContainerNodeItem;
|
const subRoot = n as ContainerSchema;
|
||||||
const container: IContainerInfo = {
|
const container: IContainerInfo = {
|
||||||
...subRoot,
|
...subRoot,
|
||||||
|
componentName: getRootComponentName(subRoot.componentName, compDeps),
|
||||||
containerType: subRoot.componentName,
|
containerType: subRoot.componentName,
|
||||||
moduleName: subRoot.fileName, // TODO: 驼峰化名称
|
moduleName: changeCase.pascalCase(subRoot.fileName),
|
||||||
};
|
};
|
||||||
return container;
|
return container;
|
||||||
});
|
});
|
||||||
@ -123,6 +141,7 @@ class SchemaParser implements ISchemaParser {
|
|||||||
internalDeps[dep.moduleName] = dep;
|
internalDeps[dep.moduleName] = dep;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const containersDeps = ([] as IDependency[]).concat(...containers.map((c) => c.deps || []));
|
||||||
// TODO: 不应该在出码部分解决?
|
// TODO: 不应该在出码部分解决?
|
||||||
// 处理 children 写在了 props 里的情况
|
// 处理 children 写在了 props 里的情况
|
||||||
containers.forEach((container) => {
|
containers.forEach((container) => {
|
||||||
@ -130,11 +149,18 @@ class SchemaParser implements ISchemaParser {
|
|||||||
handleSubNodes<string>(
|
handleSubNodes<string>(
|
||||||
container.children,
|
container.children,
|
||||||
{
|
{
|
||||||
node: (i: IComponentNodeItem) => {
|
node: (i: NodeSchema) => {
|
||||||
if (i.props && i.props.children && !i.children) {
|
if (i.props) {
|
||||||
i.children = i.props.children as ChildNodeType;
|
if (Array.isArray(i.props)) {
|
||||||
|
// FIXME: is array type props description
|
||||||
|
} else {
|
||||||
|
const nodeProps = i.props as PropsMap;
|
||||||
|
if (nodeProps.children && !i.children) {
|
||||||
|
i.children = nodeProps.children as NodeDataType;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return [''];
|
return '';
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -146,28 +172,30 @@ class SchemaParser implements ISchemaParser {
|
|||||||
|
|
||||||
// 分析容器内部组件依赖
|
// 分析容器内部组件依赖
|
||||||
containers.forEach((container) => {
|
containers.forEach((container) => {
|
||||||
if (container.children) {
|
const depNames = this.getComponentNames(container);
|
||||||
const depNames = this.getComponentNames(container.children);
|
// eslint-disable-next-line no-param-reassign
|
||||||
container.deps = uniqueArray<string>(depNames, (i: string) => i)
|
container.deps = uniqueArray<string>(depNames, (i: string) => i)
|
||||||
.map((depName) => internalDeps[depName] || compDeps[depName])
|
.map((depName) => internalDeps[depName] || compDeps[depName])
|
||||||
.filter((dep) => !!dep);
|
.filter(Boolean);
|
||||||
// container.deps = Object.keys(compDeps).map((depName) => compDeps[depName]);
|
// container.deps = Object.keys(compDeps).map((depName) => compDeps[depName]);
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// 分析路由配置
|
// 分析路由配置
|
||||||
const routes = containers
|
const routes: IRouterInfo['routes'] = containers
|
||||||
.filter((container) => container.containerType === 'Page')
|
.filter((container) => container.containerType === 'Page')
|
||||||
.map((page) => {
|
.map((page) => {
|
||||||
const { meta } = page;
|
const meta = page.meta;
|
||||||
if (meta) {
|
if (meta) {
|
||||||
return {
|
return {
|
||||||
path: meta.router,
|
path: (meta as IPageMeta).router || `/${page.fileName}`, // 如果无法找到页面路由信息,则用 fileName 做兜底
|
||||||
|
fileName: page.fileName,
|
||||||
componentName: page.moduleName,
|
componentName: page.moduleName,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
path: '',
|
path: '',
|
||||||
|
fileName: page.fileName,
|
||||||
componentName: page.moduleName,
|
componentName: page.moduleName,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
@ -177,7 +205,7 @@ class SchemaParser implements ISchemaParser {
|
|||||||
.filter((dep) => !!dep);
|
.filter((dep) => !!dep);
|
||||||
|
|
||||||
// 分析 Utils 依赖
|
// 分析 Utils 依赖
|
||||||
let utils: IUtilItem[];
|
let utils: UtilItem[];
|
||||||
if (schema.utils) {
|
if (schema.utils) {
|
||||||
utils = schema.utils;
|
utils = schema.utils;
|
||||||
utilsDeps = schema.utils.filter((u) => u.type !== 'function').map((u) => u.content as IExternalDependency);
|
utilsDeps = schema.utils.filter((u) => u.type !== 'function').map((u) => u.content as IExternalDependency);
|
||||||
@ -193,9 +221,21 @@ class SchemaParser implements ISchemaParser {
|
|||||||
return dep.dependencyType === DependencyType.External ? dep : null;
|
return dep.dependencyType === DependencyType.External ? dep : null;
|
||||||
})
|
})
|
||||||
.filter((dep) => dep !== null);
|
.filter((dep) => dep !== null);
|
||||||
npms.push(...((p as unknown) as INpmPackage[]));
|
const npmInfos: INpmPackage[] = p
|
||||||
|
.filter(Boolean)
|
||||||
|
.map((i) => ({
|
||||||
|
package: (i as IExternalDependency).package,
|
||||||
|
version: (i as IExternalDependency).version,
|
||||||
|
}));
|
||||||
|
npms.push(...npmInfos);
|
||||||
});
|
});
|
||||||
npms = uniqueArray<INpmPackage>(npms, (i) => i.package);
|
|
||||||
|
npms.push(...(utilsDeps.map(utilsDep => ({
|
||||||
|
package: utilsDep.package,
|
||||||
|
version: utilsDep.version,
|
||||||
|
}))));
|
||||||
|
|
||||||
|
npms = uniqueArray<INpmPackage>(npms, (i) => i.package).filter(Boolean);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
containers,
|
containers,
|
||||||
@ -209,21 +249,23 @@ class SchemaParser implements ISchemaParser {
|
|||||||
deps: routerDeps,
|
deps: routerDeps,
|
||||||
},
|
},
|
||||||
project: {
|
project: {
|
||||||
meta: schema.meta,
|
|
||||||
config: schema.config,
|
|
||||||
css: schema.css,
|
css: schema.css,
|
||||||
constants: schema.constants,
|
constants: schema.constants,
|
||||||
|
config: schema.config || {},
|
||||||
|
meta: schema.meta || {},
|
||||||
i18n: schema.i18n,
|
i18n: schema.i18n,
|
||||||
packages: npms,
|
containersDeps,
|
||||||
|
utilsDeps,
|
||||||
|
packages: npms || [],
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
getComponentNames(children: ChildNodeType): string[] {
|
getComponentNames(children: NodeDataType): string[] {
|
||||||
return handleSubNodes<string>(
|
return handleSubNodes<string>(
|
||||||
children,
|
children,
|
||||||
{
|
{
|
||||||
node: (i: IComponentNodeItem) => [i.componentName],
|
node: (i: NodeSchema) => i.componentName,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
rerun: true,
|
rerun: true,
|
||||||
|
|||||||
@ -28,29 +28,32 @@ function groupDepsByPack(deps: IDependency[]): Record<string, IDependency[]> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// TODO: main 这个信息到底怎么用,是不是外部包不需要使用?
|
// TODO: main 这个信息到底怎么用,是不是外部包不需要使用?
|
||||||
// deps.forEach(dep => {
|
const depMainBlackList = ['lib', 'lib/index', 'es', 'es/index', 'main'];
|
||||||
// if (dep.dependencyType === DependencyType.Internal) {
|
|
||||||
// addDep(
|
|
||||||
// `${(dep as IInternalDependency).moduleName}${`/${dep.main}` || ''}`,
|
|
||||||
// dep,
|
|
||||||
// );
|
|
||||||
// } else {
|
|
||||||
// addDep(`${(dep as IExternalDependency).package}${`/${dep.main}` || ''}`, dep);
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
|
|
||||||
deps.forEach((dep) => {
|
deps.forEach((dep) => {
|
||||||
if (dep.dependencyType === DependencyType.Internal) {
|
if (dep.dependencyType === DependencyType.Internal) {
|
||||||
addDep(`${(dep as IInternalDependency).moduleName}`, dep);
|
addDep(`${(dep as IInternalDependency).moduleName}${dep.main ? `/${dep.main}` : ''}`, dep);
|
||||||
} else {
|
} else {
|
||||||
addDep(`${(dep as IExternalDependency).package}`, dep);
|
let depMain = '';
|
||||||
|
// TODO: 部分类型的 main 暂时认为没用
|
||||||
|
if (dep.main && depMainBlackList.indexOf(dep.main) < 0) {
|
||||||
|
depMain = dep.main;
|
||||||
|
}
|
||||||
|
if (depMain.substring(0, 1) === '/') {
|
||||||
|
depMain = depMain.substring(1);
|
||||||
|
}
|
||||||
|
addDep(`${(dep as IExternalDependency).package}${depMain ? `/${depMain}` : ''}`, dep);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return depMap;
|
return depMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildPackageImport(pkg: string, deps: IDependency[], targetFileType: string): ICodeChunk[] {
|
function buildPackageImport(
|
||||||
|
pkg: string,
|
||||||
|
deps: IDependency[],
|
||||||
|
targetFileType: string,
|
||||||
|
useAliasName: boolean,
|
||||||
|
): ICodeChunk[] {
|
||||||
const chunks: ICodeChunk[] = [];
|
const chunks: ICodeChunk[] = [];
|
||||||
let defaultImport = '';
|
let defaultImport = '';
|
||||||
let defaultImportAs = '';
|
let defaultImportAs = '';
|
||||||
@ -58,8 +61,9 @@ function buildPackageImport(pkg: string, deps: IDependency[], targetFileType: st
|
|||||||
|
|
||||||
deps.forEach((dep) => {
|
deps.forEach((dep) => {
|
||||||
const srcName = dep.exportName;
|
const srcName = dep.exportName;
|
||||||
let targetName = dep.importName || dep.exportName;
|
let targetName = dep.componentName || dep.exportName;
|
||||||
|
|
||||||
|
// 如果是自组件,则导出父组件,并且根据自组件命名规则,判断是否需要定义标识符
|
||||||
if (dep.subName) {
|
if (dep.subName) {
|
||||||
if (targetName !== `${srcName}.${dep.subName}`) {
|
if (targetName !== `${srcName}.${dep.subName}`) {
|
||||||
if (!isValidIdentifier(targetName)) {
|
if (!isValidIdentifier(targetName)) {
|
||||||
@ -69,9 +73,14 @@ function buildPackageImport(pkg: string, deps: IDependency[], targetFileType: st
|
|||||||
chunks.push({
|
chunks.push({
|
||||||
type: ChunkType.STRING,
|
type: ChunkType.STRING,
|
||||||
fileType: targetFileType,
|
fileType: targetFileType,
|
||||||
name: COMMON_CHUNK_NAME.FileVarDefine,
|
name: COMMON_CHUNK_NAME.ImportAliasDefine,
|
||||||
content: `const ${targetName} = ${srcName}.${dep.subName};`,
|
content: `const ${targetName} = ${srcName}.${dep.subName};`,
|
||||||
linkAfter: [COMMON_CHUNK_NAME.ExternalDepsImport, COMMON_CHUNK_NAME.InternalDepsImport],
|
linkAfter: [COMMON_CHUNK_NAME.ExternalDepsImport, COMMON_CHUNK_NAME.InternalDepsImport],
|
||||||
|
ext: {
|
||||||
|
originalName: `${srcName}.${dep.subName}`,
|
||||||
|
aliasName: targetName,
|
||||||
|
dependency: dep,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -86,15 +95,30 @@ function buildPackageImport(pkg: string, deps: IDependency[], targetFileType: st
|
|||||||
defaultImport = srcName;
|
defaultImport = srcName;
|
||||||
defaultImportAs = targetName;
|
defaultImportAs = targetName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (targetName !== srcName) {
|
||||||
|
chunks.push({
|
||||||
|
type: ChunkType.STRING,
|
||||||
|
fileType: targetFileType,
|
||||||
|
name: COMMON_CHUNK_NAME.ImportAliasDefine,
|
||||||
|
content: '',
|
||||||
|
linkAfter: [COMMON_CHUNK_NAME.ExternalDepsImport, COMMON_CHUNK_NAME.InternalDepsImport],
|
||||||
|
ext: {
|
||||||
|
originalName: srcName,
|
||||||
|
aliasName: targetName,
|
||||||
|
dependency: dep,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const items = Object.keys(imports).map((src) => {
|
const items = Object.keys(imports).map((src) => {
|
||||||
return src === imports[src] ? src : `${src} as ${imports[src]}`;
|
return src === imports[src] || !useAliasName ? src : `${src} as ${imports[src]}`;
|
||||||
});
|
});
|
||||||
|
|
||||||
const statementL = ['import'];
|
const statementL = ['import'];
|
||||||
if (defaultImport) {
|
if (defaultImport) {
|
||||||
statementL.push(defaultImportAs);
|
statementL.push(useAliasName ? defaultImportAs : defaultImport);
|
||||||
if (items.length > 0) {
|
if (items.length > 0) {
|
||||||
statementL.push(',');
|
statementL.push(',');
|
||||||
}
|
}
|
||||||
@ -129,13 +153,15 @@ function buildPackageImport(pkg: string, deps: IDependency[], targetFileType: st
|
|||||||
}
|
}
|
||||||
|
|
||||||
type PluginConfig = {
|
type PluginConfig = {
|
||||||
fileType: string;
|
fileType?: string; // 导出的文件类型
|
||||||
|
useAliasName?: boolean; // 是否使用 componentName 重命名组件 identifier
|
||||||
};
|
};
|
||||||
|
|
||||||
const pluginFactory: BuilderComponentPluginFactory<PluginConfig> = (config?: PluginConfig) => {
|
const pluginFactory: BuilderComponentPluginFactory<PluginConfig> = (config?: PluginConfig) => {
|
||||||
const cfg: PluginConfig = {
|
const cfg = {
|
||||||
fileType: FileType.JS,
|
fileType: FileType.JS,
|
||||||
...config,
|
useAliasName: true,
|
||||||
|
...(config || {}),
|
||||||
};
|
};
|
||||||
|
|
||||||
const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => {
|
const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => {
|
||||||
@ -149,7 +175,7 @@ const pluginFactory: BuilderComponentPluginFactory<PluginConfig> = (config?: Plu
|
|||||||
const packs = groupDepsByPack(ir.deps);
|
const packs = groupDepsByPack(ir.deps);
|
||||||
|
|
||||||
Object.keys(packs).forEach((pkg) => {
|
Object.keys(packs).forEach((pkg) => {
|
||||||
const chunks = buildPackageImport(pkg, packs[pkg], cfg.fileType);
|
const chunks = buildPackageImport(pkg, packs[pkg], cfg.fileType, cfg.useAliasName);
|
||||||
next.chunks.push(...chunks);
|
next.chunks.push(...chunks);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,12 +1,6 @@
|
|||||||
import { COMMON_CHUNK_NAME } from '../../const/generator';
|
import { COMMON_CHUNK_NAME } from '../../const/generator';
|
||||||
|
|
||||||
import {
|
import { BuilderComponentPlugin, BuilderComponentPluginFactory, ChunkType, FileType, ICodeStruct } from '../../types';
|
||||||
BuilderComponentPlugin,
|
|
||||||
BuilderComponentPluginFactory,
|
|
||||||
ChunkType,
|
|
||||||
FileType,
|
|
||||||
ICodeStruct,
|
|
||||||
} from '../../types';
|
|
||||||
|
|
||||||
// TODO: How to merge this logic to common deps
|
// TODO: How to merge this logic to common deps
|
||||||
const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
|
const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
|
||||||
|
|||||||
@ -0,0 +1,35 @@
|
|||||||
|
import { COMMON_CHUNK_NAME } from '../../../const/generator';
|
||||||
|
|
||||||
|
import {
|
||||||
|
BuilderComponentPlugin,
|
||||||
|
BuilderComponentPluginFactory,
|
||||||
|
ChunkType,
|
||||||
|
FileType,
|
||||||
|
ICodeStruct,
|
||||||
|
} from '../../../types';
|
||||||
|
|
||||||
|
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: `
|
||||||
|
// 注意: 出码引擎注入的临时变量默认都以 "__$$" 开头,禁止在搭建的代码中直接访问。
|
||||||
|
// 例外:rax 框架的导出名和各种组件名除外。
|
||||||
|
import { createElement, Component } from 'rax';
|
||||||
|
import { withRouter as __$$withRouter } from 'rax-app';
|
||||||
|
`,
|
||||||
|
linkAfter: [],
|
||||||
|
});
|
||||||
|
|
||||||
|
return next;
|
||||||
|
};
|
||||||
|
return plugin;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default pluginFactory;
|
||||||
18
packages/code-generator/src/plugins/component/rax/const.ts
Normal file
18
packages/code-generator/src/plugins/component/rax/const.ts
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
export const RAX_CHUNK_NAME = {
|
||||||
|
ClassDidMountBegin: 'RaxComponentClassDidMountBegin',
|
||||||
|
ClassDidMountContent: 'RaxComponentClassDidMountContent',
|
||||||
|
ClassDidMountEnd: 'RaxComponentClassDidMountEnd',
|
||||||
|
ClassWillUnmountBegin: 'RaxComponentClassWillUnmountBegin',
|
||||||
|
ClassWillUnmountContent: 'RaxComponentClassWillUnmountContent',
|
||||||
|
ClassWillUnmountEnd: 'RaxComponentClassWillUnmountEnd',
|
||||||
|
ClassRenderBegin: 'RaxComponentClassRenderBegin',
|
||||||
|
ClassRenderPre: 'RaxComponentClassRenderPre',
|
||||||
|
ClassRenderJSX: 'RaxComponentClassRenderJSX',
|
||||||
|
ClassRenderEnd: 'RaxComponentClassRenderEnd',
|
||||||
|
MethodsBegin: 'RaxComponentMethodsBegin',
|
||||||
|
MethodsContent: 'RaxComponentMethodsContent',
|
||||||
|
MethodsEnd: 'RaxComponentMethodsEnd',
|
||||||
|
LifeCyclesBegin: 'RaxComponentLifeCyclesBegin',
|
||||||
|
LifeCyclesContent: 'RaxComponentLifeCyclesContent',
|
||||||
|
LifeCyclesEnd: 'RaxComponentLifeCyclesEnd',
|
||||||
|
};
|
||||||
@ -0,0 +1,144 @@
|
|||||||
|
import changeCase from 'change-case';
|
||||||
|
import { COMMON_CHUNK_NAME, CLASS_DEFINE_CHUNK_NAME } from '../../../const/generator';
|
||||||
|
import { RAX_CHUNK_NAME } from './const';
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
// 将模块名转换成 PascalCase 的格式,并添加特定后缀,防止命名冲突
|
||||||
|
const componentClassName = `${changeCase.pascalCase(ir.moduleName)}$$Page`;
|
||||||
|
|
||||||
|
next.chunks.push({
|
||||||
|
type: ChunkType.STRING,
|
||||||
|
fileType: FileType.JSX,
|
||||||
|
name: CLASS_DEFINE_CHUNK_NAME.Start,
|
||||||
|
content: `class ${componentClassName} extends Component {`,
|
||||||
|
linkAfter: [
|
||||||
|
COMMON_CHUNK_NAME.ExternalDepsImport,
|
||||||
|
COMMON_CHUNK_NAME.InternalDepsImport,
|
||||||
|
COMMON_CHUNK_NAME.ImportAliasDefine,
|
||||||
|
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,
|
||||||
|
CLASS_DEFINE_CHUNK_NAME.InsPrivateMethod,
|
||||||
|
RAX_CHUNK_NAME.ClassRenderEnd,
|
||||||
|
RAX_CHUNK_NAME.MethodsEnd,
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
// 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: RAX_CHUNK_NAME.ClassDidMountBegin,
|
||||||
|
content: 'componentDidMount() {',
|
||||||
|
linkAfter: [CLASS_DEFINE_CHUNK_NAME.Start, CLASS_DEFINE_CHUNK_NAME.InsVar, CLASS_DEFINE_CHUNK_NAME.InsMethod],
|
||||||
|
});
|
||||||
|
|
||||||
|
next.chunks.push({
|
||||||
|
type: ChunkType.STRING,
|
||||||
|
fileType: FileType.JSX,
|
||||||
|
name: RAX_CHUNK_NAME.ClassDidMountEnd,
|
||||||
|
content: '}',
|
||||||
|
linkAfter: [RAX_CHUNK_NAME.ClassDidMountBegin, RAX_CHUNK_NAME.ClassDidMountContent],
|
||||||
|
});
|
||||||
|
|
||||||
|
next.chunks.push({
|
||||||
|
type: ChunkType.STRING,
|
||||||
|
fileType: FileType.JSX,
|
||||||
|
name: RAX_CHUNK_NAME.ClassWillUnmountBegin,
|
||||||
|
content: 'componentWillUnmount() {',
|
||||||
|
linkAfter: [
|
||||||
|
CLASS_DEFINE_CHUNK_NAME.Start,
|
||||||
|
CLASS_DEFINE_CHUNK_NAME.InsVar,
|
||||||
|
CLASS_DEFINE_CHUNK_NAME.InsMethod,
|
||||||
|
RAX_CHUNK_NAME.ClassDidMountEnd,
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
next.chunks.push({
|
||||||
|
type: ChunkType.STRING,
|
||||||
|
fileType: FileType.JSX,
|
||||||
|
name: RAX_CHUNK_NAME.ClassWillUnmountEnd,
|
||||||
|
content: '}',
|
||||||
|
linkAfter: [RAX_CHUNK_NAME.ClassWillUnmountBegin, RAX_CHUNK_NAME.ClassWillUnmountContent],
|
||||||
|
});
|
||||||
|
|
||||||
|
next.chunks.push({
|
||||||
|
type: ChunkType.STRING,
|
||||||
|
fileType: FileType.JSX,
|
||||||
|
name: RAX_CHUNK_NAME.ClassRenderBegin,
|
||||||
|
content: 'render() {',
|
||||||
|
linkAfter: [RAX_CHUNK_NAME.ClassDidMountEnd, RAX_CHUNK_NAME.ClassWillUnmountEnd],
|
||||||
|
});
|
||||||
|
|
||||||
|
next.chunks.push({
|
||||||
|
type: ChunkType.STRING,
|
||||||
|
fileType: FileType.JSX,
|
||||||
|
name: RAX_CHUNK_NAME.ClassRenderEnd,
|
||||||
|
content: '}',
|
||||||
|
linkAfter: [RAX_CHUNK_NAME.ClassRenderBegin, RAX_CHUNK_NAME.ClassRenderPre, RAX_CHUNK_NAME.ClassRenderJSX],
|
||||||
|
});
|
||||||
|
|
||||||
|
next.chunks.push({
|
||||||
|
type: ChunkType.STRING,
|
||||||
|
fileType: FileType.JSX,
|
||||||
|
name: COMMON_CHUNK_NAME.FileExport,
|
||||||
|
content: `export default __$$withRouter(${componentClassName});`,
|
||||||
|
linkAfter: [
|
||||||
|
COMMON_CHUNK_NAME.ExternalDepsImport,
|
||||||
|
COMMON_CHUNK_NAME.InternalDepsImport,
|
||||||
|
COMMON_CHUNK_NAME.ImportAliasDefine,
|
||||||
|
COMMON_CHUNK_NAME.FileVarDefine,
|
||||||
|
COMMON_CHUNK_NAME.FileUtilDefine,
|
||||||
|
CLASS_DEFINE_CHUNK_NAME.End,
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
return next;
|
||||||
|
};
|
||||||
|
return plugin;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default pluginFactory;
|
||||||
@ -33,7 +33,7 @@ const pluginFactory: BuilderComponentPluginFactory<PluginConfig> = (config?) =>
|
|||||||
const scope = Scope.createRootScope();
|
const scope = Scope.createRootScope();
|
||||||
|
|
||||||
if (ir.state) {
|
if (ir.state) {
|
||||||
const { state } = ir;
|
const state = ir.state;
|
||||||
const fields = Object.keys(state).map<string>((stateName) => {
|
const fields = Object.keys(state).map<string>((stateName) => {
|
||||||
// TODO: 这里用什么 handlers?
|
// TODO: 这里用什么 handlers?
|
||||||
const value = generateCompositeType(state[stateName], scope);
|
const value = generateCompositeType(state[stateName], scope);
|
||||||
|
|||||||
@ -0,0 +1,116 @@
|
|||||||
|
import { CLASS_DEFINE_CHUNK_NAME, COMMON_CHUNK_NAME } from '../../../const/generator';
|
||||||
|
|
||||||
|
import {
|
||||||
|
BuilderComponentPlugin,
|
||||||
|
BuilderComponentPluginFactory,
|
||||||
|
ChunkType,
|
||||||
|
FileType,
|
||||||
|
ICodeStruct,
|
||||||
|
} from '../../../types';
|
||||||
|
import { RAX_CHUNK_NAME } from './const';
|
||||||
|
|
||||||
|
type PluginConfig = {
|
||||||
|
fileType: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
const pluginFactory: BuilderComponentPluginFactory<PluginConfig> = (config?) => {
|
||||||
|
const cfg: PluginConfig = {
|
||||||
|
fileType: FileType.JSX,
|
||||||
|
...config,
|
||||||
|
};
|
||||||
|
|
||||||
|
const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => {
|
||||||
|
const next: ICodeStruct = {
|
||||||
|
...pre,
|
||||||
|
};
|
||||||
|
|
||||||
|
next.chunks.push({
|
||||||
|
type: ChunkType.STRING,
|
||||||
|
fileType: cfg.fileType,
|
||||||
|
name: COMMON_CHUNK_NAME.InternalDepsImport,
|
||||||
|
content: 'import __$$constants from \'../../constants\';',
|
||||||
|
linkAfter: [COMMON_CHUNK_NAME.ExternalDepsImport],
|
||||||
|
});
|
||||||
|
|
||||||
|
// TODO: i18n 是可选的,如果没有 i18n 这个文件怎么办?该怎么判断?
|
||||||
|
next.chunks.push({
|
||||||
|
type: ChunkType.STRING,
|
||||||
|
fileType: cfg.fileType,
|
||||||
|
name: COMMON_CHUNK_NAME.InternalDepsImport,
|
||||||
|
content: 'import * as __$$i18n from \'../../i18n\';',
|
||||||
|
linkAfter: [COMMON_CHUNK_NAME.ExternalDepsImport],
|
||||||
|
});
|
||||||
|
|
||||||
|
next.chunks.push({
|
||||||
|
type: ChunkType.STRING,
|
||||||
|
fileType: cfg.fileType,
|
||||||
|
name: CLASS_DEFINE_CHUNK_NAME.InsVar,
|
||||||
|
content: `
|
||||||
|
_context = this._createContext();
|
||||||
|
`,
|
||||||
|
linkAfter: [CLASS_DEFINE_CHUNK_NAME.Start],
|
||||||
|
});
|
||||||
|
|
||||||
|
next.chunks.push({
|
||||||
|
type: ChunkType.STRING,
|
||||||
|
fileType: cfg.fileType,
|
||||||
|
name: CLASS_DEFINE_CHUNK_NAME.InsPrivateMethod,
|
||||||
|
content: `
|
||||||
|
_createContext() {
|
||||||
|
const self = this;
|
||||||
|
|
||||||
|
// 保存下最新的状态,这样 setState 可以搞成同步一样的了
|
||||||
|
self._latestState = self.state;
|
||||||
|
|
||||||
|
const context = {
|
||||||
|
get state() {
|
||||||
|
// 这里直接获取最新的 state,从而能避免一些 React/Rax 这样的框架因为异步 setState 而导致的一些问题
|
||||||
|
return self._latestState;
|
||||||
|
},
|
||||||
|
setState(newState) {
|
||||||
|
self._latestState = { ...self._latestState, ...newState };
|
||||||
|
self.setState(newState);
|
||||||
|
},
|
||||||
|
get dataSourceMap() {
|
||||||
|
return self._dataSourceEngine.dataSourceMap || {};
|
||||||
|
},
|
||||||
|
async reloadDataSource() {
|
||||||
|
await self._dataSourceEngine.reloadDataSource();
|
||||||
|
},
|
||||||
|
get utils() {
|
||||||
|
return self._utils;
|
||||||
|
},
|
||||||
|
get page() {
|
||||||
|
return context;
|
||||||
|
},
|
||||||
|
get component() {
|
||||||
|
return context;
|
||||||
|
},
|
||||||
|
get props() {
|
||||||
|
return self.props;
|
||||||
|
},
|
||||||
|
get constants() {
|
||||||
|
return __$$constants;
|
||||||
|
},
|
||||||
|
i18n: __$$i18n.i18n,
|
||||||
|
i18nFormat: __$$i18n.i18nFormat,
|
||||||
|
getLocale: __$$i18n.getLocale,
|
||||||
|
setLocale(locale) {
|
||||||
|
__$$i18n.setLocale(locale);
|
||||||
|
self.forceUpdate();
|
||||||
|
},
|
||||||
|
...this._methods,
|
||||||
|
};
|
||||||
|
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
linkAfter: [RAX_CHUNK_NAME.ClassRenderEnd],
|
||||||
|
});
|
||||||
|
|
||||||
|
return next;
|
||||||
|
};
|
||||||
|
return plugin;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default pluginFactory;
|
||||||
@ -45,7 +45,7 @@ const pluginFactory: BuilderComponentPluginFactory<PluginConfig> = (config?) =>
|
|||||||
dataSourceItems.forEach((ds) => {
|
dataSourceItems.forEach((ds) => {
|
||||||
const dsType = ds.type || 'fetch';
|
const dsType = ds.type || 'fetch';
|
||||||
if (!(dsType in requestHandlersMap) && dsType !== 'custom') {
|
if (!(dsType in requestHandlersMap) && dsType !== 'custom') {
|
||||||
const handlerFactoryName = `__$$create${ changeCase.pascal(dsType) }RequestHandler`;
|
const handlerFactoryName = '__$$create' + changeCase.pascal(dsType) + 'RequestHandler';
|
||||||
|
|
||||||
requestHandlersMap[dsType] = {
|
requestHandlersMap[dsType] = {
|
||||||
type: 'JSExpression',
|
type: 'JSExpression',
|
||||||
|
|||||||
@ -0,0 +1,74 @@
|
|||||||
|
import { CLASS_DEFINE_CHUNK_NAME, COMMON_CHUNK_NAME } from '../../../const/generator';
|
||||||
|
|
||||||
|
import {
|
||||||
|
BuilderComponentPlugin,
|
||||||
|
BuilderComponentPluginFactory,
|
||||||
|
ChunkType,
|
||||||
|
FileType,
|
||||||
|
ICodeStruct,
|
||||||
|
} from '../../../types';
|
||||||
|
import { RAX_CHUNK_NAME } from './const';
|
||||||
|
|
||||||
|
type PluginConfig = {
|
||||||
|
fileType: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
const pluginFactory: BuilderComponentPluginFactory<PluginConfig> = (config?) => {
|
||||||
|
const cfg: PluginConfig = {
|
||||||
|
fileType: FileType.JSX,
|
||||||
|
...config,
|
||||||
|
};
|
||||||
|
|
||||||
|
const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => {
|
||||||
|
const next: ICodeStruct = {
|
||||||
|
...pre,
|
||||||
|
};
|
||||||
|
|
||||||
|
next.chunks.push({
|
||||||
|
type: ChunkType.STRING,
|
||||||
|
fileType: cfg.fileType,
|
||||||
|
name: COMMON_CHUNK_NAME.InternalDepsImport,
|
||||||
|
// TODO: 下面这个路径有没有更好的方式来获取?而非写死
|
||||||
|
content: `
|
||||||
|
import __$$projectUtils from '../../utils';
|
||||||
|
`,
|
||||||
|
linkAfter: [COMMON_CHUNK_NAME.ExternalDepsImport],
|
||||||
|
});
|
||||||
|
|
||||||
|
next.chunks.push({
|
||||||
|
type: ChunkType.STRING,
|
||||||
|
fileType: cfg.fileType,
|
||||||
|
name: CLASS_DEFINE_CHUNK_NAME.InsVar,
|
||||||
|
content: '_utils = this._defineUtils();',
|
||||||
|
linkAfter: [CLASS_DEFINE_CHUNK_NAME.Start],
|
||||||
|
});
|
||||||
|
|
||||||
|
next.chunks.push({
|
||||||
|
type: ChunkType.STRING,
|
||||||
|
fileType: cfg.fileType,
|
||||||
|
name: CLASS_DEFINE_CHUNK_NAME.InsPrivateMethod,
|
||||||
|
|
||||||
|
// 绑定下上下文,这样在所有的 utils 里面都能通过 this.xxx 来访问上下文了
|
||||||
|
content: `
|
||||||
|
_defineUtils() {
|
||||||
|
const utils = {
|
||||||
|
...__$$projectUtils,
|
||||||
|
};
|
||||||
|
|
||||||
|
Object.entries(utils).forEach(([name, util]) => {
|
||||||
|
if (typeof util === 'function') {
|
||||||
|
utils[name] = util.bind(this._context);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return utils;
|
||||||
|
}`,
|
||||||
|
linkAfter: [RAX_CHUNK_NAME.ClassRenderEnd],
|
||||||
|
});
|
||||||
|
|
||||||
|
return next;
|
||||||
|
};
|
||||||
|
return plugin;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default pluginFactory;
|
||||||
@ -34,7 +34,7 @@ const pluginFactory: BuilderComponentPluginFactory<PluginConfig> = (config?) =>
|
|||||||
// Rax 先只支持 didMount 和 willUnmount 吧
|
// Rax 先只支持 didMount 和 willUnmount 吧
|
||||||
|
|
||||||
const ir = next.ir as IContainerInfo;
|
const ir = next.ir as IContainerInfo;
|
||||||
const { lifeCycles } = ir;
|
const lifeCycles = ir.lifeCycles;
|
||||||
|
|
||||||
if (lifeCycles && !_.isEmpty(lifeCycles)) {
|
if (lifeCycles && !_.isEmpty(lifeCycles)) {
|
||||||
Object.entries(lifeCycles).forEach(([lifeCycleName, lifeCycleMethodExpr]) => {
|
Object.entries(lifeCycles).forEach(([lifeCycleName, lifeCycleMethodExpr]) => {
|
||||||
|
|||||||
@ -0,0 +1,95 @@
|
|||||||
|
import { CLASS_DEFINE_CHUNK_NAME } from '../../../const/generator';
|
||||||
|
|
||||||
|
import {
|
||||||
|
BuilderComponentPlugin,
|
||||||
|
BuilderComponentPluginFactory,
|
||||||
|
ChunkType,
|
||||||
|
FileType,
|
||||||
|
ICodeStruct,
|
||||||
|
IContainerInfo,
|
||||||
|
} from '../../../types';
|
||||||
|
|
||||||
|
import { RAX_CHUNK_NAME } from './const';
|
||||||
|
|
||||||
|
type PluginConfig = {
|
||||||
|
fileType: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
const pluginFactory: BuilderComponentPluginFactory<PluginConfig> = (config?) => {
|
||||||
|
const cfg: PluginConfig = {
|
||||||
|
fileType: FileType.JSX,
|
||||||
|
...config,
|
||||||
|
};
|
||||||
|
|
||||||
|
const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => {
|
||||||
|
const next: ICodeStruct = {
|
||||||
|
...pre,
|
||||||
|
};
|
||||||
|
|
||||||
|
const ir = next.ir as IContainerInfo;
|
||||||
|
|
||||||
|
next.chunks.push({
|
||||||
|
type: ChunkType.STRING,
|
||||||
|
fileType: cfg.fileType,
|
||||||
|
name: CLASS_DEFINE_CHUNK_NAME.InsVar,
|
||||||
|
content: `
|
||||||
|
_methods = this._defineMethods();
|
||||||
|
`,
|
||||||
|
linkAfter: [CLASS_DEFINE_CHUNK_NAME.Start],
|
||||||
|
});
|
||||||
|
|
||||||
|
next.chunks.push({
|
||||||
|
type: ChunkType.STRING,
|
||||||
|
fileType: cfg.fileType,
|
||||||
|
name: RAX_CHUNK_NAME.MethodsBegin,
|
||||||
|
content: `
|
||||||
|
_defineMethods() {
|
||||||
|
const __$$methods = ({
|
||||||
|
`,
|
||||||
|
linkAfter: [
|
||||||
|
RAX_CHUNK_NAME.ClassRenderEnd,
|
||||||
|
CLASS_DEFINE_CHUNK_NAME.InsPrivateMethod,
|
||||||
|
RAX_CHUNK_NAME.LifeCyclesEnd,
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
next.chunks.push({
|
||||||
|
type: ChunkType.STRING,
|
||||||
|
fileType: cfg.fileType,
|
||||||
|
name: RAX_CHUNK_NAME.MethodsEnd,
|
||||||
|
content: `
|
||||||
|
});
|
||||||
|
|
||||||
|
// 为所有的方法绑定上下文
|
||||||
|
Object.entries(__$$methods).forEach(([methodName, method]) => {
|
||||||
|
if (typeof method === 'function') {
|
||||||
|
__$$methods[methodName] = (...args) => {
|
||||||
|
return method.apply(this._context, args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return __$$methods;
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
linkAfter: [RAX_CHUNK_NAME.MethodsBegin, RAX_CHUNK_NAME.MethodsContent],
|
||||||
|
});
|
||||||
|
|
||||||
|
if (ir.methods && Object.keys(ir.methods).length > 0) {
|
||||||
|
Object.entries(ir.methods).forEach(([methodName, methodDefine]) => {
|
||||||
|
next.chunks.push({
|
||||||
|
type: ChunkType.STRING,
|
||||||
|
fileType: cfg.fileType,
|
||||||
|
name: RAX_CHUNK_NAME.MethodsContent,
|
||||||
|
content: `${methodName}: (${methodDefine.value}),`,
|
||||||
|
linkAfter: [RAX_CHUNK_NAME.MethodsBegin],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return next;
|
||||||
|
};
|
||||||
|
return plugin;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default pluginFactory;
|
||||||
350
packages/code-generator/src/plugins/component/rax/jsx.ts
Normal file
350
packages/code-generator/src/plugins/component/rax/jsx.ts
Normal file
@ -0,0 +1,350 @@
|
|||||||
|
import { NodeSchema, JSExpression, NpmInfo, CompositeValue, isJSExpression } from '@ali/lowcode-types';
|
||||||
|
|
||||||
|
import _ from 'lodash';
|
||||||
|
import changeCase from 'change-case';
|
||||||
|
import { Expression } from '@babel/types';
|
||||||
|
import {
|
||||||
|
BuilderComponentPlugin,
|
||||||
|
BuilderComponentPluginFactory,
|
||||||
|
ChunkType,
|
||||||
|
CodePiece,
|
||||||
|
FileType,
|
||||||
|
ICodeChunk,
|
||||||
|
ICodeStruct,
|
||||||
|
IContainerInfo,
|
||||||
|
PIECE_TYPE,
|
||||||
|
HandlerSet,
|
||||||
|
IScope,
|
||||||
|
NodeGeneratorConfig,
|
||||||
|
NodePlugin,
|
||||||
|
AttrPlugin,
|
||||||
|
} from '../../../types';
|
||||||
|
|
||||||
|
import { RAX_CHUNK_NAME } from './const';
|
||||||
|
import { COMMON_CHUNK_NAME } from '../../../const/generator';
|
||||||
|
|
||||||
|
import { generateExpression } from '../../../utils/jsExpression';
|
||||||
|
import { createNodeGenerator, generateConditionReactCtrl, generateReactExprInJS } from '../../../utils/nodeToJSX';
|
||||||
|
import { generateCompositeType } from '../../../utils/compositeType';
|
||||||
|
import Scope from '../../../utils/Scope';
|
||||||
|
import {
|
||||||
|
parseExpression,
|
||||||
|
parseExpressionConvertThis2Context,
|
||||||
|
parseExpressionGetGlobalVariables,
|
||||||
|
} from '../../../utils/expressionParser';
|
||||||
|
|
||||||
|
type PluginConfig = {
|
||||||
|
fileType: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
// TODO: componentName 若并非大写字符打头,甚至并非是一个有效的 JS 标识符怎么办??
|
||||||
|
// FIXME: 我想了下,这块应该放到解析阶段就去做掉,对所有 componentName 做 identifier validate,然后对不合法的做统一替换。
|
||||||
|
const pluginFactory: BuilderComponentPluginFactory<PluginConfig> = (config?) => {
|
||||||
|
const cfg: PluginConfig = {
|
||||||
|
fileType: FileType.JSX,
|
||||||
|
...config,
|
||||||
|
};
|
||||||
|
|
||||||
|
const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => {
|
||||||
|
const next: ICodeStruct = {
|
||||||
|
...pre,
|
||||||
|
};
|
||||||
|
|
||||||
|
const ir = next.ir as IContainerInfo;
|
||||||
|
const rootScope = Scope.createRootScope();
|
||||||
|
|
||||||
|
// Rax 构建到小程序的时候,不能给组件起起别名,得直接引用,故这里将所有的别名替换掉
|
||||||
|
// 先收集下所有的 alias 的映射
|
||||||
|
const componentsNameAliasMap = new Map<string, string>();
|
||||||
|
next.chunks.forEach((chunk) => {
|
||||||
|
if (isImportAliasDefineChunk(chunk)) {
|
||||||
|
componentsNameAliasMap.set(chunk.ext.aliasName, chunk.ext.originalName);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 注意:这里其实隐含了一个假设:schema 中的 componentName 应该是一个有效的 JS 标识符,而且是大写字母打头的
|
||||||
|
// FIXME: 为了快速修复临时加的逻辑,需要用 pre-process 的方式替代处理。
|
||||||
|
const mapComponentNameToAliasOrKeepIt = (componentName: string) => componentsNameAliasMap.get(componentName) || componentName;
|
||||||
|
|
||||||
|
// 然后过滤掉所有的别名 chunks
|
||||||
|
next.chunks = next.chunks.filter((chunk) => !isImportAliasDefineChunk(chunk));
|
||||||
|
|
||||||
|
// 如果直接按目前的 React 的方式之间出码 JSX 的话,会有 3 个问题:
|
||||||
|
// 1. 小程序出码的时候,循环变量没法拿到
|
||||||
|
// 2. 小程序出码的时候,很容易出现 Uncaught TypeError: Cannot read property 'avatar' of undefined 这样的异常(如下图的 50 行) -- 因为若直接出码,Rax 构建到小程序的时候会立即计算所有在视图中用到的变量
|
||||||
|
// 3. 通过 this.xxx 能拿到的东西太多了,而且自定义的 methods 可能会无意间破坏 Rax 框架或小程序框架在页面 this 上的东东
|
||||||
|
const customHandlers: HandlerSet<string> = {
|
||||||
|
expression(input: JSExpression, scope: IScope) {
|
||||||
|
return transformJsExpr(generateExpression(input), scope);
|
||||||
|
},
|
||||||
|
function(input, scope: IScope) {
|
||||||
|
return transformThis2Context(input.value || 'null', scope);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
// 创建代码生成器
|
||||||
|
const commonNodeGenerator = createNodeGenerator({
|
||||||
|
handlers: customHandlers,
|
||||||
|
tagMapping: mapComponentNameToAliasOrKeepIt,
|
||||||
|
nodePlugins: [generateReactExprInJS, generateConditionReactCtrl, generateRaxLoopCtrl],
|
||||||
|
attrPlugins: [generateNodeAttrForRax],
|
||||||
|
});
|
||||||
|
|
||||||
|
// 生成 JSX 代码
|
||||||
|
const jsxContent = commonNodeGenerator(ir, rootScope);
|
||||||
|
|
||||||
|
next.chunks.push({
|
||||||
|
type: ChunkType.STRING,
|
||||||
|
fileType: cfg.fileType,
|
||||||
|
name: COMMON_CHUNK_NAME.ExternalDepsImport,
|
||||||
|
content: 'import { isMiniApp as __$$isMiniApp } from \'universal-env\';',
|
||||||
|
linkAfter: [],
|
||||||
|
});
|
||||||
|
|
||||||
|
next.chunks.push({
|
||||||
|
type: ChunkType.STRING,
|
||||||
|
fileType: cfg.fileType,
|
||||||
|
name: RAX_CHUNK_NAME.ClassRenderPre,
|
||||||
|
// TODO: setState, dataSourceMap, reloadDataSource, utils, i18n, i18nFormat, getLocale, setLocale 这些在 Rax 的编译模式下不能在视图中直接访问,需要转化成 this.xxx
|
||||||
|
content: `
|
||||||
|
const __$$context = this._context;
|
||||||
|
const { state, setState, dataSourceMap, reloadDataSource, utils, constants, i18n, i18nFormat, getLocale, setLocale } = __$$context;
|
||||||
|
`,
|
||||||
|
linkAfter: [RAX_CHUNK_NAME.ClassRenderBegin],
|
||||||
|
});
|
||||||
|
|
||||||
|
next.chunks.push({
|
||||||
|
type: ChunkType.STRING,
|
||||||
|
fileType: cfg.fileType,
|
||||||
|
name: RAX_CHUNK_NAME.ClassRenderJSX,
|
||||||
|
content: `return ${jsxContent};`,
|
||||||
|
linkAfter: [RAX_CHUNK_NAME.ClassRenderBegin, RAX_CHUNK_NAME.ClassRenderPre],
|
||||||
|
});
|
||||||
|
|
||||||
|
next.chunks.push({
|
||||||
|
type: ChunkType.STRING,
|
||||||
|
fileType: cfg.fileType,
|
||||||
|
name: COMMON_CHUNK_NAME.CustomContent,
|
||||||
|
content: `
|
||||||
|
|
||||||
|
function __$$eval(expr) {
|
||||||
|
try {
|
||||||
|
return expr();
|
||||||
|
} catch (err) {
|
||||||
|
console.warn('Failed to evaluate: ', expr, err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function __$$evalArray(expr) {
|
||||||
|
const res = __$$eval(expr);
|
||||||
|
return Array.isArray(res) ? res : [];
|
||||||
|
}
|
||||||
|
|
||||||
|
`,
|
||||||
|
linkAfter: [COMMON_CHUNK_NAME.FileExport],
|
||||||
|
});
|
||||||
|
|
||||||
|
return next;
|
||||||
|
};
|
||||||
|
|
||||||
|
return plugin;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default pluginFactory;
|
||||||
|
|
||||||
|
function transformJsExpr(expr: string, scope: IScope) {
|
||||||
|
if (!expr) {
|
||||||
|
return 'undefined';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isLiteralAtomicExpr(expr)) {
|
||||||
|
return expr;
|
||||||
|
}
|
||||||
|
|
||||||
|
const exprAst = parseExpression(expr);
|
||||||
|
|
||||||
|
// 对于下面这些比较安全的字面值,可以直接返回对应的表达式,而非包一层
|
||||||
|
if (isSimpleStraightLiteral(exprAst)) {
|
||||||
|
return expr;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (exprAst.type) {
|
||||||
|
// 对于直接写个函数的,则不用再包下,因为这样不会抛出异常的
|
||||||
|
case 'ArrowFunctionExpression':
|
||||||
|
case 'FunctionExpression':
|
||||||
|
return transformThis2Context(exprAst, scope);
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 其他的都需要包一层
|
||||||
|
return `__$$eval(() => (${transformThis2Context(exprAst, scope)}))`;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 判断是非是一些简单直接的字面值 */
|
||||||
|
function isSimpleStraightLiteral(expr: Expression): boolean {
|
||||||
|
switch (expr.type) {
|
||||||
|
case 'BigIntLiteral':
|
||||||
|
case 'BooleanLiteral':
|
||||||
|
case 'DecimalLiteral':
|
||||||
|
case 'NullLiteral':
|
||||||
|
case 'NumericLiteral':
|
||||||
|
case 'RegExpLiteral':
|
||||||
|
case 'StringLiteral':
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function isImportAliasDefineChunk(
|
||||||
|
chunk: ICodeChunk,
|
||||||
|
): chunk is ICodeChunk & {
|
||||||
|
ext: {
|
||||||
|
aliasName: string;
|
||||||
|
originalName: string;
|
||||||
|
dependency: NpmInfo;
|
||||||
|
};
|
||||||
|
} {
|
||||||
|
return (
|
||||||
|
chunk.name === COMMON_CHUNK_NAME.ImportAliasDefine &&
|
||||||
|
!!chunk.ext &&
|
||||||
|
typeof chunk.ext.aliasName === 'string' &&
|
||||||
|
typeof chunk.ext.originalName === 'string' &&
|
||||||
|
!!(chunk.ext.dependency as NpmInfo | null)?.componentName
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断是否是原子类型的表达式
|
||||||
|
*/
|
||||||
|
function isLiteralAtomicExpr(expr: string): boolean {
|
||||||
|
return expr === 'null' || expr === 'undefined' || expr === 'true' || expr === 'false' || /^-?\d+(\.\d+)?$/.test(expr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将所有的 this.xxx 替换为 __$$context.xxx
|
||||||
|
* @param expr
|
||||||
|
*/
|
||||||
|
function transformThis2Context(expr: string | Expression, scope: IScope): string {
|
||||||
|
// 下面这种字符串替换的方式虽然简单直接,但是对于复杂场景会误匹配,故后期改成了解析 AST 然后修改 AST 最后再重新生成代码的方式
|
||||||
|
// return expr
|
||||||
|
// .replace(/\bthis\.item\./g, () => 'item.')
|
||||||
|
// .replace(/\bthis\.index\./g, () => 'index.')
|
||||||
|
// .replace(/\bthis\./g, () => '__$$context.');
|
||||||
|
|
||||||
|
return parseExpressionConvertThis2Context(expr, '__$$context', scope.bindings?.getAllBindings() || []);
|
||||||
|
}
|
||||||
|
|
||||||
|
function generateRaxLoopCtrl(
|
||||||
|
nodeItem: NodeSchema,
|
||||||
|
scope: IScope,
|
||||||
|
config?: NodeGeneratorConfig,
|
||||||
|
next?: NodePlugin,
|
||||||
|
): CodePiece[] {
|
||||||
|
if (nodeItem.loop) {
|
||||||
|
const loopItemName = nodeItem.loopArgs?.[0] || 'item';
|
||||||
|
const loopIndexName = nodeItem.loopArgs?.[1] || 'index';
|
||||||
|
const subScope = scope.createSubScope([loopItemName, loopIndexName]);
|
||||||
|
const pieces: CodePiece[] = next ? next(nodeItem, subScope, config) : [];
|
||||||
|
|
||||||
|
const loopDataExpr = `__$$evalArray(() => (${transformThis2Context(
|
||||||
|
generateCompositeType(nodeItem.loop, scope, { handlers: config?.handlers }),
|
||||||
|
scope,
|
||||||
|
)}))`;
|
||||||
|
|
||||||
|
pieces.unshift({
|
||||||
|
value: `${loopDataExpr}.map((${loopItemName}, ${loopIndexName}) => (`,
|
||||||
|
type: PIECE_TYPE.BEFORE,
|
||||||
|
});
|
||||||
|
|
||||||
|
pieces.push({
|
||||||
|
value: '))',
|
||||||
|
type: PIECE_TYPE.AFTER,
|
||||||
|
});
|
||||||
|
|
||||||
|
return pieces;
|
||||||
|
}
|
||||||
|
|
||||||
|
return next ? next(nodeItem, scope, config) : [];
|
||||||
|
}
|
||||||
|
|
||||||
|
function generateNodeAttrForRax(
|
||||||
|
attrData: { attrName: string; attrValue: CompositeValue },
|
||||||
|
scope: IScope,
|
||||||
|
config?: NodeGeneratorConfig,
|
||||||
|
next?: AttrPlugin,
|
||||||
|
): CodePiece[] {
|
||||||
|
if (!/^on/.test(attrData.attrName)) {
|
||||||
|
return next ? next(attrData, scope, config) : [];
|
||||||
|
}
|
||||||
|
// else: onXxx 的都是事件处理函数需要特殊处理下
|
||||||
|
return generateEventHandlerAttrForRax(attrData.attrName, attrData.attrValue, scope, config);
|
||||||
|
}
|
||||||
|
|
||||||
|
function generateEventHandlerAttrForRax(
|
||||||
|
attrName: string,
|
||||||
|
attrValue: CompositeValue,
|
||||||
|
scope: IScope,
|
||||||
|
config?: NodeGeneratorConfig,
|
||||||
|
): CodePiece[] {
|
||||||
|
// -- 事件处理函数中 JSExpression 转成 JSFunction 来处理,避免当 JSExpression 处理的时候多包一层 eval 而导致 Rax 转码成小程序的时候出问题
|
||||||
|
const valueExpr = generateCompositeType(
|
||||||
|
isJSExpression(attrValue) ? { type: 'JSFunction', value: attrValue.value } : attrValue,
|
||||||
|
scope,
|
||||||
|
{
|
||||||
|
handlers: config?.handlers,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
// 查询当前作用域下的变量
|
||||||
|
const currentScopeVariables = scope.bindings?.getAllBindings() || [];
|
||||||
|
if (currentScopeVariables.length <= 0) {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
type: PIECE_TYPE.ATTR,
|
||||||
|
name: attrName,
|
||||||
|
value: valueExpr,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
// 提取出所有的未定义的全局变量
|
||||||
|
const undeclaredVariablesInValueExpr = parseExpressionGetGlobalVariables(valueExpr);
|
||||||
|
const referencedLocalVariables = _.intersection(undeclaredVariablesInValueExpr, currentScopeVariables);
|
||||||
|
if (referencedLocalVariables.length <= 0) {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
type: PIECE_TYPE.ATTR,
|
||||||
|
name: attrName,
|
||||||
|
value: valueExpr,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
const wrappedAttrValueExpr = [
|
||||||
|
'(...__$$args) => {',
|
||||||
|
' if (__$$isMiniApp) {',
|
||||||
|
' const __$$event = __$$args[0];',
|
||||||
|
...referencedLocalVariables.map((localVar) => `const ${localVar} = __$$event.target.dataset.${localVar};`),
|
||||||
|
` return (${valueExpr}).apply(this, __$$args);`,
|
||||||
|
' } else {',
|
||||||
|
` return (${valueExpr}).apply(this, __$$args);`,
|
||||||
|
' }',
|
||||||
|
'}',
|
||||||
|
].join('\n');
|
||||||
|
|
||||||
|
return [
|
||||||
|
...referencedLocalVariables.map((localVar) => ({
|
||||||
|
type: PIECE_TYPE.ATTR,
|
||||||
|
name: `data-${changeCase.snake(localVar)}`,
|
||||||
|
value: localVar,
|
||||||
|
})),
|
||||||
|
{
|
||||||
|
type: PIECE_TYPE.ATTR,
|
||||||
|
name: attrName,
|
||||||
|
value: wrappedAttrValueExpr,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
@ -1,3 +1,4 @@
|
|||||||
|
import changeCase from 'change-case';
|
||||||
import { COMMON_CHUNK_NAME, CLASS_DEFINE_CHUNK_NAME } from '../../../const/generator';
|
import { COMMON_CHUNK_NAME, CLASS_DEFINE_CHUNK_NAME } from '../../../const/generator';
|
||||||
import { REACT_CHUNK_NAME } from './const';
|
import { REACT_CHUNK_NAME } from './const';
|
||||||
|
|
||||||
@ -18,14 +19,18 @@ const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
|
|||||||
|
|
||||||
const ir = next.ir as IContainerInfo;
|
const ir = next.ir as IContainerInfo;
|
||||||
|
|
||||||
|
// 将模块名转换成 PascalCase 的格式,并添加特定后缀,防止命名冲突
|
||||||
|
const componentClassName = `${changeCase.pascalCase(ir.moduleName)}$$Page`;
|
||||||
|
|
||||||
next.chunks.push({
|
next.chunks.push({
|
||||||
type: ChunkType.STRING,
|
type: ChunkType.STRING,
|
||||||
fileType: FileType.JSX,
|
fileType: FileType.JSX,
|
||||||
name: CLASS_DEFINE_CHUNK_NAME.Start,
|
name: CLASS_DEFINE_CHUNK_NAME.Start,
|
||||||
content: `class ${ir.moduleName} extends React.Component {`,
|
content: `class ${componentClassName} extends React.Component {`,
|
||||||
linkAfter: [
|
linkAfter: [
|
||||||
COMMON_CHUNK_NAME.ExternalDepsImport,
|
COMMON_CHUNK_NAME.ExternalDepsImport,
|
||||||
COMMON_CHUNK_NAME.InternalDepsImport,
|
COMMON_CHUNK_NAME.InternalDepsImport,
|
||||||
|
COMMON_CHUNK_NAME.ImportAliasDefine,
|
||||||
COMMON_CHUNK_NAME.FileVarDefine,
|
COMMON_CHUNK_NAME.FileVarDefine,
|
||||||
COMMON_CHUNK_NAME.FileUtilDefine,
|
COMMON_CHUNK_NAME.FileUtilDefine,
|
||||||
],
|
],
|
||||||
@ -36,7 +41,10 @@ const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
|
|||||||
fileType: FileType.JSX,
|
fileType: FileType.JSX,
|
||||||
name: CLASS_DEFINE_CHUNK_NAME.End,
|
name: CLASS_DEFINE_CHUNK_NAME.End,
|
||||||
content: '}',
|
content: '}',
|
||||||
linkAfter: [CLASS_DEFINE_CHUNK_NAME.Start, REACT_CHUNK_NAME.ClassRenderEnd],
|
linkAfter: [
|
||||||
|
CLASS_DEFINE_CHUNK_NAME.Start,
|
||||||
|
REACT_CHUNK_NAME.ClassRenderEnd,
|
||||||
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
next.chunks.push({
|
next.chunks.push({
|
||||||
@ -52,10 +60,7 @@ const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
|
|||||||
fileType: FileType.JSX,
|
fileType: FileType.JSX,
|
||||||
name: CLASS_DEFINE_CHUNK_NAME.ConstructorEnd,
|
name: CLASS_DEFINE_CHUNK_NAME.ConstructorEnd,
|
||||||
content: '}',
|
content: '}',
|
||||||
linkAfter: [
|
linkAfter: [CLASS_DEFINE_CHUNK_NAME.ConstructorStart, CLASS_DEFINE_CHUNK_NAME.ConstructorContent],
|
||||||
CLASS_DEFINE_CHUNK_NAME.ConstructorStart,
|
|
||||||
CLASS_DEFINE_CHUNK_NAME.ConstructorContent,
|
|
||||||
],
|
|
||||||
});
|
});
|
||||||
|
|
||||||
next.chunks.push({
|
next.chunks.push({
|
||||||
@ -75,21 +80,18 @@ const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
|
|||||||
fileType: FileType.JSX,
|
fileType: FileType.JSX,
|
||||||
name: REACT_CHUNK_NAME.ClassRenderEnd,
|
name: REACT_CHUNK_NAME.ClassRenderEnd,
|
||||||
content: '}',
|
content: '}',
|
||||||
linkAfter: [
|
linkAfter: [REACT_CHUNK_NAME.ClassRenderStart, REACT_CHUNK_NAME.ClassRenderPre, REACT_CHUNK_NAME.ClassRenderJSX],
|
||||||
REACT_CHUNK_NAME.ClassRenderStart,
|
|
||||||
REACT_CHUNK_NAME.ClassRenderPre,
|
|
||||||
REACT_CHUNK_NAME.ClassRenderJSX,
|
|
||||||
],
|
|
||||||
});
|
});
|
||||||
|
|
||||||
next.chunks.push({
|
next.chunks.push({
|
||||||
type: ChunkType.STRING,
|
type: ChunkType.STRING,
|
||||||
fileType: FileType.JSX,
|
fileType: FileType.JSX,
|
||||||
name: COMMON_CHUNK_NAME.FileExport,
|
name: COMMON_CHUNK_NAME.FileExport,
|
||||||
content: `export default ${ir.moduleName};`,
|
content: `export default ${componentClassName};`,
|
||||||
linkAfter: [
|
linkAfter: [
|
||||||
COMMON_CHUNK_NAME.ExternalDepsImport,
|
COMMON_CHUNK_NAME.ExternalDepsImport,
|
||||||
COMMON_CHUNK_NAME.InternalDepsImport,
|
COMMON_CHUNK_NAME.InternalDepsImport,
|
||||||
|
COMMON_CHUNK_NAME.ImportAliasDefine,
|
||||||
COMMON_CHUNK_NAME.FileVarDefine,
|
COMMON_CHUNK_NAME.FileVarDefine,
|
||||||
COMMON_CHUNK_NAME.FileUtilDefine,
|
COMMON_CHUNK_NAME.FileUtilDefine,
|
||||||
CLASS_DEFINE_CHUNK_NAME.End,
|
CLASS_DEFINE_CHUNK_NAME.End,
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
import { CLASS_DEFINE_CHUNK_NAME } from '../../../const/generator';
|
import { CLASS_DEFINE_CHUNK_NAME } from '../../../const/generator';
|
||||||
|
|
||||||
import { generateCompositeType } from '../../../utils/compositeType';
|
import { generateCompositeType } from '../../../utils/compositeType';
|
||||||
|
import Scope from '../../../utils/Scope';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
BuilderComponentPlugin,
|
BuilderComponentPlugin,
|
||||||
@ -28,10 +29,12 @@ const pluginFactory: BuilderComponentPluginFactory<PluginConfig> = (config?) =>
|
|||||||
|
|
||||||
const ir = next.ir as IContainerInfo;
|
const ir = next.ir as IContainerInfo;
|
||||||
|
|
||||||
|
const scope = Scope.createRootScope();
|
||||||
|
|
||||||
if (ir.state) {
|
if (ir.state) {
|
||||||
const { state } = ir;
|
const { state } = ir;
|
||||||
const fields = Object.keys(state).map<string>((stateName) => {
|
const fields = Object.keys(state).map<string>((stateName) => {
|
||||||
const value = generateCompositeType(state[stateName]);
|
const value = generateCompositeType(state[stateName], scope);
|
||||||
return `${stateName}: ${value},`;
|
return `${stateName}: ${value},`;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
import { CLASS_DEFINE_CHUNK_NAME, DEFAULT_LINK_AFTER } from '../../../const/generator';
|
import { CLASS_DEFINE_CHUNK_NAME, DEFAULT_LINK_AFTER } from '../../../const/generator';
|
||||||
|
|
||||||
import { generateCompositeType } from '../../../utils/compositeType';
|
import { generateCompositeType } from '../../../utils/compositeType';
|
||||||
|
import Scope from '../../../utils/Scope';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
BuilderComponentPlugin,
|
BuilderComponentPlugin,
|
||||||
@ -29,11 +30,12 @@ const pluginFactory: BuilderComponentPluginFactory<PluginConfig> = (config?) =>
|
|||||||
};
|
};
|
||||||
|
|
||||||
const ir = next.ir as IContainerInfo;
|
const ir = next.ir as IContainerInfo;
|
||||||
|
const scope = Scope.createRootScope();
|
||||||
|
|
||||||
if (ir.state) {
|
if (ir.state) {
|
||||||
const { state } = ir;
|
const { state } = ir;
|
||||||
const fields = Object.keys(state).map<string>((stateName) => {
|
const fields = Object.keys(state).map<string>((stateName) => {
|
||||||
const value = generateCompositeType(state[stateName]);
|
const value = generateCompositeType(state[stateName], scope);
|
||||||
return `${stateName}: ${value},`;
|
return `${stateName}: ${value},`;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -5,11 +5,13 @@ import {
|
|||||||
FileType,
|
FileType,
|
||||||
ICodeStruct,
|
ICodeStruct,
|
||||||
IContainerInfo,
|
IContainerInfo,
|
||||||
|
IScope,
|
||||||
} from '../../../types';
|
} from '../../../types';
|
||||||
|
|
||||||
import { REACT_CHUNK_NAME } from './const';
|
import { REACT_CHUNK_NAME } from './const';
|
||||||
|
|
||||||
import { createReactNodeGenerator } from '../../../utils/nodeToJSX';
|
import { createReactNodeGenerator } from '../../../utils/nodeToJSX';
|
||||||
|
import Scope from '../../../utils/Scope';
|
||||||
|
|
||||||
type PluginConfig = {
|
type PluginConfig = {
|
||||||
fileType?: string;
|
fileType?: string;
|
||||||
@ -23,7 +25,11 @@ const pluginFactory: BuilderComponentPluginFactory<PluginConfig> = (config?) =>
|
|||||||
...config,
|
...config,
|
||||||
};
|
};
|
||||||
|
|
||||||
const generator = createReactNodeGenerator({ nodeTypeMapping: cfg.nodeTypeMapping });
|
const { nodeTypeMapping } = cfg;
|
||||||
|
|
||||||
|
const generator = createReactNodeGenerator({
|
||||||
|
tagMapping: (v) => nodeTypeMapping[v] || v,
|
||||||
|
});
|
||||||
|
|
||||||
const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => {
|
const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => {
|
||||||
const next: ICodeStruct = {
|
const next: ICodeStruct = {
|
||||||
@ -31,17 +37,15 @@ const pluginFactory: BuilderComponentPluginFactory<PluginConfig> = (config?) =>
|
|||||||
};
|
};
|
||||||
|
|
||||||
const ir = next.ir as IContainerInfo;
|
const ir = next.ir as IContainerInfo;
|
||||||
const jsxContent = generator(ir);
|
const scope: IScope = Scope.createRootScope();
|
||||||
|
const jsxContent = generator(ir, scope);
|
||||||
|
|
||||||
next.chunks.push({
|
next.chunks.push({
|
||||||
type: ChunkType.STRING,
|
type: ChunkType.STRING,
|
||||||
fileType: cfg.fileType,
|
fileType: cfg.fileType,
|
||||||
name: REACT_CHUNK_NAME.ClassRenderJSX,
|
name: REACT_CHUNK_NAME.ClassRenderJSX,
|
||||||
content: `return ${jsxContent};`,
|
content: `return ${jsxContent};`,
|
||||||
linkAfter: [
|
linkAfter: [REACT_CHUNK_NAME.ClassRenderStart, REACT_CHUNK_NAME.ClassRenderPre],
|
||||||
REACT_CHUNK_NAME.ClassRenderStart,
|
|
||||||
REACT_CHUNK_NAME.ClassRenderPre,
|
|
||||||
],
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return next;
|
return next;
|
||||||
|
|||||||
@ -1,3 +0,0 @@
|
|||||||
export const RECORE_CHUNK_NAME = {
|
|
||||||
|
|
||||||
};
|
|
||||||
@ -1,4 +1,7 @@
|
|||||||
|
import { JSExpression, CompositeValue } from '@ali/lowcode-types';
|
||||||
|
|
||||||
import { CLASS_DEFINE_CHUNK_NAME, DEFAULT_LINK_AFTER } from '../../../const/generator';
|
import { CLASS_DEFINE_CHUNK_NAME, DEFAULT_LINK_AFTER } from '../../../const/generator';
|
||||||
|
import Scope from '../../../utils/Scope';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
BuilderComponentPlugin,
|
BuilderComponentPlugin,
|
||||||
@ -7,15 +10,13 @@ import {
|
|||||||
FileType,
|
FileType,
|
||||||
ICodeStruct,
|
ICodeStruct,
|
||||||
IContainerInfo,
|
IContainerInfo,
|
||||||
IJSExpression,
|
|
||||||
CompositeValue,
|
|
||||||
} from '../../../types';
|
} from '../../../types';
|
||||||
|
|
||||||
import { generateCompositeType } from '../../../utils/compositeType';
|
import { generateCompositeType } from '../../../utils/compositeType';
|
||||||
import { generateExpression } from '../../../utils/jsExpression';
|
import { generateExpression } from '../../../utils/jsExpression';
|
||||||
|
|
||||||
function packJsExpression(exp: unknown): string {
|
function packJsExpression(exp: unknown): string {
|
||||||
const expression = exp as IJSExpression;
|
const expression = exp as JSExpression;
|
||||||
const funcStr = generateExpression(expression);
|
const funcStr = generateExpression(expression);
|
||||||
return `function() { return (${funcStr}); }`;
|
return `function() { return (${funcStr}); }`;
|
||||||
}
|
}
|
||||||
@ -27,6 +28,8 @@ const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const ir = next.ir as IContainerInfo;
|
const ir = next.ir as IContainerInfo;
|
||||||
|
const scope = Scope.createRootScope();
|
||||||
|
|
||||||
if (ir.dataSource) {
|
if (ir.dataSource) {
|
||||||
const { dataSource } = ir;
|
const { dataSource } = ir;
|
||||||
const { list, ...rest } = dataSource;
|
const { list, ...rest } = dataSource;
|
||||||
@ -35,13 +38,13 @@ const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
|
|||||||
|
|
||||||
const extConfigs = Object.keys(rest).map((extConfigName) => {
|
const extConfigs = Object.keys(rest).map((extConfigName) => {
|
||||||
const value = (rest as Record<string, CompositeValue>)[extConfigName];
|
const value = (rest as Record<string, CompositeValue>)[extConfigName];
|
||||||
const valueStr = generateCompositeType(value);
|
const valueStr = generateCompositeType(value, scope);
|
||||||
return `${extConfigName}: ${valueStr}`;
|
return `${extConfigName}: ${valueStr}`;
|
||||||
});
|
});
|
||||||
|
|
||||||
attrs = [...attrs, ...extConfigs];
|
attrs = [...attrs, ...extConfigs];
|
||||||
|
|
||||||
const listProp = generateCompositeType((list as unknown) as CompositeValue, {
|
const listProp = generateCompositeType((list as unknown) as CompositeValue, scope, {
|
||||||
handlers: {
|
handlers: {
|
||||||
expression: packJsExpression,
|
expression: packJsExpression,
|
||||||
},
|
},
|
||||||
|
|||||||
@ -22,7 +22,7 @@ const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
|
|||||||
type: ChunkType.STRING,
|
type: ChunkType.STRING,
|
||||||
fileType: FileType.TS,
|
fileType: FileType.TS,
|
||||||
name: CLASS_DEFINE_CHUNK_NAME.StaticVar,
|
name: CLASS_DEFINE_CHUNK_NAME.StaticVar,
|
||||||
content: `static cssText = '${ir.css.replace(/'/g, '\\\'')}';`,
|
content: `static cssText = '${ir.css.replace(/'/g, "\\'")}';`,
|
||||||
linkAfter: [...DEFAULT_LINK_AFTER[CLASS_DEFINE_CHUNK_NAME.StaticVar]],
|
linkAfter: [...DEFAULT_LINK_AFTER[CLASS_DEFINE_CHUNK_NAME.StaticVar]],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,21 +1,22 @@
|
|||||||
|
import { NodeSchema } from '@ali/lowcode-types';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
BuilderComponentPlugin,
|
BuilderComponentPlugin,
|
||||||
BuilderComponentPluginFactory,
|
BuilderComponentPluginFactory,
|
||||||
ChunkType,
|
ChunkType,
|
||||||
ICodeStruct,
|
ICodeStruct,
|
||||||
IContainerInfo,
|
IContainerInfo,
|
||||||
IComponentNodeItem,
|
IScope,
|
||||||
INodeGeneratorContext,
|
|
||||||
CodePiece,
|
CodePiece,
|
||||||
PIECE_TYPE,
|
PIECE_TYPE,
|
||||||
} from '../../../types';
|
} from '../../../types';
|
||||||
import { COMMON_CHUNK_NAME } from '../../../const/generator';
|
import { COMMON_CHUNK_NAME } from '../../../const/generator';
|
||||||
|
|
||||||
import { createNodeGenerator, generateString } from '../../../utils/nodeToJSX';
|
import { createNodeGenerator } from '../../../utils/nodeToJSX';
|
||||||
import { generateExpression } from '../../../utils/jsExpression';
|
|
||||||
import { generateCompositeType } from '../../../utils/compositeType';
|
import { generateCompositeType } from '../../../utils/compositeType';
|
||||||
|
import Scope from '../../../utils/Scope';
|
||||||
|
|
||||||
const generateGlobalProps = (ctx: INodeGeneratorContext, nodeItem: IComponentNodeItem): CodePiece[] => {
|
const generateGlobalProps = (nodeItem: NodeSchema): CodePiece[] => {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
value: `{...globalProps.${nodeItem.componentName}}`,
|
value: `{...globalProps.${nodeItem.componentName}}`,
|
||||||
@ -24,11 +25,11 @@ const generateGlobalProps = (ctx: INodeGeneratorContext, nodeItem: IComponentNod
|
|||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
const generateCtrlLine = (ctx: INodeGeneratorContext, nodeItem: IComponentNodeItem): CodePiece[] => {
|
const generateCtrlLine = (nodeItem: NodeSchema, scope: IScope): CodePiece[] => {
|
||||||
const pieces: CodePiece[] = [];
|
const pieces: CodePiece[] = [];
|
||||||
|
|
||||||
if (nodeItem.loop && nodeItem.loopArgs) {
|
if (nodeItem.loop && nodeItem.loopArgs) {
|
||||||
const loopDataExp = generateCompositeType(nodeItem.loop);
|
const loopDataExp = generateCompositeType(nodeItem.loop, scope);
|
||||||
pieces.push({
|
pieces.push({
|
||||||
type: PIECE_TYPE.ATTR,
|
type: PIECE_TYPE.ATTR,
|
||||||
value: `x-for={${loopDataExp}}`,
|
value: `x-for={${loopDataExp}}`,
|
||||||
@ -41,7 +42,7 @@ const generateCtrlLine = (ctx: INodeGeneratorContext, nodeItem: IComponentNodeIt
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (nodeItem.condition) {
|
if (nodeItem.condition) {
|
||||||
const conditionExp = generateCompositeType(nodeItem.condition);
|
const conditionExp = generateCompositeType(nodeItem.condition, scope);
|
||||||
pieces.push({
|
pieces.push({
|
||||||
type: PIECE_TYPE.ATTR,
|
type: PIECE_TYPE.ATTR,
|
||||||
value: `x-if={${conditionExp}}`,
|
value: `x-if={${conditionExp}}`,
|
||||||
@ -52,13 +53,9 @@ const generateCtrlLine = (ctx: INodeGeneratorContext, nodeItem: IComponentNodeIt
|
|||||||
};
|
};
|
||||||
|
|
||||||
const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
|
const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
|
||||||
const generator = createNodeGenerator(
|
const generator = createNodeGenerator({
|
||||||
{
|
nodePlugins: [generateGlobalProps, generateCtrlLine],
|
||||||
string: generateString,
|
});
|
||||||
expression: (input) => [generateExpression(input)],
|
|
||||||
},
|
|
||||||
[generateGlobalProps, generateCtrlLine],
|
|
||||||
);
|
|
||||||
|
|
||||||
const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => {
|
const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => {
|
||||||
const next: ICodeStruct = {
|
const next: ICodeStruct = {
|
||||||
@ -66,8 +63,9 @@ const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const ir = next.ir as IContainerInfo;
|
const ir = next.ir as IContainerInfo;
|
||||||
|
const scope = Scope.createRootScope();
|
||||||
|
|
||||||
const vxContent = generator(ir);
|
const vxContent = generator(ir, scope);
|
||||||
|
|
||||||
next.chunks.push({
|
next.chunks.push({
|
||||||
type: ChunkType.STRING,
|
type: ChunkType.STRING,
|
||||||
|
|||||||
@ -1,11 +1,6 @@
|
|||||||
import { COMMON_CHUNK_NAME } from '../../../const/generator';
|
import { COMMON_CHUNK_NAME } from '../../../const/generator';
|
||||||
|
|
||||||
import {
|
import { BuilderComponentPlugin, BuilderComponentPluginFactory, ChunkType, ICodeStruct } from '../../../types';
|
||||||
BuilderComponentPlugin,
|
|
||||||
BuilderComponentPluginFactory,
|
|
||||||
ChunkType,
|
|
||||||
ICodeStruct,
|
|
||||||
} from '../../../types';
|
|
||||||
|
|
||||||
const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
|
const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
|
||||||
const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => {
|
const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => {
|
||||||
|
|||||||
@ -8,6 +8,7 @@ import {
|
|||||||
ICodeStruct,
|
ICodeStruct,
|
||||||
IProjectInfo,
|
IProjectInfo,
|
||||||
} from '../../types';
|
} from '../../types';
|
||||||
|
import Scope from '../../utils/Scope';
|
||||||
|
|
||||||
const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
|
const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
|
||||||
const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => {
|
const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => {
|
||||||
@ -16,35 +17,39 @@ const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const ir = next.ir as IProjectInfo;
|
const ir = next.ir as IProjectInfo;
|
||||||
if (ir.constants) {
|
const scope = Scope.createRootScope();
|
||||||
const constantStr = generateCompositeType(ir.constants);
|
const constantStr = generateCompositeType(ir.constants || {}, scope);
|
||||||
|
|
||||||
next.chunks.push({
|
next.chunks.push({
|
||||||
type: ChunkType.STRING,
|
type: ChunkType.STRING,
|
||||||
fileType: FileType.JS,
|
fileType: FileType.JS,
|
||||||
name: COMMON_CHUNK_NAME.FileVarDefine,
|
name: COMMON_CHUNK_NAME.FileVarDefine,
|
||||||
content: `
|
content: `
|
||||||
const constantConfig = ${constantStr};
|
const __$$constants = (${constantStr});
|
||||||
`,
|
`,
|
||||||
linkAfter: [COMMON_CHUNK_NAME.ExternalDepsImport, COMMON_CHUNK_NAME.InternalDepsImport],
|
linkAfter: [
|
||||||
});
|
COMMON_CHUNK_NAME.ExternalDepsImport,
|
||||||
|
COMMON_CHUNK_NAME.InternalDepsImport,
|
||||||
|
COMMON_CHUNK_NAME.ImportAliasDefine,
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
next.chunks.push({
|
next.chunks.push({
|
||||||
type: ChunkType.STRING,
|
type: ChunkType.STRING,
|
||||||
fileType: FileType.JS,
|
fileType: FileType.JS,
|
||||||
name: COMMON_CHUNK_NAME.FileExport,
|
name: COMMON_CHUNK_NAME.FileExport,
|
||||||
content: `
|
content: `
|
||||||
export default constantConfig;
|
export default __$$constants;
|
||||||
`,
|
`,
|
||||||
linkAfter: [
|
linkAfter: [
|
||||||
COMMON_CHUNK_NAME.ExternalDepsImport,
|
COMMON_CHUNK_NAME.ExternalDepsImport,
|
||||||
COMMON_CHUNK_NAME.InternalDepsImport,
|
COMMON_CHUNK_NAME.InternalDepsImport,
|
||||||
COMMON_CHUNK_NAME.FileVarDefine,
|
COMMON_CHUNK_NAME.ImportAliasDefine,
|
||||||
COMMON_CHUNK_NAME.FileUtilDefine,
|
COMMON_CHUNK_NAME.FileVarDefine,
|
||||||
COMMON_CHUNK_NAME.FileMainContent,
|
COMMON_CHUNK_NAME.FileUtilDefine,
|
||||||
],
|
COMMON_CHUNK_NAME.FileMainContent,
|
||||||
});
|
],
|
||||||
}
|
});
|
||||||
|
|
||||||
return next;
|
return next;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -6,7 +6,6 @@ import {
|
|||||||
ChunkType,
|
ChunkType,
|
||||||
FileType,
|
FileType,
|
||||||
ICodeStruct,
|
ICodeStruct,
|
||||||
IProjectInfo,
|
|
||||||
} from '../../../../../types';
|
} from '../../../../../types';
|
||||||
|
|
||||||
const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
|
const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
|
||||||
@ -15,8 +14,6 @@ const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
|
|||||||
...pre,
|
...pre,
|
||||||
};
|
};
|
||||||
|
|
||||||
const ir = next.ir as IProjectInfo;
|
|
||||||
|
|
||||||
next.chunks.push({
|
next.chunks.push({
|
||||||
type: ChunkType.STRING,
|
type: ChunkType.STRING,
|
||||||
fileType: FileType.JS,
|
fileType: FileType.JS,
|
||||||
@ -34,10 +31,10 @@ const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
|
|||||||
content: `
|
content: `
|
||||||
const appConfig = {
|
const appConfig = {
|
||||||
app: {
|
app: {
|
||||||
rootId: '${ir.config.targetRootID}',
|
rootId: 'app',
|
||||||
},
|
},
|
||||||
router: {
|
router: {
|
||||||
type: '${ir.config.historyMode}',
|
type: 'hash',
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
createApp(appConfig);
|
createApp(appConfig);
|
||||||
@ -45,6 +42,7 @@ const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
|
|||||||
linkAfter: [
|
linkAfter: [
|
||||||
COMMON_CHUNK_NAME.ExternalDepsImport,
|
COMMON_CHUNK_NAME.ExternalDepsImport,
|
||||||
COMMON_CHUNK_NAME.InternalDepsImport,
|
COMMON_CHUNK_NAME.InternalDepsImport,
|
||||||
|
COMMON_CHUNK_NAME.ImportAliasDefine,
|
||||||
COMMON_CHUNK_NAME.FileVarDefine,
|
COMMON_CHUNK_NAME.FileVarDefine,
|
||||||
COMMON_CHUNK_NAME.FileUtilDefine,
|
COMMON_CHUNK_NAME.FileUtilDefine,
|
||||||
],
|
],
|
||||||
|
|||||||
@ -28,10 +28,10 @@ const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
|
|||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<meta http-equiv="x-ua-compatible" content="ie=edge,chrome=1" />
|
<meta http-equiv="x-ua-compatible" content="ie=edge,chrome=1" />
|
||||||
<meta name="viewport" content="width=device-width" />
|
<meta name="viewport" content="width=device-width" />
|
||||||
<title>${ir.meta.name}</title>
|
<title>${ir?.meta?.name || 'Ice App'}</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="${ir.config.targetRootID}"></div>
|
<div id="app"></div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
`,
|
`,
|
||||||
|
|||||||
@ -1,3 +1,5 @@
|
|||||||
|
import { PackageJSON } from '@ali/lowcode-types';
|
||||||
|
|
||||||
import { COMMON_CHUNK_NAME } from '../../../../../const/generator';
|
import { COMMON_CHUNK_NAME } from '../../../../../const/generator';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@ -6,11 +8,10 @@ import {
|
|||||||
ChunkType,
|
ChunkType,
|
||||||
FileType,
|
FileType,
|
||||||
ICodeStruct,
|
ICodeStruct,
|
||||||
IPackageJSON,
|
|
||||||
IProjectInfo,
|
IProjectInfo,
|
||||||
} from '../../../../../types';
|
} from '../../../../../types';
|
||||||
|
|
||||||
interface IIceJsPackageJSON extends IPackageJSON {
|
interface IIceJsPackageJSON extends PackageJSON {
|
||||||
ideMode: {
|
ideMode: {
|
||||||
name: string;
|
name: string;
|
||||||
};
|
};
|
||||||
@ -73,6 +74,7 @@ const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
|
|||||||
originTemplate: '@alifd/scaffold-lite-js',
|
originTemplate: '@alifd/scaffold-lite-js',
|
||||||
};
|
};
|
||||||
|
|
||||||
|
console.log(ir.packages);
|
||||||
ir.packages.forEach((packageInfo) => {
|
ir.packages.forEach((packageInfo) => {
|
||||||
packageJson.dependencies[packageInfo.package] = packageInfo.version;
|
packageJson.dependencies[packageInfo.package] = packageInfo.version;
|
||||||
});
|
});
|
||||||
|
|||||||
@ -39,7 +39,7 @@ const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
|
|||||||
children: [
|
children: [
|
||||||
${ir.routes
|
${ir.routes
|
||||||
.map(
|
.map(
|
||||||
route => `
|
(route) => `
|
||||||
{
|
{
|
||||||
path: '${route.path}',
|
path: '${route.path}',
|
||||||
component: ${route.componentName},
|
component: ${route.componentName},
|
||||||
@ -54,6 +54,7 @@ const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
|
|||||||
linkAfter: [
|
linkAfter: [
|
||||||
COMMON_CHUNK_NAME.ExternalDepsImport,
|
COMMON_CHUNK_NAME.ExternalDepsImport,
|
||||||
COMMON_CHUNK_NAME.InternalDepsImport,
|
COMMON_CHUNK_NAME.InternalDepsImport,
|
||||||
|
COMMON_CHUNK_NAME.ImportAliasDefine,
|
||||||
COMMON_CHUNK_NAME.FileUtilDefine,
|
COMMON_CHUNK_NAME.FileUtilDefine,
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
@ -69,6 +70,7 @@ const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
|
|||||||
COMMON_CHUNK_NAME.ExternalDepsImport,
|
COMMON_CHUNK_NAME.ExternalDepsImport,
|
||||||
COMMON_CHUNK_NAME.InternalDepsImport,
|
COMMON_CHUNK_NAME.InternalDepsImport,
|
||||||
COMMON_CHUNK_NAME.FileUtilDefine,
|
COMMON_CHUNK_NAME.FileUtilDefine,
|
||||||
|
COMMON_CHUNK_NAME.ImportAliasDefine,
|
||||||
COMMON_CHUNK_NAME.FileVarDefine,
|
COMMON_CHUNK_NAME.FileVarDefine,
|
||||||
COMMON_CHUNK_NAME.FileMainContent,
|
COMMON_CHUNK_NAME.FileMainContent,
|
||||||
],
|
],
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
import ResultFile from '../../../../../../model/ResultFile';
|
import { ResultFile } from '@ali/lowcode-types';
|
||||||
import { IResultFile } from '../../../../../../types';
|
import { createResultFile } from '../../../../../../utils/resultHelper';
|
||||||
|
|
||||||
export default function getFile(): [string[], IResultFile] {
|
export default function getFile(): [string[], ResultFile] {
|
||||||
const file = new ResultFile(
|
const file = createResultFile(
|
||||||
'README',
|
'README',
|
||||||
'md',
|
'md',
|
||||||
`
|
`
|
||||||
|
|||||||
@ -1,17 +1,17 @@
|
|||||||
import ResultFile from '../../../../../../model/ResultFile';
|
import { ResultFile } from '@ali/lowcode-types';
|
||||||
import { IResultFile } from '../../../../../../types';
|
|
||||||
|
|
||||||
export default function getFile(): [string[], IResultFile] {
|
export default function getFile(): [string[], ResultFile] {
|
||||||
const file = new ResultFile(
|
return [
|
||||||
'abc',
|
[],
|
||||||
'json',
|
{
|
||||||
`
|
name: 'abc',
|
||||||
|
ext: 'json',
|
||||||
|
content: `
|
||||||
{
|
{
|
||||||
"type": "ice-app",
|
"type": "ice-app",
|
||||||
"builder": "@ali/builder-ice-app"
|
"builder": "@ali/builder-ice-app"
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
);
|
},
|
||||||
|
];
|
||||||
return [[], file];
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,11 +1,12 @@
|
|||||||
import ResultFile from '../../../../../../model/ResultFile';
|
import { ResultFile } from '@ali/lowcode-types';
|
||||||
import { IResultFile } from '../../../../../../types';
|
|
||||||
|
|
||||||
export default function getFile(): [string[], IResultFile] {
|
export default function getFile(): [string[], ResultFile] {
|
||||||
const file = new ResultFile(
|
return [
|
||||||
'build',
|
[],
|
||||||
'json',
|
{
|
||||||
`
|
name: 'build',
|
||||||
|
ext: 'json',
|
||||||
|
content: `
|
||||||
{
|
{
|
||||||
"entry": "src/app.js",
|
"entry": "src/app.js",
|
||||||
"plugins": [
|
"plugins": [
|
||||||
@ -26,8 +27,7 @@ export default function getFile(): [string[], IResultFile] {
|
|||||||
"@ali/build-plugin-ice-def"
|
"@ali/build-plugin-ice-def"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
);
|
},
|
||||||
|
];
|
||||||
return [[], file];
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
import ResultFile from '../../../../../../model/ResultFile';
|
import { ResultFile } from '@ali/lowcode-types';
|
||||||
import { IResultFile } from '../../../../../../types';
|
import { createResultFile } from '../../../../../../utils/resultHelper';
|
||||||
|
|
||||||
export default function getFile(): [string[], IResultFile] {
|
export default function getFile(): [string[], ResultFile] {
|
||||||
const file = new ResultFile(
|
const file = createResultFile(
|
||||||
'.editorconfig',
|
'.editorconfig',
|
||||||
'',
|
'',
|
||||||
`
|
`
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
import ResultFile from '../../../../../../model/ResultFile';
|
import { ResultFile } from '@ali/lowcode-types';
|
||||||
import { IResultFile } from '../../../../../../types';
|
import { createResultFile } from '../../../../../../utils/resultHelper';
|
||||||
|
|
||||||
export default function getFile(): [string[], IResultFile] {
|
export default function getFile(): [string[], ResultFile] {
|
||||||
const file = new ResultFile(
|
const file = createResultFile(
|
||||||
'.eslintignore',
|
'.eslintignore',
|
||||||
'',
|
'',
|
||||||
`
|
`
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
import ResultFile from '../../../../../../model/ResultFile';
|
import { ResultFile } from '@ali/lowcode-types';
|
||||||
import { IResultFile } from '../../../../../../types';
|
import { createResultFile } from '../../../../../../utils/resultHelper';
|
||||||
|
|
||||||
export default function getFile(): [string[], IResultFile] {
|
export default function getFile(): [string[], ResultFile] {
|
||||||
const file = new ResultFile(
|
const file = createResultFile(
|
||||||
'.eslintrc',
|
'.eslintrc',
|
||||||
'js',
|
'js',
|
||||||
`
|
`
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
import ResultFile from '../../../../../../model/ResultFile';
|
import { ResultFile } from '@ali/lowcode-types';
|
||||||
import { IResultFile } from '../../../../../../types';
|
import { createResultFile } from '../../../../../../utils/resultHelper';
|
||||||
|
|
||||||
export default function getFile(): [string[], IResultFile] {
|
export default function getFile(): [string[], ResultFile] {
|
||||||
const file = new ResultFile(
|
const file = createResultFile(
|
||||||
'.gitignore',
|
'.gitignore',
|
||||||
'',
|
'',
|
||||||
`
|
`
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
import ResultFile from '../../../../../../model/ResultFile';
|
import { ResultFile } from '@ali/lowcode-types';
|
||||||
import { IResultFile } from '../../../../../../types';
|
import { createResultFile } from '../../../../../../utils/resultHelper';
|
||||||
|
|
||||||
export default function getFile(): [string[], IResultFile] {
|
export default function getFile(): [string[], ResultFile] {
|
||||||
const file = new ResultFile(
|
const file = createResultFile(
|
||||||
'jsconfig',
|
'jsconfig',
|
||||||
'json',
|
'json',
|
||||||
`
|
`
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
import ResultFile from '../../../../../../model/ResultFile';
|
import { ResultFile } from '@ali/lowcode-types';
|
||||||
import { IResultFile } from '../../../../../../types';
|
import { createResultFile } from '../../../../../../utils/resultHelper';
|
||||||
|
|
||||||
export default function getFile(): [string[], IResultFile] {
|
export default function getFile(): [string[], ResultFile] {
|
||||||
const file = new ResultFile(
|
const file = createResultFile(
|
||||||
'.prettierignore',
|
'.prettierignore',
|
||||||
'',
|
'',
|
||||||
`
|
`
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
import ResultFile from '../../../../../../model/ResultFile';
|
import { ResultFile } from '@ali/lowcode-types';
|
||||||
import { IResultFile } from '../../../../../../types';
|
import { createResultFile } from '../../../../../../utils/resultHelper';
|
||||||
|
|
||||||
export default function getFile(): [string[], IResultFile] {
|
export default function getFile(): [string[], ResultFile] {
|
||||||
const file = new ResultFile(
|
const file = createResultFile(
|
||||||
'.prettierrc',
|
'.prettierrc',
|
||||||
'js',
|
'js',
|
||||||
`
|
`
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
import ResultFile from '../../../../../../../../../../../model/ResultFile';
|
import { ResultFile } from '@ali/lowcode-types';
|
||||||
import { IResultFile } from '../../../../../../../../../../../types';
|
import { createResultFile } from '../../../../../../../../../../../utils/resultHelper';
|
||||||
|
|
||||||
export default function getFile(): [string[], IResultFile] {
|
export default function getFile(): [string[], ResultFile] {
|
||||||
const file = new ResultFile(
|
const file = createResultFile(
|
||||||
'index',
|
'index',
|
||||||
'jsx',
|
'jsx',
|
||||||
`
|
`
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
import ResultFile from '../../../../../../../../../../../model/ResultFile';
|
import { ResultFile } from '@ali/lowcode-types';
|
||||||
import { IResultFile } from '../../../../../../../../../../../types';
|
import { createResultFile } from '../../../../../../../../../../../utils/resultHelper';
|
||||||
|
|
||||||
export default function getFile(): [string[], IResultFile] {
|
export default function getFile(): [string[], ResultFile] {
|
||||||
const file = new ResultFile(
|
const file = createResultFile(
|
||||||
'index',
|
'index',
|
||||||
'module.scss',
|
'module.scss',
|
||||||
`
|
`
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
import ResultFile from '../../../../../../../../../../../model/ResultFile';
|
import { ResultFile } from '@ali/lowcode-types';
|
||||||
import { IResultFile } from '../../../../../../../../../../../types';
|
import { createResultFile } from '../../../../../../../../../../../utils/resultHelper';
|
||||||
|
|
||||||
export default function getFile(): [string[], IResultFile] {
|
export default function getFile(): [string[], ResultFile] {
|
||||||
const file = new ResultFile(
|
const file = createResultFile(
|
||||||
'index',
|
'index',
|
||||||
'jsx',
|
'jsx',
|
||||||
`
|
`
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
import ResultFile from '../../../../../../../../../../../model/ResultFile';
|
import { ResultFile } from '@ali/lowcode-types';
|
||||||
import { IResultFile } from '../../../../../../../../../../../types';
|
import { createResultFile } from '../../../../../../../../../../../utils/resultHelper';
|
||||||
|
|
||||||
export default function getFile(): [string[], IResultFile] {
|
export default function getFile(): [string[], ResultFile] {
|
||||||
const file = new ResultFile(
|
const file = createResultFile(
|
||||||
'index',
|
'index',
|
||||||
'module.scss',
|
'module.scss',
|
||||||
`
|
`
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
import ResultFile from '../../../../../../../../../../../model/ResultFile';
|
import { ResultFile } from '@ali/lowcode-types';
|
||||||
import { IResultFile } from '../../../../../../../../../../../types';
|
import { createResultFile } from '../../../../../../../../../../../utils/resultHelper';
|
||||||
|
|
||||||
export default function getFile(): [string[], IResultFile] {
|
export default function getFile(): [string[], ResultFile] {
|
||||||
const file = new ResultFile(
|
const file = createResultFile(
|
||||||
'index',
|
'index',
|
||||||
'jsx',
|
'jsx',
|
||||||
`
|
`
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
import ResultFile from '../../../../../../../../../model/ResultFile';
|
import { ResultFile } from '@ali/lowcode-types';
|
||||||
import { IResultFile } from '../../../../../../../../../types';
|
import { createResultFile } from '../../../../../../../../../utils/resultHelper';
|
||||||
|
|
||||||
export default function getFile(): [string[], IResultFile] {
|
export default function getFile(): [string[], ResultFile] {
|
||||||
const file = new ResultFile(
|
const file = createResultFile(
|
||||||
'index',
|
'index',
|
||||||
'jsx',
|
'jsx',
|
||||||
`
|
`
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
import ResultFile from '../../../../../../../../../model/ResultFile';
|
import { ResultFile } from '@ali/lowcode-types';
|
||||||
import { IResultFile } from '../../../../../../../../../types';
|
import { createResultFile } from '../../../../../../../../../utils/resultHelper';
|
||||||
|
|
||||||
export default function getFile(): [string[], IResultFile] {
|
export default function getFile(): [string[], ResultFile] {
|
||||||
const file = new ResultFile(
|
const file = createResultFile(
|
||||||
'menuConfig',
|
'menuConfig',
|
||||||
'js',
|
'js',
|
||||||
`
|
`
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
import ResultFile from '../../../../../../model/ResultFile';
|
import { ResultFile } from '@ali/lowcode-types';
|
||||||
import { IResultFile } from '../../../../../../types';
|
import { createResultFile } from '../../../../../../utils/resultHelper';
|
||||||
|
|
||||||
export default function getFile(): [string[], IResultFile] {
|
export default function getFile(): [string[], ResultFile] {
|
||||||
const file = new ResultFile(
|
const file = createResultFile(
|
||||||
'.stylelintignore',
|
'.stylelintignore',
|
||||||
'',
|
'',
|
||||||
`
|
`
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
import ResultFile from '../../../../../../model/ResultFile';
|
import { ResultFile } from '@ali/lowcode-types';
|
||||||
import { IResultFile } from '../../../../../../types';
|
import { createResultFile } from '../../../../../../utils/resultHelper';
|
||||||
|
|
||||||
export default function getFile(): [string[], IResultFile] {
|
export default function getFile(): [string[], ResultFile] {
|
||||||
const file = new ResultFile(
|
const file = createResultFile(
|
||||||
'.stylelintrc',
|
'.stylelintrc',
|
||||||
'js',
|
'js',
|
||||||
`
|
`
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
import ResultFile from '../../../../../../model/ResultFile';
|
import { ResultFile } from '@ali/lowcode-types';
|
||||||
import { IResultFile } from '../../../../../../types';
|
import { createResultFile } from '../../../../../../utils/resultHelper';
|
||||||
|
|
||||||
export default function getFile(): [string[], IResultFile] {
|
export default function getFile(): [string[], ResultFile] {
|
||||||
const file = new ResultFile(
|
const file = createResultFile(
|
||||||
'tsconfig',
|
'tsconfig',
|
||||||
'json',
|
'json',
|
||||||
`
|
`
|
||||||
|
|||||||
@ -1,8 +1,7 @@
|
|||||||
import ResultDir from '../../../../../model/ResultDir';
|
import { ResultDir } from '@ali/lowcode-types';
|
||||||
import {
|
import { IProjectTemplate } from '../../../../../types';
|
||||||
IProjectTemplate,
|
|
||||||
IResultDir,
|
import { createResultDir } from '../../../../../utils/resultHelper';
|
||||||
} from '../../../../../types';
|
|
||||||
import { runFileGenerator } from '../../../../../utils/templateHelper';
|
import { runFileGenerator } from '../../../../../utils/templateHelper';
|
||||||
|
|
||||||
import file12 from './files/abc.json';
|
import file12 from './files/abc.json';
|
||||||
@ -68,8 +67,8 @@ const icejsTemplate: IProjectTemplate = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
generateTemplate(): IResultDir {
|
generateTemplate(): ResultDir {
|
||||||
const root = new ResultDir('.');
|
const root = createResultDir('.');
|
||||||
|
|
||||||
runFileGenerator(root, file1);
|
runFileGenerator(root, file1);
|
||||||
runFileGenerator(root, file2);
|
runFileGenerator(root, file2);
|
||||||
|
|||||||
@ -0,0 +1,19 @@
|
|||||||
|
import template from './template';
|
||||||
|
import entry from './plugins/entry';
|
||||||
|
import appConfig from './plugins/appConfig';
|
||||||
|
import buildConfig from './plugins/buildConfig';
|
||||||
|
import entryDocument from './plugins/entryDocument';
|
||||||
|
import globalStyle from './plugins/globalStyle';
|
||||||
|
import packageJSON from './plugins/packageJSON';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
template,
|
||||||
|
plugins: {
|
||||||
|
appConfig,
|
||||||
|
buildConfig,
|
||||||
|
entry,
|
||||||
|
entryDocument,
|
||||||
|
globalStyle,
|
||||||
|
packageJSON,
|
||||||
|
},
|
||||||
|
};
|
||||||
@ -0,0 +1,46 @@
|
|||||||
|
import changeCase from 'change-case';
|
||||||
|
import { COMMON_CHUNK_NAME } from '../../../../../const/generator';
|
||||||
|
|
||||||
|
import {
|
||||||
|
BuilderComponentPlugin,
|
||||||
|
BuilderComponentPluginFactory,
|
||||||
|
ChunkType,
|
||||||
|
FileType,
|
||||||
|
ICodeStruct,
|
||||||
|
IParseResult,
|
||||||
|
} from '../../../../../types';
|
||||||
|
|
||||||
|
const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
|
||||||
|
const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => {
|
||||||
|
const next: ICodeStruct = {
|
||||||
|
...pre,
|
||||||
|
};
|
||||||
|
|
||||||
|
const ir = next.ir as IParseResult;
|
||||||
|
|
||||||
|
const routes = ir.globalRouter?.routes?.map((route) => ({
|
||||||
|
path: route.path,
|
||||||
|
source: `pages/${changeCase.pascalCase(route.fileName)}/index`,
|
||||||
|
})) || [{ path: '/', source: 'pages/Home/index' }];
|
||||||
|
|
||||||
|
next.chunks.push({
|
||||||
|
type: ChunkType.STRING,
|
||||||
|
fileType: FileType.JSON,
|
||||||
|
name: COMMON_CHUNK_NAME.CustomContent,
|
||||||
|
content: `
|
||||||
|
{
|
||||||
|
"routes": ${JSON.stringify(routes, null, 2)},
|
||||||
|
"window": {
|
||||||
|
"title": ${JSON.stringify(ir.project?.meta?.title || ir.project?.meta?.name || '')}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
linkAfter: [],
|
||||||
|
});
|
||||||
|
|
||||||
|
return next;
|
||||||
|
};
|
||||||
|
return plugin;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default pluginFactory;
|
||||||
@ -16,7 +16,8 @@ const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const ir = next.ir as IParseResult;
|
const ir = next.ir as IParseResult;
|
||||||
const miniAppBuildType = ir.project?.config.miniAppBuildType;
|
// TODO: miniAppBuildType 这个东西是不是不应该在 schema 里面,而是应该由 plugin 的构造参数传入
|
||||||
|
const miniAppBuildType = ir.project?.config?.miniAppBuildType;
|
||||||
|
|
||||||
const buildCfg = {
|
const buildCfg = {
|
||||||
inlineStyle: false,
|
inlineStyle: false,
|
||||||
@ -40,7 +41,7 @@ const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
|
|||||||
type: ChunkType.STRING,
|
type: ChunkType.STRING,
|
||||||
fileType: FileType.JSON,
|
fileType: FileType.JSON,
|
||||||
name: COMMON_CHUNK_NAME.CustomContent,
|
name: COMMON_CHUNK_NAME.CustomContent,
|
||||||
content: `${JSON.stringify(buildCfg, null, 2) }\n`,
|
content: JSON.stringify(buildCfg, null, 2) + '\n',
|
||||||
linkAfter: [],
|
linkAfter: [],
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,51 @@
|
|||||||
|
import { COMMON_CHUNK_NAME } from '../../../../../const/generator';
|
||||||
|
|
||||||
|
import {
|
||||||
|
BuilderComponentPlugin,
|
||||||
|
BuilderComponentPluginFactory,
|
||||||
|
ChunkType,
|
||||||
|
FileType,
|
||||||
|
ICodeStruct,
|
||||||
|
} from '../../../../../types';
|
||||||
|
|
||||||
|
const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
|
||||||
|
const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => {
|
||||||
|
const next: ICodeStruct = {
|
||||||
|
...pre,
|
||||||
|
};
|
||||||
|
|
||||||
|
next.chunks.push({
|
||||||
|
type: ChunkType.STRING,
|
||||||
|
fileType: FileType.JS,
|
||||||
|
name: COMMON_CHUNK_NAME.ExternalDepsImport,
|
||||||
|
content: `
|
||||||
|
import { runApp } from 'rax-app';
|
||||||
|
import appConfig from './app.json';
|
||||||
|
|
||||||
|
import './global.scss';
|
||||||
|
`,
|
||||||
|
linkAfter: [],
|
||||||
|
});
|
||||||
|
|
||||||
|
next.chunks.push({
|
||||||
|
type: ChunkType.STRING,
|
||||||
|
fileType: FileType.JS,
|
||||||
|
name: COMMON_CHUNK_NAME.FileMainContent,
|
||||||
|
content: `
|
||||||
|
runApp(appConfig);
|
||||||
|
`,
|
||||||
|
linkAfter: [
|
||||||
|
COMMON_CHUNK_NAME.ExternalDepsImport,
|
||||||
|
COMMON_CHUNK_NAME.InternalDepsImport,
|
||||||
|
COMMON_CHUNK_NAME.ImportAliasDefine,
|
||||||
|
COMMON_CHUNK_NAME.FileVarDefine,
|
||||||
|
COMMON_CHUNK_NAME.FileUtilDefine,
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
return next;
|
||||||
|
};
|
||||||
|
return plugin;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default pluginFactory;
|
||||||
@ -0,0 +1,59 @@
|
|||||||
|
import { COMMON_CHUNK_NAME } from '../../../../../const/generator';
|
||||||
|
|
||||||
|
import {
|
||||||
|
BuilderComponentPlugin,
|
||||||
|
BuilderComponentPluginFactory,
|
||||||
|
ChunkType,
|
||||||
|
FileType,
|
||||||
|
ICodeStruct,
|
||||||
|
IProjectInfo,
|
||||||
|
} from '../../../../../types';
|
||||||
|
|
||||||
|
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.JSX,
|
||||||
|
name: COMMON_CHUNK_NAME.CustomContent,
|
||||||
|
content: `
|
||||||
|
import { createElement } from 'rax';
|
||||||
|
import { Root, Style, Script } from 'rax-document';
|
||||||
|
|
||||||
|
function Document() {
|
||||||
|
return (
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<meta
|
||||||
|
name="viewport"
|
||||||
|
content="width=device-width,initial-scale=1,maximum-scale=1,minimum-scale=1,user-scalable=no,viewport-fit=cover"
|
||||||
|
/>
|
||||||
|
<title>${ir?.meta?.name || 'Rax App'}</title>
|
||||||
|
<Style />
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
{/* root container */}
|
||||||
|
<Root />
|
||||||
|
<Script />
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Document;
|
||||||
|
`,
|
||||||
|
linkAfter: [],
|
||||||
|
});
|
||||||
|
|
||||||
|
return next;
|
||||||
|
};
|
||||||
|
return plugin;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default pluginFactory;
|
||||||
@ -0,0 +1,64 @@
|
|||||||
|
import { COMMON_CHUNK_NAME } from '../../../../../const/generator';
|
||||||
|
|
||||||
|
import {
|
||||||
|
BuilderComponentPlugin,
|
||||||
|
BuilderComponentPluginFactory,
|
||||||
|
ChunkType,
|
||||||
|
FileType,
|
||||||
|
ICodeStruct,
|
||||||
|
IProjectInfo,
|
||||||
|
} from '../../../../../types';
|
||||||
|
|
||||||
|
export type GlobalStylePluginConfig = {
|
||||||
|
fileType: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
const pluginFactory: BuilderComponentPluginFactory<GlobalStylePluginConfig> = (
|
||||||
|
config?: Partial<GlobalStylePluginConfig>,
|
||||||
|
) => {
|
||||||
|
const cfg: GlobalStylePluginConfig = {
|
||||||
|
fileType: FileType.SCSS,
|
||||||
|
...config,
|
||||||
|
};
|
||||||
|
|
||||||
|
const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => {
|
||||||
|
const next: ICodeStruct = {
|
||||||
|
...pre,
|
||||||
|
};
|
||||||
|
|
||||||
|
const ir = next.ir as IProjectInfo;
|
||||||
|
|
||||||
|
next.chunks.push({
|
||||||
|
type: ChunkType.STRING,
|
||||||
|
fileType: cfg.fileType,
|
||||||
|
name: COMMON_CHUNK_NAME.StyleDepsImport,
|
||||||
|
content: '',
|
||||||
|
linkAfter: [],
|
||||||
|
});
|
||||||
|
|
||||||
|
next.chunks.push({
|
||||||
|
type: ChunkType.STRING,
|
||||||
|
fileType: cfg.fileType,
|
||||||
|
name: COMMON_CHUNK_NAME.StyleCssContent,
|
||||||
|
content: `
|
||||||
|
body {
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
linkAfter: [COMMON_CHUNK_NAME.StyleDepsImport],
|
||||||
|
});
|
||||||
|
|
||||||
|
next.chunks.push({
|
||||||
|
type: ChunkType.STRING,
|
||||||
|
fileType: cfg.fileType,
|
||||||
|
name: COMMON_CHUNK_NAME.StyleCssContent,
|
||||||
|
content: ir.css || '',
|
||||||
|
linkAfter: [COMMON_CHUNK_NAME.StyleDepsImport],
|
||||||
|
});
|
||||||
|
|
||||||
|
return next;
|
||||||
|
};
|
||||||
|
return plugin;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default pluginFactory;
|
||||||
@ -0,0 +1,115 @@
|
|||||||
|
import { NpmInfo, PackageJSON } from '@ali/lowcode-types';
|
||||||
|
import { COMMON_CHUNK_NAME } from '../../../../../const/generator';
|
||||||
|
|
||||||
|
import {
|
||||||
|
BuilderComponentPlugin,
|
||||||
|
BuilderComponentPluginFactory,
|
||||||
|
ChunkType,
|
||||||
|
FileType,
|
||||||
|
ICodeStruct,
|
||||||
|
IProjectInfo,
|
||||||
|
} from '../../../../../types';
|
||||||
|
import { isNpmInfo } from '../../../../../utils/schema';
|
||||||
|
import { calcCompatibleVersion } from '../../../../../utils/version';
|
||||||
|
|
||||||
|
const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
|
||||||
|
const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => {
|
||||||
|
const next: ICodeStruct = {
|
||||||
|
...pre,
|
||||||
|
};
|
||||||
|
|
||||||
|
const ir = next.ir as IProjectInfo;
|
||||||
|
|
||||||
|
const npmDeps = getNpmDependencies(ir);
|
||||||
|
|
||||||
|
const packageJson: PackageJSON = {
|
||||||
|
name: '@ali/rax-app-demo',
|
||||||
|
private: true,
|
||||||
|
version: '1.0.0',
|
||||||
|
scripts: {
|
||||||
|
build: 'build-scripts build',
|
||||||
|
start: 'build-scripts start',
|
||||||
|
lint: 'eslint --ext .js --ext .jsx ./',
|
||||||
|
},
|
||||||
|
dependencies: {
|
||||||
|
'@ali/lowcode-datasource-engine': '*',
|
||||||
|
// TODO: 如何动态获取下面这些依赖?
|
||||||
|
'@ali/lowcode-datasource-url-params-handler': '*',
|
||||||
|
'@ali/lowcode-datasource-fetch-handler': '*',
|
||||||
|
'@ali/lowcode-datasource-mtop-handler': '*',
|
||||||
|
'@ali/lowcode-datasource-mopen-handler': '*',
|
||||||
|
'universal-env': '^3.2.0',
|
||||||
|
'intl-messageformat': '^9.3.6',
|
||||||
|
rax: '^1.1.0',
|
||||||
|
'rax-app': '^2.0.0',
|
||||||
|
'rax-document': '^0.1.0',
|
||||||
|
...npmDeps.reduce(
|
||||||
|
(acc, npm) => ({
|
||||||
|
...acc,
|
||||||
|
[npm.package]: npm.version || '*',
|
||||||
|
}),
|
||||||
|
{} as Record<string, string>,
|
||||||
|
),
|
||||||
|
},
|
||||||
|
devDependencies: {
|
||||||
|
'build-plugin-rax-app': '^5.0.0',
|
||||||
|
'@alib/build-scripts': '^0.1.0',
|
||||||
|
'@typescript-eslint/eslint-plugin': '^2.11.0',
|
||||||
|
'@typescript-eslint/parser': '^2.11.0',
|
||||||
|
'babel-eslint': '^10.0.3',
|
||||||
|
eslint: '^6.8.0',
|
||||||
|
'eslint-config-rax': '^0.1.0',
|
||||||
|
'eslint-plugin-import': '^2.20.0',
|
||||||
|
'eslint-plugin-module': '^0.1.0',
|
||||||
|
'eslint-plugin-react': '^7.18.0',
|
||||||
|
'@ali/build-plugin-rax-app-def': '^1.0.0',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
next.chunks.push({
|
||||||
|
type: ChunkType.JSON,
|
||||||
|
fileType: FileType.JSON,
|
||||||
|
name: COMMON_CHUNK_NAME.FileMainContent,
|
||||||
|
content: packageJson,
|
||||||
|
linkAfter: [],
|
||||||
|
});
|
||||||
|
|
||||||
|
return next;
|
||||||
|
};
|
||||||
|
return plugin;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default pluginFactory;
|
||||||
|
|
||||||
|
function getNpmDependencies(project: IProjectInfo): NpmInfo[] {
|
||||||
|
const npmDeps: NpmInfo[] = [];
|
||||||
|
const npmNameToPkgMap = new Map<string, NpmInfo>();
|
||||||
|
|
||||||
|
const allDeps = project.packages;
|
||||||
|
|
||||||
|
allDeps.forEach((dep) => {
|
||||||
|
if (!isNpmInfo(dep)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const existing = npmNameToPkgMap.get(dep.package);
|
||||||
|
if (!existing) {
|
||||||
|
npmNameToPkgMap.set(dep.package, dep);
|
||||||
|
npmDeps.push(dep);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (existing.version !== dep.version) {
|
||||||
|
try {
|
||||||
|
npmNameToPkgMap.set(dep.package, {
|
||||||
|
...existing,
|
||||||
|
version: calcCompatibleVersion(existing.version, dep.version),
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
throw new Error(`Cannot find compatible version for ${dep.package}. Detail: ${e.message}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return npmDeps;
|
||||||
|
}
|
||||||
@ -0,0 +1,27 @@
|
|||||||
|
import { ResultFile } from '@ali/lowcode-types';
|
||||||
|
import { createResultFile } from '../../../../../../utils/resultHelper';
|
||||||
|
|
||||||
|
export default function getFile(): [string[], ResultFile] {
|
||||||
|
const file = createResultFile(
|
||||||
|
'README',
|
||||||
|
'md',
|
||||||
|
`# @ali/rax-component-demo
|
||||||
|
|
||||||
|
## Getting Started
|
||||||
|
|
||||||
|
### \`npm run start\`
|
||||||
|
|
||||||
|
Runs the app in development mode.
|
||||||
|
|
||||||
|
Open [http://localhost:9999](http://localhost:9999) to view it in the browser.
|
||||||
|
|
||||||
|
The page will reload if you make edits.
|
||||||
|
|
||||||
|
### \`npm run build\`
|
||||||
|
|
||||||
|
Builds the app for production to the \`build\` folder.
|
||||||
|
`,
|
||||||
|
);
|
||||||
|
|
||||||
|
return [[], file];
|
||||||
|
}
|
||||||
@ -0,0 +1,19 @@
|
|||||||
|
import { ResultFile } from '@ali/lowcode-types';
|
||||||
|
import { createResultFile } from '../../../../../../utils/resultHelper';
|
||||||
|
|
||||||
|
export default function getFile(): [string[], ResultFile] {
|
||||||
|
const file = createResultFile(
|
||||||
|
'abc',
|
||||||
|
'json',
|
||||||
|
`{
|
||||||
|
"type": "rax",
|
||||||
|
"builder": "@ali/builder-rax-v1",
|
||||||
|
"info": {
|
||||||
|
"raxVersion": "1.x"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
);
|
||||||
|
|
||||||
|
return [[], file];
|
||||||
|
}
|
||||||
@ -0,0 +1,24 @@
|
|||||||
|
import { ResultFile } from '@ali/lowcode-types';
|
||||||
|
import { createResultFile } from '../../../../../../utils/resultHelper';
|
||||||
|
|
||||||
|
export default function getFile(): [string[], ResultFile] {
|
||||||
|
const file = createResultFile(
|
||||||
|
'build',
|
||||||
|
'json',
|
||||||
|
`{
|
||||||
|
"inlineStyle": false,
|
||||||
|
"plugins": [
|
||||||
|
[
|
||||||
|
"build-plugin-rax-app",
|
||||||
|
{
|
||||||
|
"targets": ["web", "miniapp"]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"@ali/build-plugin-rax-app-def"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
);
|
||||||
|
|
||||||
|
return [[], file];
|
||||||
|
}
|
||||||
@ -0,0 +1,25 @@
|
|||||||
|
|
||||||
|
import { ResultFile } from '@ali/lowcode-types';
|
||||||
|
import { createResultFile } from '../../../../../../utils/resultHelper';
|
||||||
|
|
||||||
|
export default function getFile(): [string[], ResultFile] {
|
||||||
|
const file = createResultFile(
|
||||||
|
'.editorconfig',
|
||||||
|
'',
|
||||||
|
`# http://editorconfig.org
|
||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 2
|
||||||
|
charset = utf-8
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
insert_final_newline = true
|
||||||
|
|
||||||
|
[*.md]
|
||||||
|
trim_trailing_whitespace = false
|
||||||
|
`,
|
||||||
|
);
|
||||||
|
|
||||||
|
return [[], file];
|
||||||
|
}
|
||||||
@ -0,0 +1,23 @@
|
|||||||
|
import { ResultFile } from '@ali/lowcode-types';
|
||||||
|
import { createResultFile } from '../../../../../../utils/resultHelper';
|
||||||
|
|
||||||
|
export default function getFile(): [string[], ResultFile] {
|
||||||
|
const file = createResultFile(
|
||||||
|
'.eslintignore',
|
||||||
|
'',
|
||||||
|
`# 忽略目录
|
||||||
|
build/
|
||||||
|
tests/
|
||||||
|
demo/
|
||||||
|
|
||||||
|
# node 覆盖率文件
|
||||||
|
coverage/
|
||||||
|
|
||||||
|
# 忽略文件
|
||||||
|
**/*-min.js
|
||||||
|
**/*.min.js
|
||||||
|
`,
|
||||||
|
);
|
||||||
|
|
||||||
|
return [[], file];
|
||||||
|
}
|
||||||
@ -0,0 +1,16 @@
|
|||||||
|
|
||||||
|
import { ResultFile } from '@ali/lowcode-types';
|
||||||
|
import { createResultFile } from '../../../../../../utils/resultHelper';
|
||||||
|
|
||||||
|
export default function getFile(): [string[], ResultFile] {
|
||||||
|
const file = createResultFile(
|
||||||
|
'.eslintrc',
|
||||||
|
'js',
|
||||||
|
`module.exports = {
|
||||||
|
extends: ['rax'],
|
||||||
|
};
|
||||||
|
`,
|
||||||
|
);
|
||||||
|
|
||||||
|
return [[], file];
|
||||||
|
}
|
||||||
@ -0,0 +1,29 @@
|
|||||||
|
import { ResultFile } from '@ali/lowcode-types';
|
||||||
|
import { createResultFile } from '../../../../../../utils/resultHelper';
|
||||||
|
|
||||||
|
export default function getFile(): [string[], ResultFile] {
|
||||||
|
const file = createResultFile(
|
||||||
|
'.gitignore',
|
||||||
|
'',
|
||||||
|
`# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
||||||
|
|
||||||
|
*~
|
||||||
|
*.swp
|
||||||
|
*.log
|
||||||
|
|
||||||
|
.DS_Store
|
||||||
|
.idea/
|
||||||
|
.temp/
|
||||||
|
|
||||||
|
build/
|
||||||
|
dist/
|
||||||
|
lib/
|
||||||
|
coverage/
|
||||||
|
node_modules/
|
||||||
|
|
||||||
|
template.yml
|
||||||
|
`,
|
||||||
|
);
|
||||||
|
|
||||||
|
return [[], file];
|
||||||
|
}
|
||||||
@ -0,0 +1,78 @@
|
|||||||
|
import { ResultDir } from '@ali/lowcode-types';
|
||||||
|
import { IProjectTemplate } from '../../../../../types';
|
||||||
|
|
||||||
|
import { runFileGenerator } from '../../../../../utils/templateHelper';
|
||||||
|
import { createResultDir } from '../../../../../utils/resultHelper';
|
||||||
|
|
||||||
|
import file0 from './files/editorconfig';
|
||||||
|
import file1 from './files/eslintignore';
|
||||||
|
import file2 from './files/eslintrc.js';
|
||||||
|
import file3 from './files/gitignore';
|
||||||
|
import file4 from './files/README.md';
|
||||||
|
import file5 from './files/abc.json';
|
||||||
|
|
||||||
|
const raxAppTemplate: IProjectTemplate = {
|
||||||
|
slots: {
|
||||||
|
components: {
|
||||||
|
path: ['src', 'components'],
|
||||||
|
},
|
||||||
|
pages: {
|
||||||
|
path: ['src', 'pages'],
|
||||||
|
},
|
||||||
|
router: {
|
||||||
|
path: ['src'],
|
||||||
|
fileName: 'router',
|
||||||
|
},
|
||||||
|
entry: {
|
||||||
|
path: ['src'],
|
||||||
|
fileName: 'app',
|
||||||
|
},
|
||||||
|
appConfig: {
|
||||||
|
path: ['src'],
|
||||||
|
fileName: 'app',
|
||||||
|
},
|
||||||
|
buildConfig: {
|
||||||
|
path: [],
|
||||||
|
fileName: 'build',
|
||||||
|
},
|
||||||
|
constants: {
|
||||||
|
path: ['src'],
|
||||||
|
fileName: 'constants',
|
||||||
|
},
|
||||||
|
utils: {
|
||||||
|
path: ['src'],
|
||||||
|
fileName: 'utils',
|
||||||
|
},
|
||||||
|
i18n: {
|
||||||
|
path: ['src'],
|
||||||
|
fileName: 'i18n',
|
||||||
|
},
|
||||||
|
globalStyle: {
|
||||||
|
path: ['src'],
|
||||||
|
fileName: 'global',
|
||||||
|
},
|
||||||
|
htmlEntry: {
|
||||||
|
path: ['src', 'document'],
|
||||||
|
fileName: 'index',
|
||||||
|
},
|
||||||
|
packageJSON: {
|
||||||
|
path: [],
|
||||||
|
fileName: 'package',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
generateTemplate(): ResultDir {
|
||||||
|
const root = createResultDir('.');
|
||||||
|
|
||||||
|
runFileGenerator(root, file0);
|
||||||
|
runFileGenerator(root, file1);
|
||||||
|
runFileGenerator(root, file2);
|
||||||
|
runFileGenerator(root, file3);
|
||||||
|
runFileGenerator(root, file4);
|
||||||
|
runFileGenerator(root, file5);
|
||||||
|
|
||||||
|
return root;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default raxAppTemplate;
|
||||||
@ -1,9 +1,8 @@
|
|||||||
|
import { ResultFile } from '@ali/lowcode-types';
|
||||||
|
import { createResultFile } from '../../../../../../utils/resultHelper';
|
||||||
|
|
||||||
import ResultFile from '../../../../../../model/ResultFile';
|
export default function getFile(): [string[], ResultFile] {
|
||||||
import { IResultFile } from '../../../../../../types';
|
const file = createResultFile(
|
||||||
|
|
||||||
export default function getFile(): [string[], IResultFile] {
|
|
||||||
const file = new ResultFile(
|
|
||||||
'.editorconfig',
|
'.editorconfig',
|
||||||
'',
|
'',
|
||||||
`
|
`
|
||||||
@ -29,4 +28,3 @@ trim_trailing_whitespace = false
|
|||||||
|
|
||||||
return [[], file];
|
return [[], file];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1,9 +1,9 @@
|
|||||||
|
|
||||||
import ResultFile from '../../../../../../model/ResultFile';
|
import { ResultFile } from '@ali/lowcode-types';
|
||||||
import { IResultFile } from '../../../../../../types';
|
import { createResultFile } from '../../../../../../utils/resultHelper';
|
||||||
|
|
||||||
export default function getFile(): [string[], IResultFile] {
|
export default function getFile(): [string[], ResultFile] {
|
||||||
const file = new ResultFile(
|
const file = createResultFile(
|
||||||
'.eslintignore',
|
'.eslintignore',
|
||||||
'',
|
'',
|
||||||
`
|
`
|
||||||
@ -23,4 +23,3 @@ packages/solution
|
|||||||
|
|
||||||
return [[], file];
|
return [[], file];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1,9 +1,8 @@
|
|||||||
|
import { ResultFile } from '@ali/lowcode-types';
|
||||||
|
import { createResultFile } from '../../../../../../utils/resultHelper';
|
||||||
|
|
||||||
import ResultFile from '../../../../../../model/ResultFile';
|
export default function getFile(): [string[], ResultFile] {
|
||||||
import { IResultFile } from '../../../../../../types';
|
const file = createResultFile(
|
||||||
|
|
||||||
export default function getFile(): [string[], IResultFile] {
|
|
||||||
const file = new ResultFile(
|
|
||||||
'.gitignore',
|
'.gitignore',
|
||||||
'',
|
'',
|
||||||
`
|
`
|
||||||
@ -54,4 +53,3 @@ Thumbs.db
|
|||||||
|
|
||||||
return [[], file];
|
return [[], file];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1,9 +1,8 @@
|
|||||||
|
import { ResultFile } from '@ali/lowcode-types';
|
||||||
|
import { createResultFile } from '../../../../../../utils/resultHelper';
|
||||||
|
|
||||||
import ResultFile from '../../../../../../model/ResultFile';
|
export default function getFile(): [string[], ResultFile] {
|
||||||
import { IResultFile } from '../../../../../../types';
|
const file = createResultFile(
|
||||||
|
|
||||||
export default function getFile(): [string[], IResultFile] {
|
|
||||||
const file = new ResultFile(
|
|
||||||
'.prettierrc',
|
'.prettierrc',
|
||||||
'',
|
'',
|
||||||
`
|
`
|
||||||
@ -19,4 +18,3 @@ export default function getFile(): [string[], IResultFile] {
|
|||||||
|
|
||||||
return [[], file];
|
return [[], file];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1,9 +1,8 @@
|
|||||||
|
import { ResultFile } from '@ali/lowcode-types';
|
||||||
|
import { createResultFile } from '../../../../../../utils/resultHelper';
|
||||||
|
|
||||||
import ResultFile from '../../../../../../model/ResultFile';
|
export default function getFile(): [string[], ResultFile] {
|
||||||
import { IResultFile } from '../../../../../../types';
|
const file = createResultFile(
|
||||||
|
|
||||||
export default function getFile(): [string[], IResultFile] {
|
|
||||||
const file = new ResultFile(
|
|
||||||
'README',
|
'README',
|
||||||
'md',
|
'md',
|
||||||
`
|
`
|
||||||
|
|||||||
@ -1,9 +1,8 @@
|
|||||||
|
import { ResultFile } from '@ali/lowcode-types';
|
||||||
|
import { createResultFile } from '../../../../../../utils/resultHelper';
|
||||||
|
|
||||||
import ResultFile from '../../../../../../model/ResultFile';
|
export default function getFile(): [string[], ResultFile] {
|
||||||
import { IResultFile } from '../../../../../../types';
|
const file = createResultFile(
|
||||||
|
|
||||||
export default function getFile(): [string[], IResultFile] {
|
|
||||||
const file = new ResultFile(
|
|
||||||
'abc',
|
'abc',
|
||||||
'json',
|
'json',
|
||||||
`
|
`
|
||||||
|
|||||||
@ -1,9 +1,8 @@
|
|||||||
|
import { ResultFile } from '@ali/lowcode-types';
|
||||||
|
import { createResultFile } from '../../../../../../utils/resultHelper';
|
||||||
|
|
||||||
import ResultFile from '../../../../../../model/ResultFile';
|
export default function getFile(): [string[], ResultFile] {
|
||||||
import { IResultFile } from '../../../../../../types';
|
const file = createResultFile(
|
||||||
|
|
||||||
export default function getFile(): [string[], IResultFile] {
|
|
||||||
const file = new ResultFile(
|
|
||||||
'build',
|
'build',
|
||||||
'json',
|
'json',
|
||||||
`
|
`
|
||||||
|
|||||||
@ -1,9 +1,8 @@
|
|||||||
|
import { ResultFile } from '@ali/lowcode-types';
|
||||||
|
import { createResultFile } from '../../../../../../utils/resultHelper';
|
||||||
|
|
||||||
import ResultFile from '../../../../../../model/ResultFile';
|
export default function getFile(): [string[], ResultFile] {
|
||||||
import { IResultFile } from '../../../../../../types';
|
const file = createResultFile(
|
||||||
|
|
||||||
export default function getFile(): [string[], IResultFile] {
|
|
||||||
const file = new ResultFile(
|
|
||||||
'package',
|
'package',
|
||||||
'json',
|
'json',
|
||||||
`
|
`
|
||||||
|
|||||||
@ -1,9 +1,8 @@
|
|||||||
|
import { ResultFile } from '@ali/lowcode-types';
|
||||||
|
import { createResultFile } from '../../../../../../../utils/resultHelper';
|
||||||
|
|
||||||
import ResultFile from '../../../../../../../model/ResultFile';
|
export default function getFile(): [string[], ResultFile] {
|
||||||
import { IResultFile } from '../../../../../../../types';
|
const file = createResultFile(
|
||||||
|
|
||||||
export default function getFile(): [string[], IResultFile] {
|
|
||||||
const file = new ResultFile(
|
|
||||||
'index',
|
'index',
|
||||||
'html',
|
'html',
|
||||||
`
|
`
|
||||||
|
|||||||
@ -1,9 +1,8 @@
|
|||||||
|
import { ResultFile } from '@ali/lowcode-types';
|
||||||
|
import { createResultFile } from '../../../../../../../../utils/resultHelper';
|
||||||
|
|
||||||
import ResultFile from '../../../../../../../../model/ResultFile';
|
export default function getFile(): [string[], ResultFile] {
|
||||||
import { IResultFile } from '../../../../../../../../types';
|
const file = createResultFile(
|
||||||
|
|
||||||
export default function getFile(): [string[], IResultFile] {
|
|
||||||
const file = new ResultFile(
|
|
||||||
'app',
|
'app',
|
||||||
'ts',
|
'ts',
|
||||||
`
|
`
|
||||||
|
|||||||
@ -1,9 +1,8 @@
|
|||||||
|
import { ResultFile } from '@ali/lowcode-types';
|
||||||
|
import { createResultFile } from '../../../../../../../../utils/resultHelper';
|
||||||
|
|
||||||
import ResultFile from '../../../../../../../../model/ResultFile';
|
export default function getFile(): [string[], ResultFile] {
|
||||||
import { IResultFile } from '../../../../../../../../types';
|
const file = createResultFile(
|
||||||
|
|
||||||
export default function getFile(): [string[], IResultFile] {
|
|
||||||
const file = new ResultFile(
|
|
||||||
'components',
|
'components',
|
||||||
'ts',
|
'ts',
|
||||||
`
|
`
|
||||||
|
|||||||
@ -1,9 +1,8 @@
|
|||||||
|
import { ResultFile } from '@ali/lowcode-types';
|
||||||
|
import { createResultFile } from '../../../../../../../../utils/resultHelper';
|
||||||
|
|
||||||
import ResultFile from '../../../../../../../../model/ResultFile';
|
export default function getFile(): [string[], ResultFile] {
|
||||||
import { IResultFile } from '../../../../../../../../types';
|
const file = createResultFile(
|
||||||
|
|
||||||
export default function getFile(): [string[], IResultFile] {
|
|
||||||
const file = new ResultFile(
|
|
||||||
'utils',
|
'utils',
|
||||||
'ts',
|
'ts',
|
||||||
`
|
`
|
||||||
|
|||||||
@ -1,9 +1,8 @@
|
|||||||
|
import { ResultFile } from '@ali/lowcode-types';
|
||||||
|
import { createResultFile } from '../../../../../../../utils/resultHelper';
|
||||||
|
|
||||||
import ResultFile from '../../../../../../../model/ResultFile';
|
export default function getFile(): [string[], ResultFile] {
|
||||||
import { IResultFile } from '../../../../../../../types';
|
const file = createResultFile(
|
||||||
|
|
||||||
export default function getFile(): [string[], IResultFile] {
|
|
||||||
const file = new ResultFile(
|
|
||||||
'index',
|
'index',
|
||||||
'ts',
|
'ts',
|
||||||
`
|
`
|
||||||
|
|||||||
@ -1,9 +1,8 @@
|
|||||||
|
import { ResultFile } from '@ali/lowcode-types';
|
||||||
|
import { createResultFile } from '../../../../../../../utils/resultHelper';
|
||||||
|
|
||||||
import ResultFile from '../../../../../../../model/ResultFile';
|
export default function getFile(): [string[], ResultFile] {
|
||||||
import { IResultFile } from '../../../../../../../types';
|
const file = createResultFile(
|
||||||
|
|
||||||
export default function getFile(): [string[], IResultFile] {
|
|
||||||
const file = new ResultFile(
|
|
||||||
'router',
|
'router',
|
||||||
'ts',
|
'ts',
|
||||||
`
|
`
|
||||||
|
|||||||
@ -1,9 +1,8 @@
|
|||||||
|
import { ResultFile } from '@ali/lowcode-types';
|
||||||
|
import { createResultFile } from '../../../../../../utils/resultHelper';
|
||||||
|
|
||||||
import ResultFile from '../../../../../../model/ResultFile';
|
export default function getFile(): [string[], ResultFile] {
|
||||||
import { IResultFile } from '../../../../../../types';
|
const file = createResultFile(
|
||||||
|
|
||||||
export default function getFile(): [string[], IResultFile] {
|
|
||||||
const file = new ResultFile(
|
|
||||||
'tsconfig',
|
'tsconfig',
|
||||||
'json',
|
'json',
|
||||||
`
|
`
|
||||||
|
|||||||
@ -1,8 +1,6 @@
|
|||||||
import ResultDir from '../../../../../model/ResultDir';
|
import { ResultDir } from '@ali/lowcode-types';
|
||||||
import {
|
import { IProjectTemplate } from '../../../../../types';
|
||||||
IProjectTemplate,
|
import { createResultDir } from '../../../../../utils/resultHelper';
|
||||||
IResultDir,
|
|
||||||
} from '../../../../../types';
|
|
||||||
import { runFileGenerator } from '../../../../../utils/templateHelper';
|
import { runFileGenerator } from '../../../../../utils/templateHelper';
|
||||||
|
|
||||||
import file1 from './files/abc.json';
|
import file1 from './files/abc.json';
|
||||||
@ -28,8 +26,8 @@ const icejsTemplate: IProjectTemplate = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
generateTemplate(): IResultDir {
|
generateTemplate(): ResultDir {
|
||||||
const root = new ResultDir('.');
|
const root = createResultDir('.');
|
||||||
|
|
||||||
runFileGenerator(root, file1);
|
runFileGenerator(root, file1);
|
||||||
runFileGenerator(root, file2);
|
runFileGenerator(root, file2);
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import { COMMON_CHUNK_NAME } from '../../const/generator';
|
import { COMMON_CHUNK_NAME } from '../../const/generator';
|
||||||
import { generateCompositeType } from '../../utils/compositeType';
|
|
||||||
import {
|
import {
|
||||||
BuilderComponentPlugin,
|
BuilderComponentPlugin,
|
||||||
BuilderComponentPluginFactory,
|
BuilderComponentPluginFactory,
|
||||||
@ -16,51 +16,73 @@ const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const ir = next.ir as IProjectInfo;
|
const ir = next.ir as IProjectInfo;
|
||||||
if (ir.i18n) {
|
const i18nStr = ir.i18n ? JSON.stringify(ir.i18n, null, 2) : '{}';
|
||||||
const i18nStr = generateCompositeType(ir.i18n);
|
|
||||||
|
|
||||||
next.chunks.push({
|
next.chunks.push({
|
||||||
type: ChunkType.STRING,
|
type: ChunkType.STRING,
|
||||||
fileType: FileType.JS,
|
fileType: FileType.JS,
|
||||||
name: COMMON_CHUNK_NAME.FileMainContent,
|
name: COMMON_CHUNK_NAME.FileMainContent,
|
||||||
content: `
|
content: `
|
||||||
const i18nConfig = ${i18nStr};
|
import IntlMessageFormat from 'intl-messageformat';
|
||||||
let locale = 'en_US';
|
|
||||||
|
|
||||||
const changeLocale = (target) => {
|
const i18nConfig = ${i18nStr};
|
||||||
locale = target;
|
|
||||||
};
|
|
||||||
|
|
||||||
const i18n = key => i18nConfig && i18nConfig[locale] && i18nConfig[locale][key] || '';
|
let locale = 'en-US';
|
||||||
`,
|
|
||||||
linkAfter: [
|
|
||||||
COMMON_CHUNK_NAME.ExternalDepsImport,
|
|
||||||
COMMON_CHUNK_NAME.InternalDepsImport,
|
|
||||||
COMMON_CHUNK_NAME.FileVarDefine,
|
|
||||||
COMMON_CHUNK_NAME.FileUtilDefine,
|
|
||||||
],
|
|
||||||
});
|
|
||||||
|
|
||||||
next.chunks.push({
|
const getLocale = () => locale;
|
||||||
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,
|
|
||||||
],
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
const setLocale = (target) => {
|
||||||
|
locale = target;
|
||||||
|
};
|
||||||
|
|
||||||
|
const i18nFormat = ({ id, defaultMessage }, variables) => {
|
||||||
|
const msg = i18nConfig && i18nConfig[locale] && i18nConfig[locale][id] || defaultMessage;
|
||||||
|
if (msg == null) {
|
||||||
|
console.warn('[i18n]: unknown message id: %o (locale=%o)', id, locale);
|
||||||
|
return \`\${id}\`;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!variables || !variables.length) {
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new IntlMessageFormat(msg, locale).format(variables);
|
||||||
|
}
|
||||||
|
|
||||||
|
const i18n = id => {
|
||||||
|
return i18nFormat({ id });
|
||||||
|
};
|
||||||
|
`,
|
||||||
|
linkAfter: [
|
||||||
|
COMMON_CHUNK_NAME.ExternalDepsImport,
|
||||||
|
COMMON_CHUNK_NAME.InternalDepsImport,
|
||||||
|
COMMON_CHUNK_NAME.ImportAliasDefine,
|
||||||
|
COMMON_CHUNK_NAME.FileVarDefine,
|
||||||
|
COMMON_CHUNK_NAME.FileUtilDefine,
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
next.chunks.push({
|
||||||
|
type: ChunkType.STRING,
|
||||||
|
fileType: FileType.JS,
|
||||||
|
name: COMMON_CHUNK_NAME.FileExport,
|
||||||
|
content: `
|
||||||
|
export {
|
||||||
|
getLocale,
|
||||||
|
setLocale,
|
||||||
|
i18n,
|
||||||
|
i18nFormat,
|
||||||
|
};
|
||||||
|
`,
|
||||||
|
linkAfter: [
|
||||||
|
COMMON_CHUNK_NAME.ExternalDepsImport,
|
||||||
|
COMMON_CHUNK_NAME.InternalDepsImport,
|
||||||
|
COMMON_CHUNK_NAME.ImportAliasDefine,
|
||||||
|
COMMON_CHUNK_NAME.FileVarDefine,
|
||||||
|
COMMON_CHUNK_NAME.FileUtilDefine,
|
||||||
|
COMMON_CHUNK_NAME.FileMainContent,
|
||||||
|
],
|
||||||
|
});
|
||||||
return next;
|
return next;
|
||||||
};
|
};
|
||||||
return plugin;
|
return plugin;
|
||||||
|
|||||||
@ -28,24 +28,26 @@ const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
|
|||||||
linkAfter: [
|
linkAfter: [
|
||||||
COMMON_CHUNK_NAME.ExternalDepsImport,
|
COMMON_CHUNK_NAME.ExternalDepsImport,
|
||||||
COMMON_CHUNK_NAME.InternalDepsImport,
|
COMMON_CHUNK_NAME.InternalDepsImport,
|
||||||
|
COMMON_CHUNK_NAME.ImportAliasDefine,
|
||||||
COMMON_CHUNK_NAME.FileVarDefine,
|
COMMON_CHUNK_NAME.FileVarDefine,
|
||||||
COMMON_CHUNK_NAME.FileUtilDefine,
|
COMMON_CHUNK_NAME.FileUtilDefine,
|
||||||
COMMON_CHUNK_NAME.FileMainContent,
|
COMMON_CHUNK_NAME.FileMainContent,
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
ir.utils.forEach(util => {
|
ir.utils.forEach((util) => {
|
||||||
if (util.type === 'function') {
|
if (util.type === 'function') {
|
||||||
next.chunks.push({
|
next.chunks.push({
|
||||||
type: ChunkType.STRING,
|
type: ChunkType.STRING,
|
||||||
fileType: FileType.JS,
|
fileType: FileType.JS,
|
||||||
name: COMMON_CHUNK_NAME.FileVarDefine,
|
name: COMMON_CHUNK_NAME.FileVarDefine,
|
||||||
content: `
|
content: `
|
||||||
const ${util.name} = ${util.content};
|
const ${util.name} = ${util.content.value};
|
||||||
`,
|
`,
|
||||||
linkAfter: [
|
linkAfter: [
|
||||||
COMMON_CHUNK_NAME.ExternalDepsImport,
|
COMMON_CHUNK_NAME.ExternalDepsImport,
|
||||||
COMMON_CHUNK_NAME.InternalDepsImport,
|
COMMON_CHUNK_NAME.InternalDepsImport,
|
||||||
|
COMMON_CHUNK_NAME.ImportAliasDefine,
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -54,12 +56,11 @@ const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
|
|||||||
type: ChunkType.STRING,
|
type: ChunkType.STRING,
|
||||||
fileType: FileType.JS,
|
fileType: FileType.JS,
|
||||||
name: COMMON_CHUNK_NAME.FileExport,
|
name: COMMON_CHUNK_NAME.FileExport,
|
||||||
content: `
|
content: `${util.name},`,
|
||||||
${util.name},
|
|
||||||
`,
|
|
||||||
linkAfter: [
|
linkAfter: [
|
||||||
COMMON_CHUNK_NAME.ExternalDepsImport,
|
COMMON_CHUNK_NAME.ExternalDepsImport,
|
||||||
COMMON_CHUNK_NAME.InternalDepsImport,
|
COMMON_CHUNK_NAME.InternalDepsImport,
|
||||||
|
COMMON_CHUNK_NAME.ImportAliasDefine,
|
||||||
COMMON_CHUNK_NAME.FileVarDefine,
|
COMMON_CHUNK_NAME.FileVarDefine,
|
||||||
COMMON_CHUNK_NAME.FileUtilDefine,
|
COMMON_CHUNK_NAME.FileUtilDefine,
|
||||||
COMMON_CHUNK_NAME.FileMainContent,
|
COMMON_CHUNK_NAME.FileMainContent,
|
||||||
@ -77,6 +78,7 @@ const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
|
|||||||
linkAfter: [
|
linkAfter: [
|
||||||
COMMON_CHUNK_NAME.ExternalDepsImport,
|
COMMON_CHUNK_NAME.ExternalDepsImport,
|
||||||
COMMON_CHUNK_NAME.InternalDepsImport,
|
COMMON_CHUNK_NAME.InternalDepsImport,
|
||||||
|
COMMON_CHUNK_NAME.ImportAliasDefine,
|
||||||
COMMON_CHUNK_NAME.FileVarDefine,
|
COMMON_CHUNK_NAME.FileVarDefine,
|
||||||
COMMON_CHUNK_NAME.FileUtilDefine,
|
COMMON_CHUNK_NAME.FileUtilDefine,
|
||||||
COMMON_CHUNK_NAME.FileMainContent,
|
COMMON_CHUNK_NAME.FileMainContent,
|
||||||
|
|||||||
@ -21,6 +21,8 @@ const factory: PostProcessorFactory<ProcessorConfig> = (config?: ProcessorConfig
|
|||||||
parser = 'babel';
|
parser = 'babel';
|
||||||
} else if (fileType === 'ts' || fileType === 'tsx') {
|
} else if (fileType === 'ts' || fileType === 'tsx') {
|
||||||
parser = 'typescript';
|
parser = 'typescript';
|
||||||
|
} else if (fileType === 'json') {
|
||||||
|
parser = 'json';
|
||||||
} else if (PARSERS.indexOf(fileType) >= 0) {
|
} else if (PARSERS.indexOf(fileType) >= 0) {
|
||||||
parser = fileType as prettier.BuiltInParserName;
|
parser = fileType as prettier.BuiltInParserName;
|
||||||
} else if (cfg.customFileTypeParser[fileType]) {
|
} else if (cfg.customFileTypeParser[fileType]) {
|
||||||
|
|||||||
@ -1,16 +1,14 @@
|
|||||||
import {
|
import * as defaultFs from 'fs';
|
||||||
IResultDir,
|
|
||||||
PublisherFactory,
|
import { ResultDir } from '@ali/lowcode-types';
|
||||||
IPublisher,
|
import { PublisherFactory, IPublisher, IPublisherFactoryParams, PublisherError } from '../../types';
|
||||||
IPublisherFactoryParams,
|
import { writeFolder, IFileSystem } from './utils';
|
||||||
PublisherError,
|
|
||||||
} from '../../types';
|
|
||||||
import { writeFolder } from './utils';
|
|
||||||
|
|
||||||
export interface IDiskFactoryParams extends IPublisherFactoryParams {
|
export interface IDiskFactoryParams extends IPublisherFactoryParams {
|
||||||
outputPath?: string;
|
outputPath?: string;
|
||||||
projectSlug?: string;
|
projectSlug?: string;
|
||||||
createProjectFolder?: boolean;
|
createProjectFolder?: boolean;
|
||||||
|
fs?: IFileSystem;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IDiskPublisher extends IPublisher<IDiskFactoryParams, string> {
|
export interface IDiskPublisher extends IPublisher<IDiskFactoryParams, string> {
|
||||||
@ -18,19 +16,19 @@ export interface IDiskPublisher extends IPublisher<IDiskFactoryParams, string> {
|
|||||||
setOutputPath: (path: string) => void;
|
setOutputPath: (path: string) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const createDiskPublisher: PublisherFactory<
|
export const createDiskPublisher: PublisherFactory<IDiskFactoryParams, IDiskPublisher> = (
|
||||||
IDiskFactoryParams,
|
params: IDiskFactoryParams = {},
|
||||||
IDiskPublisher
|
): IDiskPublisher => {
|
||||||
> = (params: IDiskFactoryParams = {}): IDiskPublisher => {
|
|
||||||
let { project, outputPath = './' } = params;
|
let { project, outputPath = './' } = params;
|
||||||
|
const { fs = defaultFs } = params;
|
||||||
|
|
||||||
const getProject = (): IResultDir => {
|
const getProject = (): ResultDir => {
|
||||||
if (!project) {
|
if (!project) {
|
||||||
throw new PublisherError('Missing Project');
|
throw new PublisherError('Missing Project');
|
||||||
}
|
}
|
||||||
return project;
|
return project;
|
||||||
};
|
};
|
||||||
const setProject = (projectToSet: IResultDir): void => {
|
const setProject = (projectToSet: ResultDir): void => {
|
||||||
project = projectToSet;
|
project = projectToSet;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -49,19 +47,14 @@ IDiskPublisher
|
|||||||
|
|
||||||
const projectOutputPath = options.outputPath || outputPath;
|
const projectOutputPath = options.outputPath || outputPath;
|
||||||
const overrideProjectSlug = options.projectSlug || params.projectSlug;
|
const overrideProjectSlug = options.projectSlug || params.projectSlug;
|
||||||
const createProjectFolder =
|
const createProjectFolder = options.createProjectFolder || params.createProjectFolder;
|
||||||
options.createProjectFolder || params.createProjectFolder;
|
|
||||||
|
|
||||||
if (overrideProjectSlug) {
|
if (overrideProjectSlug) {
|
||||||
projectToPublish.name = overrideProjectSlug;
|
projectToPublish.name = overrideProjectSlug;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await writeFolder(
|
await writeFolder(projectToPublish, projectOutputPath, createProjectFolder, fs);
|
||||||
projectToPublish,
|
|
||||||
projectOutputPath,
|
|
||||||
createProjectFolder,
|
|
||||||
);
|
|
||||||
return { success: true, payload: projectOutputPath };
|
return { success: true, payload: projectOutputPath };
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw new PublisherError(error);
|
throw new PublisherError(error);
|
||||||
|
|||||||
@ -1,58 +1,53 @@
|
|||||||
import { existsSync, mkdir, writeFile } from 'fs';
|
import * as systemFs from 'fs';
|
||||||
import { join } from 'path';
|
import { join } from 'path';
|
||||||
|
import { ResultDir, ResultFile } from '@ali/lowcode-types';
|
||||||
|
|
||||||
import { IResultDir, IResultFile } from '../../types';
|
export interface IFileSystem {
|
||||||
|
existsSync: typeof systemFs.existsSync;
|
||||||
|
mkdir: typeof systemFs.mkdir;
|
||||||
|
writeFile: typeof systemFs.writeFile;
|
||||||
|
}
|
||||||
|
|
||||||
export const writeFolder = async (
|
export const writeFolder = async (
|
||||||
folder: IResultDir,
|
folder: ResultDir,
|
||||||
currentPath: string,
|
currentPath: string,
|
||||||
createProjectFolder = true,
|
createProjectFolder = true,
|
||||||
|
fs: IFileSystem = systemFs,
|
||||||
): Promise<void> => {
|
): Promise<void> => {
|
||||||
const { name, files, dirs } = folder;
|
const { name, files, dirs } = folder;
|
||||||
|
|
||||||
const folderPath = createProjectFolder
|
const folderPath = createProjectFolder ? join(currentPath, name) : currentPath;
|
||||||
? join(currentPath, name)
|
|
||||||
: currentPath;
|
|
||||||
|
|
||||||
if (!existsSync(folderPath)) {
|
if (!fs.existsSync(folderPath)) {
|
||||||
await createDirectory(folderPath);
|
await createDirectory(folderPath, fs);
|
||||||
}
|
}
|
||||||
|
|
||||||
const promises = [
|
const promises = [writeFilesToFolder(folderPath, files, fs), writeSubFoldersToFolder(folderPath, dirs, fs)];
|
||||||
writeFilesToFolder(folderPath, files),
|
|
||||||
writeSubFoldersToFolder(folderPath, dirs),
|
|
||||||
];
|
|
||||||
|
|
||||||
await Promise.all(promises);
|
await Promise.all(promises);
|
||||||
};
|
};
|
||||||
|
|
||||||
const writeFilesToFolder = async (
|
const writeFilesToFolder = async (folderPath: string, files: ResultFile[], fs: IFileSystem): Promise<void> => {
|
||||||
folderPath: string,
|
const promises = files.map((file) => {
|
||||||
files: IResultFile[],
|
|
||||||
): Promise<void> => {
|
|
||||||
const promises = files.map(file => {
|
|
||||||
const fileName = file.ext ? `${file.name}.${file.ext}` : file.name;
|
const fileName = file.ext ? `${file.name}.${file.ext}` : file.name;
|
||||||
const filePath = join(folderPath, fileName);
|
const filePath = join(folderPath, fileName);
|
||||||
return writeContentToFile(filePath, file.content);
|
return writeContentToFile(filePath, file.content, 'utf8', fs);
|
||||||
});
|
});
|
||||||
|
|
||||||
await Promise.all(promises);
|
await Promise.all(promises);
|
||||||
};
|
};
|
||||||
|
|
||||||
const writeSubFoldersToFolder = async (
|
const writeSubFoldersToFolder = async (folderPath: string, subFolders: ResultDir[]): Promise<void> => {
|
||||||
folderPath: string,
|
const promises = subFolders.map((subFolder) => {
|
||||||
subFolders: IResultDir[],
|
|
||||||
): Promise<void> => {
|
|
||||||
const promises = subFolders.map(subFolder => {
|
|
||||||
return writeFolder(subFolder, folderPath);
|
return writeFolder(subFolder, folderPath);
|
||||||
});
|
});
|
||||||
|
|
||||||
await Promise.all(promises);
|
await Promise.all(promises);
|
||||||
};
|
};
|
||||||
|
|
||||||
const createDirectory = (pathToDir: string): Promise<void> => {
|
const createDirectory = (pathToDir: string, fs: IFileSystem): Promise<void> => {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
mkdir(pathToDir, { recursive: true }, err => {
|
fs.mkdir(pathToDir, { recursive: true }, (err) => {
|
||||||
err ? reject(err) : resolve();
|
err ? reject(err) : resolve();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -62,9 +57,10 @@ const writeContentToFile = (
|
|||||||
filePath: string,
|
filePath: string,
|
||||||
fileContent: string,
|
fileContent: string,
|
||||||
encoding = 'utf8',
|
encoding = 'utf8',
|
||||||
|
fs: IFileSystem,
|
||||||
): Promise<void> => {
|
): Promise<void> => {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
writeFile(filePath, fileContent, encoding, err => {
|
fs.writeFile(filePath, fileContent, encoding, (err) => {
|
||||||
err ? reject(err) : resolve();
|
err ? reject(err) : resolve();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -1,10 +1,5 @@
|
|||||||
import {
|
import { ResultDir } from '@ali/lowcode-types';
|
||||||
IResultDir,
|
import { PublisherFactory, IPublisher, IPublisherFactoryParams, PublisherError } from '../../types';
|
||||||
PublisherFactory,
|
|
||||||
IPublisher,
|
|
||||||
IPublisherFactoryParams,
|
|
||||||
PublisherError,
|
|
||||||
} from '../../types';
|
|
||||||
import { isNodeProcess, writeZipToDisk, generateProjectZip } from './utils';
|
import { isNodeProcess, writeZipToDisk, generateProjectZip } from './utils';
|
||||||
|
|
||||||
// export type ZipBuffer = Buffer | Blob;
|
// export type ZipBuffer = Buffer | Blob;
|
||||||
@ -28,7 +23,7 @@ export const createZipPublisher: PublisherFactory<ZipFactoryParams, ZipPublisher
|
|||||||
let { project, outputPath } = params;
|
let { project, outputPath } = params;
|
||||||
|
|
||||||
const getProject = () => project;
|
const getProject = () => project;
|
||||||
const setProject = (projectToSet: IResultDir) => {
|
const setProject = (projectToSet: ResultDir) => {
|
||||||
project = projectToSet;
|
project = projectToSet;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -1,21 +1,17 @@
|
|||||||
import JSZip from 'jszip';
|
import JSZip from 'jszip';
|
||||||
import { IResultDir, IResultFile } from '../../types';
|
import { ResultDir, ResultFile } from '@ali/lowcode-types';
|
||||||
import { ZipBuffer } from './index';
|
import { ZipBuffer } from './index';
|
||||||
|
|
||||||
export const isNodeProcess = (): boolean => {
|
export const isNodeProcess = (): boolean => {
|
||||||
return (
|
return (
|
||||||
typeof process === 'object' &&
|
typeof process === 'object' && typeof process.versions === 'object' && typeof process.versions.node !== 'undefined'
|
||||||
typeof process.versions === 'object' &&
|
|
||||||
typeof process.versions.node !== 'undefined'
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const writeZipToDisk = (
|
export const writeZipToDisk = (zipFolderPath: string, content: ZipBuffer, zipName: string): void => {
|
||||||
zipFolderPath: string,
|
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||||
content: ZipBuffer,
|
|
||||||
zipName: string,
|
|
||||||
): void => {
|
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
|
|
||||||
if (!fs.existsSync(zipFolderPath)) {
|
if (!fs.existsSync(zipFolderPath)) {
|
||||||
@ -29,7 +25,7 @@ export const writeZipToDisk = (
|
|||||||
writeStream.end();
|
writeStream.end();
|
||||||
};
|
};
|
||||||
|
|
||||||
export const generateProjectZip = async (project: IResultDir): Promise<ZipBuffer> => {
|
export const generateProjectZip = async (project: ResultDir): Promise<ZipBuffer> => {
|
||||||
let zip = new JSZip();
|
let zip = new JSZip();
|
||||||
zip = writeFolderToZip(project, zip, true);
|
zip = writeFolderToZip(project, zip, true);
|
||||||
// const zipType = isNodeProcess() ? 'nodebuffer' : 'blob';
|
// const zipType = isNodeProcess() ? 'nodebuffer' : 'blob';
|
||||||
@ -37,21 +33,17 @@ export const generateProjectZip = async (project: IResultDir): Promise<ZipBuffer
|
|||||||
return zip.generateAsync({ type: zipType });
|
return zip.generateAsync({ type: zipType });
|
||||||
};
|
};
|
||||||
|
|
||||||
const writeFolderToZip = (
|
const writeFolderToZip = (folder: ResultDir, parentFolder: JSZip, ignoreFolder = false) => {
|
||||||
folder: IResultDir,
|
|
||||||
parentFolder: JSZip,
|
|
||||||
ignoreFolder = false,
|
|
||||||
) => {
|
|
||||||
const zipFolder = ignoreFolder ? parentFolder : parentFolder.folder(folder.name);
|
const zipFolder = ignoreFolder ? parentFolder : parentFolder.folder(folder.name);
|
||||||
if (zipFolder !== null) {
|
if (zipFolder !== null) {
|
||||||
folder.files.forEach((file: IResultFile) => {
|
folder.files.forEach((file: ResultFile) => {
|
||||||
// const options = file.contentEncoding === 'base64' ? { base64: true } : {};
|
// const options = file.contentEncoding === 'base64' ? { base64: true } : {};
|
||||||
const options = {};
|
const options = {};
|
||||||
const fileName = file.ext ? `${file.name}.${file.ext}` : file.name;
|
const fileName = file.ext ? `${file.name}.${file.ext}` : file.name;
|
||||||
zipFolder.file(fileName, file.content, options);
|
zipFolder.file(fileName, file.content, options);
|
||||||
});
|
});
|
||||||
|
|
||||||
folder.dirs.forEach((subFolder: IResultDir) => {
|
folder.dirs.forEach((subFolder: ResultDir) => {
|
||||||
writeFolderToZip(subFolder, zipFolder);
|
writeFolderToZip(subFolder, zipFolder);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user