Merge branch 'master' into polyfill/vision

This commit is contained in:
kangwei 2020-04-01 17:07:57 +08:00
commit eb5f0871bb
1127 changed files with 105619 additions and 9294 deletions

1
.gitignore vendored
View File

@ -7,6 +7,7 @@ packages/*/dist/
package-lock.json
yarn.lock
deploy-space/packages
deploy-space/.env
# IDE

View File

@ -11,11 +11,12 @@
#### 跑起来:
- `npm run setup`
- `npm start`
#### 开发提交:
- `git add <your-files>`
- `npm run commit`
- `npm run commit` # 在根目录
## 发布

View File

@ -4,7 +4,7 @@
<meta charset="utf-8" />
<meta http-equiv="x-ua-compatible" content="ie=edge,chrome=1" />
<meta name="viewport" content="width=device-width" />
<title>LowCodeEngine DEMO</title>
<title>LowCodeEngine Editor DEMO</title>
<link rel="shortcut icon" href="./favicon.png" />
<script src="https://g.alicdn.com/code/lib/react/16.9.0/umd/react.development.js"></script>
<script src="https://g.alicdn.com/code/lib/react-dom/16.9.0/umd/react-dom.development.js"></script>
@ -16,7 +16,7 @@
<!-- lowcode engine globals -->
<link rel="stylesheet" href="./globals.css" />
<!-- lowcode engine app -->
<link rel="stylesheet" href="./lowcode-demo.css" />
<link rel="stylesheet" href="./lowcode-editor.css" />
</head>
<body>
@ -24,6 +24,6 @@
<!-- lowcode engine globals -->
<script src="./globals.js"></script>
<!-- lowcode engine app -->
<script src="./lowcode-demo.js"></script>
<script src="./lowcode-editor.js"></script>
</body>
</html>

View File

@ -4,7 +4,8 @@
<meta charset="utf-8" />
<meta http-equiv="x-ua-compatible" content="ie=edge,chrome=1" />
<meta name="viewport" content="width=device-width" />
<title>LowCodeEngine DEMO</title>
<title>LowCodeEngine Preview DEMO</title>
<link rel="shortcut icon" href="./favicon.png" />
<script src="https://g.alicdn.com/code/lib/react/16.9.0/umd/react.development.js"></script>
<script src="https://g.alicdn.com/code/lib/react-dom/16.9.0/umd/react-dom.development.js"></script>
<script src="https://g.alicdn.com/code/lib/prop-types/15.7.2/prop-types.js"></script>
@ -13,9 +14,10 @@
<link rel="stylesheet" href="https://alifd.alicdn.com/npm/@alifd/next/1.11.6/next.min.css">
<script src="https://unpkg.alibaba-inc.com/@alifd/next@1.18.17/dist/next.min.js"></script>
<link rel="stylesheet" href="./lowcode-preview.css" />
</head>
<body>
<div id="lce-container"></div>
<script src="./lowcode-preview.js"></script>
</body>
</html>

View File

@ -1,9 +1,5 @@
{
"private": true,
"dependencies": {
"tslib": "^1.9.3",
"typescript": "^3.2.2"
},
"workspaces": {
"packages": [
"packages/*"
@ -13,5 +9,8 @@
"**/@alife/theme-lowcode-*"
]
},
"engines" : { "node" : "^10" }
"dependencies": {
"tslib": "^1.11.1",
"typescript": "^3.8.3"
}
}

View File

@ -5,7 +5,7 @@
// Target latest version of ECMAScript.
"target": "esnext",
// Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'.
"module": "commonjs",
"module": "esnext",
// Search under node_modules for non-relative imports.
"moduleResolution": "node",
// Process & infer types from .js files.
@ -34,6 +34,7 @@
"resolveJsonModule": true,
// skip type checking of declaration files
"skipLibCheck": true,
"outDir": "lib"
},
"exclude": ["**/test", "**/lib", "**/es", "node_modules"]
}

View File

@ -10,7 +10,7 @@
- 使用 `camelCase` 为属性或本地变量命名
- 不要为私有属性名添加 `_` 前缀
- 尽可能使用完整的单词拼写命名
- 文件夹命名统一使用小写
- 文件夹/文件命名统一使用小写 `get-custom-data.ts`
### 组件

View File

@ -1,7 +1,7 @@
{
"lerna": "2.11.0",
"version": "independent",
"npmClient": "yarn",
"npmClient": "tyarn",
"registry": "http://registry.npm.alibaba-inc.com",
"useWorkspaces": true,
"packages": [

View File

@ -1,14 +1,34 @@
{
"private": true,
"workspaces": {
"packages": [
"packages/*"
],
"nohoist": [
"**/css-modules-typescript-loader",
"**/@alife/theme-lowcode-*"
]
},
"scripts": {
"build": "lerna run build --stream",
"clean": "rm -rf ./packages/*/lib ./packages/*/es ./packages/*/dist ./packages/*/build",
"commit": "git-cz",
"pub": "lerna publish",
"setup": "./scripts/setup.sh",
"start": "./scripts/start.sh",
"build": "lerna run build",
"test": "lerna run test",
"test:snapshot": "lerna run test:snapshot",
"pub": "lerna publish",
"commit": "git-cz"
"test": "lerna run test --stream",
"test:snapshot": "lerna run test:snapshot"
},
"lint-staged": {
"*.{tsx,ts}": [
"eslint --quiet",
"git add"
]
},
"config": {
"commitizen": {
"path": "node_modules/cz-conventional-changelog"
}
},
"devDependencies": {
"@ali/lowcode-config": "^2.0.5",
@ -26,25 +46,7 @@
"tslib": "^1.9.3",
"typescript": "^3.2.2"
},
"engines" : { "node" : "^10" },
"workspaces": {
"packages": [
"packages/*"
],
"nohoist": [
"**/css-modules-typescript-loader",
"**/@alife/theme-lowcode-*"
]
},
"lint-staged": {
"*.{tsx,ts}": [
"eslint --quiet",
"git add"
]
},
"config": {
"commitizen": {
"path": "node_modules/cz-conventional-changelog"
}
"engines": {
"node": ">=10.0.0"
}
}

View File

@ -0,0 +1,52 @@
# Change Log
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
<a name="0.8.4"></a>
## [0.8.4](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-code-generator@0.8.3...@ali/lowcode-code-generator@0.8.4) (2020-03-30)
**Note:** Version bump only for package @ali/lowcode-code-generator
<a name="0.8.3"></a>
## [0.8.3](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-code-generator@0.8.2...@ali/lowcode-code-generator@0.8.3) (2020-03-30)
**Note:** Version bump only for package @ali/lowcode-code-generator
<a name="0.8.2"></a>
## 0.8.2 (2020-03-30)
### Features
* code generator main process ([021d6e0](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/021d6e0))
* demo schema & complex children type ([a5ee6bd](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/a5ee6bd))
* fix gaps ([32af3d3](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/32af3d3))
* project builder fix & publish demo to disk ([26983b3](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/26983b3))
<a name="0.8.1"></a>
## 0.8.1 (2020-03-30)
### Features
<<<<<<< HEAD
* code generator main process ([021d6e0](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/021d6e0))
* demo schema & complex children type ([a5ee6bd](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/a5ee6bd))
* fix gaps ([32af3d3](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/32af3d3))
* project builder fix & publish demo to disk ([26983b3](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/26983b3))
=======
* code generator main process ([021d6e0](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/021d6e0fe9fb29a8b6c1c5d5f4d06ec71896faa5))
* demo schema & complex children type ([a5ee6bd](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/a5ee6bd55806fc9aea695096ccd4c7f50b8e31c4))
* fix gaps ([32af3d3](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/32af3d3a3ca4d5aca15be25e05c840c8ea0cb6ae))
* project builder fix & publish demo to disk ([26983b3](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/26983b38c2b0f1d39d79964eb54d8ce60250dd82))
>>>>>>> df955e1db90ff104cd11160def80113cfd6faccc

View File

@ -1,27 +1,34 @@
{
"name": "@ali/lowcode-engine-code-generator",
"version": "0.8.0",
"name": "@ali/lowcode-code-generator",
"version": "0.8.4",
"description": "出码引擎 for LowCode Engine",
"main": "lib/index.js",
"files": [
"lib"
],
"scripts": {
"build": "rimraf lib && tsc",
"compile": "rimraf lib && tsc",
"build": "rimraf lib && webpack",
"demo": "ts-node -r tsconfig-paths/register ./src/demo/main.ts",
"test": "ava"
},
"dependencies": {
"@ali/am-eslint-config": "*",
"@types/prettier": "^1.19.1",
"change-case": "^3.1.0",
"prettier": "^2.0.2",
"short-uuid": "^3.1.1"
},
"devDependencies": {
"ava": "^1.0.1",
"rimraf": "^3.0.2",
"ts-loader": "^6.2.2",
"ts-node": "^7.0.1",
"tsconfig-paths": "^3.9.0",
"typescript": "^3.8.3"
"tsconfig-paths-webpack-plugin": "^3.2.0",
"webpack": "^4.42.1",
"webpack-cli": "^3.3.11",
"webpack-node-externals": "^1.7.2"
},
"ava": {
"compileEnhancements": false,

View File

@ -5,6 +5,7 @@ import {
ICompiledModule,
IModuleBuilder,
IResultFile,
PostProcessor,
} from '../types';
import { COMMON_SUB_MODULE_NAME } from '../const/generator';
@ -17,9 +18,11 @@ import ResultFile from '../model/ResultFile';
export function createModuleBuilder(
options: {
plugins: BuilderComponentPlugin[];
postProcessors: PostProcessor[];
mainFileName?: string;
} = {
plugins: [],
postProcessors: [],
},
): IModuleBuilder {
const chunkGenerator = new ChunkBuilder(options.plugins);
@ -33,7 +36,7 @@ export function createModuleBuilder(
);
}
const files: IResultFile[] = [];
let files: IResultFile[] = [];
const { chunks } = await chunkGenerator.run(input);
chunks.forEach(fileChunkList => {
@ -46,6 +49,18 @@ export function createModuleBuilder(
files.push(file);
});
if (options.postProcessors.length > 0) {
files = files.map(file => {
let content = file.content;
const type = file.ext;
options.postProcessors.forEach(processer => {
content = processer(content, type);
});
return new ResultFile(file.name, type, content);
});
}
return {
files,
};

View File

@ -8,10 +8,11 @@ import {
IResultDir,
IResultFile,
ISchemaParser,
PostProcessor,
} from '../types';
import ResultDir from '@/model/ResultDir';
import SchemaParser from '@/parse/SchemaParser';
import SchemaParser from '@/parser/SchemaParser';
import { createModuleBuilder } from '@/generator/ModuleBuilder';
@ -40,16 +41,20 @@ function getDirFromRoot(root: IResultDir, path: string[]): IResultDir {
export class ProjectBuilder implements IProjectBuilder {
private template: IProjectTemplate;
private plugins: IProjectPlugins;
private postProcessors: PostProcessor[];
constructor({
template,
plugins,
postProcessors,
}: {
template: IProjectTemplate;
plugins: IProjectPlugins;
postProcessors: PostProcessor[];
}) {
this.template = template;
this.plugins = plugins;
this.postProcessors = postProcessors;
}
public async generateProject(schema: IProjectSchema): Promise<IResultDir> {
@ -212,45 +217,57 @@ export class ProjectBuilder implements IProjectBuilder {
builders.components = createModuleBuilder({
plugins: this.plugins.components,
postProcessors: this.postProcessors,
});
builders.pages = createModuleBuilder({
plugins: this.plugins.pages,
postProcessors: this.postProcessors,
});
builders.pages = createModuleBuilder({ plugins: this.plugins.pages });
builders.router = createModuleBuilder({
plugins: this.plugins.router,
mainFileName: this.template.slots.router.fileName,
postProcessors: this.postProcessors,
});
builders.entry = createModuleBuilder({
plugins: this.plugins.entry,
mainFileName: this.template.slots.entry.fileName,
postProcessors: this.postProcessors,
});
builders.globalStyle = createModuleBuilder({
plugins: this.plugins.globalStyle,
mainFileName: this.template.slots.globalStyle.fileName,
postProcessors: this.postProcessors,
});
builders.htmlEntry = createModuleBuilder({
plugins: this.plugins.htmlEntry,
mainFileName: this.template.slots.htmlEntry.fileName,
postProcessors: this.postProcessors,
});
builders.packageJSON = createModuleBuilder({
plugins: this.plugins.packageJSON,
mainFileName: this.template.slots.packageJSON.fileName,
postProcessors: this.postProcessors,
});
if (this.template.slots.constants && this.plugins.constants) {
builders.constants = createModuleBuilder({
plugins: this.plugins.constants,
mainFileName: this.template.slots.constants.fileName,
postProcessors: this.postProcessors,
});
}
if (this.template.slots.utils && this.plugins.utils) {
builders.utils = createModuleBuilder({
plugins: this.plugins.utils,
mainFileName: this.template.slots.utils.fileName,
postProcessors: this.postProcessors,
});
}
if (this.template.slots.i18n && this.plugins.i18n) {
builders.i18n = createModuleBuilder({
plugins: this.plugins.i18n,
mainFileName: this.template.slots.i18n.fileName,
postProcessors: this.postProcessors,
});
}
@ -261,12 +278,15 @@ export class ProjectBuilder implements IProjectBuilder {
export function createProjectBuilder({
template,
plugins,
postProcessors,
}: {
template: IProjectTemplate;
plugins: IProjectPlugins;
postProcessors: PostProcessor[];
}): IProjectBuilder {
return new ProjectBuilder({
template,
plugins,
postProcessors,
});
}

View File

@ -3,6 +3,7 @@
*
*/
import { createProjectBuilder } from '@/generator/ProjectBuilder';
import { createDiskPublisher } from '@/publisher/disk';
import createIceJsProjectBuilder from '@/solutions/icejs';
export * from './types';
@ -12,4 +13,7 @@ export default {
solutions: {
icejs: createIceJsProjectBuilder,
},
publishers: {
disk: createDiskPublisher,
},
};

View File

@ -0,0 +1,3 @@
import prettier from './prettier';
export { prettier };

View File

@ -0,0 +1,22 @@
import prettier from 'prettier';
import { PostProcessor } from '@/types';
const PARSERS = ['css', 'scss', 'less', 'json', 'html', 'vue'];
const codePrettier: PostProcessor = (content: string, fileType: string) => {
let parser: prettier.BuiltInParserName;
if (fileType === 'js' || fileType === 'jsx') {
parser = 'babel';
} else if (PARSERS.indexOf(fileType) >= 0) {
parser = fileType as prettier.BuiltInParserName;
} else {
return content;
}
return prettier.format(content, {
parser,
});
};
export default codePrettier;

View File

@ -21,6 +21,8 @@ import template from '@/plugins/project/framework/icejs/template';
import i18n from '@/plugins/project/i18n';
import utils from '@/plugins/project/utils';
import { prettier } from '@/postprocessor';
export default function createIceJsProjectBuilder(): IProjectBuilder {
return createProjectBuilder({
template,
@ -56,5 +58,6 @@ export default function createIceJsProjectBuilder(): IProjectBuilder {
htmlEntry: [iceJsEntryHtml],
packageJSON: [iceJsPackageJSON],
},
postProcessors: [prettier],
});
}

View File

@ -141,3 +141,5 @@ export interface IProjectPlugins {
export interface IProjectBuilder {
generateProject(schema: IProjectSchema): Promise<IResultDir>;
}
export type PostProcessor = (content: string, fileType: string) => string;

View File

@ -1,14 +1,17 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"target": "es6",
"module": "commonjs",
"outDir": "lib",
"target": "es5",
"strictNullChecks": true,
"inlineSources": false,
"lib": ["es6"],
"downlevelIteration": true,
"paths": {
"@/*": ["./src/*"]
},
"outDir": "./lib",
"types": ["node"],
"baseUrl": ".", /* Base directory to resolve non-absolute module names. */
"baseUrl": "." /* Base directory to resolve non-absolute module names. */
},
"include": [
"src/**/*"

View File

@ -0,0 +1,31 @@
const path = require('path');
const nodeExternals = require('webpack-node-externals');
const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin');
module.exports = {
mode: 'production',
target: 'node',
entry: {
index: './src/index.ts',
// demo: './src/demo/main.ts',
},
module: {
rules: [
{
test: /\.tsx?$/,
use: 'ts-loader',
exclude: /node_modules/,
},
],
},
resolve: {
extensions: [ '.tsx', '.ts', '.js' ],
plugins: [new TsconfigPathsPlugin({/* options: see below */})],
},
output: {
// filename: 'bundle.js',
filename: '[name].js',
path: path.resolve(__dirname, 'lib'),
},
externals: [nodeExternals()], // in order to ignore all modules in node_modules folder
};

View File

@ -0,0 +1,81 @@
# Change Log
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
<a name="0.8.8"></a>
## [0.8.8](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-demo@0.8.7...@ali/lowcode-demo@0.8.8) (2020-03-31)
**Note:** Version bump only for package @ali/lowcode-demo
<a name="0.8.7"></a>
## [0.8.7](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-demo@0.8.6...@ali/lowcode-demo@0.8.7) (2020-03-30)
**Note:** Version bump only for package @ali/lowcode-demo
<a name="0.8.6"></a>
## [0.8.6](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-demo@0.8.5...@ali/lowcode-demo@0.8.6) (2020-03-30)
**Note:** Version bump only for package @ali/lowcode-demo
<a name="0.8.5"></a>
## [0.8.5](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-demo@0.8.4...@ali/lowcode-demo@0.8.5) (2020-03-30)
### Bug Fixes
* depend ([c90996d](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/c90996d))
<a name="0.8.4"></a>
## [0.8.4](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-demo@0.8.3...@ali/lowcode-demo@0.8.4) (2020-03-30)
**Note:** Version bump only for package @ali/lowcode-demo
<a name="0.8.3"></a>
## [0.8.3](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-demo@0.8.2...@ali/lowcode-demo@0.8.3) (2020-03-30)
**Note:** Version bump only for package @ali/lowcode-demo
<a name="0.8.2"></a>
## 0.8.2 (2020-03-30)
### Features
* complet preview ([56c16ff](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/56c16ff))
* double outline & ZH_EN support ([b379bd7](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/b379bd7))
<a name="0.8.1"></a>
## 0.8.1 (2020-03-30)
### Features
<<<<<<< HEAD
* complet preview ([56c16ff](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/56c16ff))
* double outline & ZH_EN support ([b379bd7](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/b379bd7))
=======
* complet preview ([56c16ff](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/56c16ffa5c39c2d01abd9cfa90fea49a4539da1d))
* double outline & ZH_EN support ([b379bd7](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/b379bd7c0c488ef24f825760750a13d3fa083c96))
>>>>>>> df955e1db90ff104cd11160def80113cfd6faccc

View File

@ -1,7 +1,8 @@
{
"entry": {
"index": "src/index.jsx",
"react-simulator-renderer": "../react-simulator-renderer/src/index.js"
"index": "src/index.ts",
"react-simulator-renderer": "../react-simulator-renderer/src/index.ts",
"preview": "src/preview.ts"
},
"vendor": false,
"devServer": {
@ -15,7 +16,9 @@
"@alifd/next": "window.Next"
},
"plugins": [
["build-plugin-react-app"],
[
"build-plugin-react-app"
],
[
"build-plugin-fusion",
{
@ -25,9 +28,11 @@
[
"build-plugin-moment-locales",
{
"locales": ["zh-cn"]
"locales": [
"zh-cn"
]
}
],
"./build.plugin.js"
]
}
}

View File

@ -1,6 +1,7 @@
{
"entry": {
"lowcode-demo": "src/index.jsx"
"lowcode-editor": "src/index.ts",
"lowcode-preview": "src/preview.ts"
},
"vendor": false,
"externals": {

View File

@ -1,28 +1,39 @@
{
"name": "@ali/lowcode-demo",
"version": "0.8.0",
"version": "0.8.8",
"private": true,
"description": "低代码引擎 DEMO",
"scripts": {
"start": "build-scripts start",
"cloud-build": "build-scripts build --config cloud-build.json"
"cloud-build": "build-scripts build --config cloud-build.json",
"gen": "npm run genSkeleton && tyarn",
"genSkeleton": "iceluna gen lowcode -c ./skeleton.config.js -t ./src/editor/config",
"start": "build-scripts start"
},
"config": {},
"dependencies": {
"@ali/lowcode-editor-core": "^0.8",
"@ali/lowcode-editor-core": "^0.8.4",
"@ali/lowcode-editor-skeleton": "^0.8.0",
"@ali/lowcode-plugin-designer": "^0.8.0",
"@ali/lowcode-setters": "^0.8.0",
"@ali/lowcode-plugin-components-pane": "^0.8.0",
"@ali/lowcode-plugin-settings-pane": "^0.8.0",
"@ali/lowcode-plugin-outline-pane": "^0.8.0",
"@ali/lowcode-plugin-undo-redo": "^0.8.0",
"@ali/lowcode-plugin-designer": "^0.9.1",
"@ali/lowcode-plugin-event-bind-dialog": "^0.8.0",
"@ali/lowcode-plugin-outline-pane": "^0.8.7",
"@ali/lowcode-plugin-sample-logo": "^0.8.0",
"@ali/lowcode-plugin-sample-preview": "^0.8.0",
"@ali/lowcode-plugin-sample-preview": "^0.8.6",
"@ali/lowcode-plugin-settings-pane": "^0.8.8",
"@ali/lowcode-plugin-undo-redo": "^0.8.0",
"@ali/lowcode-plugin-variable-bind-dialog": "^0.8.2",
"@ali/lowcode-plugin-zh-en": "^0.8.6",
"@ali/lowcode-react-renderer": "^0.8.4",
"@ali/lowcode-runtime": "^0.8.7",
"@ali/lowcode-setters": "^0.8.6",
"@alifd/next": "^1.19.12",
"@alife/theme-lowcode-dark": "^0.1.0",
"@alife/theme-lowcode-light": "^0.1.0",
"react": "^16.8.1",
"react-dom": "^16.8.1"
},
"devDependencies": {
"@ali/iceluna-cli": "^0.0.16",
"@alib/build-scripts": "^0.1.18",
"@types/events": "^3.0.0",
"@types/react": "^16.8.3",

View File

@ -0,0 +1,21 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="x-ua-compatible" content="ie=edge,chrome=1" />
<meta name="viewport" content="width=device-width" />
<title>LowCodeEngine DEMO</title>
<script src="https://g.alicdn.com/code/lib/react/16.9.0/umd/react.development.js"></script>
<script src="https://g.alicdn.com/code/lib/react-dom/16.9.0/umd/react-dom.development.js"></script>
<script src="https://g.alicdn.com/code/lib/prop-types/15.7.2/prop-types.js"></script>
<script> React.PropTypes = PropTypes; </script>
<script src="https://g.alicdn.com/mylib/moment/2.24.0/min/moment.min.js"></script>
<link rel="stylesheet" href="https://alifd.alicdn.com/npm/@alifd/next/1.11.6/next.min.css">
<script src="https://unpkg.alibaba-inc.com/@alifd/next@1.18.17/dist/next.min.js"></script>
</head>
<body>
<div id="lce-container"></div>
</body>
</html>

View File

@ -1,5 +1,10 @@
export default {
version: '^1.0.2',
module.exports = {
skeleton: {
config: {
package: '@ali/lowcode-editor-skeleton',
version: '^0.8.0'
}
},
theme: {
fusion: {
package: '@alife/theme-lowcode-light',
@ -22,7 +27,7 @@ export default {
},
config: {
package: '@ali/lowcode-plugin-sample-logo',
version: '1.0.0'
version: '^0.8.0'
},
pluginProps: {
logo: 'https://img.alicdn.com/tfs/TB1hoI9x1H2gK0jSZFEXXcqMpXa-146-40.png',
@ -38,7 +43,7 @@ export default {
},
config: {
package: '@ali/lowcode-plugin-undo-redo',
version: '1.0.0'
version: '^0.8.0'
}
},
{
@ -57,7 +62,7 @@ export default {
},
config: {
package: '@ali/lowcode-plugin-sample-preview',
version: '1.0.0'
version: '^0.8.0'
}
}
],
@ -68,14 +73,14 @@ export default {
props: {
align: 'top',
icon: 'zujianku',
title: '组件库'
title: '组件库',
floatable: true,
},
config: {
package: '@ali/iceluna-plugin-components-pane',
version: '0.0.1'
package: '@ali/lowcode-plugin-components-pane',
version: '^0.8.0'
},
pluginProps: {
disableAppComponent: true
}
},
{
@ -83,12 +88,24 @@ export default {
type: 'PanelIcon',
props: {
align: 'top',
icon: 'dengpao',
icon: 'shuxingkongjian',
title: '大纲树'
},
config: {
package: '@ali/lowcode-plugin-outline-pane',
version: '^1.0.0'
version: '^0.8.0'
},
pluginProps: {}
},
{
pluginKey: 'zhEn',
type: 'Custom',
props: {
align: 'bottom',
},
config: {
package: '@ali/lowcode-plugin-zh-en',
version: '^0.8.0'
},
pluginProps: {}
}
@ -100,7 +117,7 @@ export default {
props: {},
config: {
package: '@ali/lowcode-plugin-settings-pane',
version: '^1.0.0'
version: '^0.8.0'
},
pluginProps: {}
}
@ -110,7 +127,14 @@ export default {
pluginKey: 'designer',
config: {
package: '@ali/lowcode-plugin-designer',
version: '1.0.0'
version: '^0.8.0'
}
},
{
pluginKey: 'eventBindDialog',
config: {
package: '@ali/lowcode-plugin-event-bind-dialog',
version: '^0.8.0'
}
}
]

View File

@ -0,0 +1,21 @@
export default {
sdkVersion: '1.0.3',
history: 'hash', // 浏览器路由brower 哈希路由hash
containerId: 'lce-container',
layout: {
componentName: 'BasicLayout',
props: {
name: '低代码引擎预览 demo',
logo: {
src: 'https://img.alicdn.com/tfs/TB1L.1QAeL2gK0jSZFmXXc7iXXa-90-90.png',
width: 25,
height: 25,
},
},
},
theme: {
package: '@alife/theme-fusion',
version: '^0.1.0',
},
compDependencies: [],
};

View File

@ -0,0 +1,5 @@
/**
*
*/
export default {};

View File

@ -0,0 +1,53 @@
export default {
Button: {
package: '@alifd/next',
version: '1.19.18',
destructuring: true,
exportName: 'Button',
},
'Button.Group': {
package: '@alifd/next',
version: '1.19.18',
destructuring: true,
exportName: 'Button',
subName: 'Group',
},
Input: {
package: '@alifd/next',
version: '1.19.18',
destructuring: true,
exportName: 'Input',
},
Form: {
package: '@alifd/next',
version: '1.19.18',
destructuring: true,
exportName: 'Form',
},
'Form.Item': {
package: '@alifd/next',
version: '1.19.18',
destructuring: true,
exportName: 'Form',
subName: 'Item',
},
NumberPicker: {
package: '@alifd/next',
version: '1.19.18',
destructuring: true,
exportName: 'NumberPicker',
},
Select: {
package: '@alifd/next',
version: '1.19.18',
destructuring: true,
exportName: 'Select',
},
'Select.Option': {
package: '@alifd/next',
version: '1.19.18',
destructuring: true,
exportName: 'Select',
subName: 'Option',
},
};

View File

@ -0,0 +1 @@
export default {};

View File

@ -0,0 +1,20 @@
import { app } from '@ali/lowcode-runtime';
import Renderer from '@ali/lowcode-react-renderer';
import FusionLoading from './plugins/loading/fusion';
import BasicLayout from './layouts/BasicLayout';
import Preview from './plugins/provider';
// 注册渲染模块
app.registerRenderer(Renderer);
// 注册布局组件,可注册多个
app.registerLayout('BasicLayout', BasicLayout);
// 注册页面 Loading
app.registerLoading(FusionLoading);
// appKey应用唯一标识
app.registerProvider(Preview);
// 启动应用
app.run();

View File

@ -0,0 +1,24 @@
$header-height: 52px;
.avatar {
width: 24px;
height: 24px;
border-radius: 50%;
vertical-align: middle;
}
.basic-shell {
min-height: 100vh;
.next-shell-header {
height: $header-height;
}
.next-shell-main {
flex: 1;
display: flex;
flex-flow: column;
min-height: calc(100% - $header-height);
.next-shell-sub-main {
flex: 1;
}
}
}

View File

@ -0,0 +1,34 @@
import { Search, Icon, Shell } from '@alifd/next';
import './index.scss';
export default ({
name,
children,
logo,
}: {
name: string;
children: any;
logo: { src: string; width: number; height: number };
}) => (
<Shell className="basic-shell" style={{ border: '1px solid #eee' }}>
<Shell.Branding>
<img src={logo.src} width={logo.width} height={logo.height} alt="logo" />
<span style={{ marginLeft: 10 }}>{name}</span>
</Shell.Branding>
<Shell.Navigation direction="hoz">
<Search key="2" shape="simple" type="dark" style={{ width: '200px' }} />
</Shell.Navigation>
<Shell.Action>
<Icon type="ic_tongzhi" />
<img src="https://img.alicdn.com/tfs/TB1.ZBecq67gK0jSZFHXXa9jVXa-904-826.png" className="avatar" alt="用户头像" />
<span style={{ marginLeft: 10 }}>MyName</span>
</Shell.Action>
<Shell.Content className="content">{children}</Shell.Content>
<Shell.Footer>
<span>Alibaba Fusion</span>
<span>@ 2019 Alibaba Piecework </span>
</Shell.Footer>
</Shell>
);

View File

@ -0,0 +1,9 @@
.fusion-loading {
width: 48px;
height: 48px;
position: fixed;
top: 50%;
left: 50%;
margin-top: -24px;
margin-left: -24px;
}

View File

@ -0,0 +1,4 @@
import { Loading } from '@alifd/next';
import './index.scss';
export default () => <Loading tip="加载中..." className="fusion-loading" />;

View File

@ -0,0 +1,51 @@
import { ReactProvider, Utils } from '@ali/lowcode-runtime';
import appConfig from '../config/app';
import builtInComps from '../config/components';
import componentsMap from '../config/componentsMap';
import constants from '../config/constants';
import utils from '../config/utils';
// 定制加载应用配置的逻辑
export default class Preview extends ReactProvider {
// 定制获取、处理应用配置(组件、插件、路由模式、布局等)的逻辑
async getAppData(): Promise<any> {
const { history, layout, containerId } = appConfig;
const appSchemaStr: any = localStorage.getItem('lce-dev-store');
if (!appSchemaStr) {
return;
}
const appSchema = JSON.parse(appSchemaStr);
if (!appSchema) {
return;
}
const routes: any = {};
appSchema.componentsTree.forEach((page: any) => {
if (!page.fileName) {
return;
}
const pageId = page.fileName;
routes[pageId] = `/${pageId}`;
});
return {
history,
layout,
routes,
containerId,
components: { ...builtInComps, ...Utils.buildComponents({ '@alifd/next': 'Next' }, componentsMap) },
componentsMap,
utils: utils,
constants,
};
}
// 定制获取、处理页面 schema 的逻辑
async getPageData(pageId: string) {
const appSchemaStr = localStorage.getItem('lce-dev-store');
const appSchema = JSON.parse(appSchemaStr || '');
const idx = appSchema.componentsTree.findIndex(
(page: any, idx: number) => (page.fileName || `page${idx}`) === pageId,
);
const schema = appSchema.componentsTree[idx];
return schema;
}
}

View File

@ -1,18 +0,0 @@
import undoRedo from '@ali/lowcode-plugin-undo-redo';
import logo from '@ali/lowcode-plugin-sample-logo';
import SamplePreview from '@ali/lowcode-plugin-sample-preview';
import Designer from '@ali/lowcode-plugin-designer';
import SettingsPane from '@ali/lowcode-plugin-settings-pane';
import componentsPane from '@ali/lowcode-plugin-components-pane';
import OutlinePane from '@ali/lowcode-plugin-outline-pane';
import { PluginFactory } from '@ali/lowcode-editor-core';
export default {
logo: PluginFactory(logo),
samplePreview: PluginFactory(SamplePreview),
undoRedo: PluginFactory(undoRedo),
designer: PluginFactory(Designer),
componentsPane: PluginFactory(componentsPane),
settingsPane: PluginFactory(SettingsPane),
outlinePane: PluginFactory(OutlinePane),
};

View File

@ -1,3 +0,0 @@
export default {
namespace: 'page'
};

View File

@ -0,0 +1,22 @@
import LowcodeSkeleton from '@ali/lowcode-editor-skeleton';
import logo from '@ali/lowcode-plugin-sample-logo';
import undoRedo from '@ali/lowcode-plugin-undo-redo';
import samplePreview from '@ali/lowcode-plugin-sample-preview';
import componentsPane from '@ali/lowcode-plugin-components-pane';
import outlinePane from '@ali/lowcode-plugin-outline-pane';
import zhEn from '@ali/lowcode-plugin-zh-en';
import settingsPane from '@ali/lowcode-plugin-settings-pane';
import designer from '@ali/lowcode-plugin-designer';
import eventBindDialog from '@ali/lowcode-plugin-event-bind-dialog';
export default {
LowcodeSkeleton,
logo,
undoRedo,
samplePreview,
componentsPane,
outlinePane,
zhEn,
settingsPane,
designer,
eventBindDialog
};

View File

@ -0,0 +1,3 @@
export default {
"namespace": "page"
}

View File

@ -0,0 +1 @@
export default {};

View File

@ -0,0 +1,10 @@
import en_us from './en-US';
import zh_cn from './zh-CN';
import zh_tw from './zh-TW';
import ja_jp from './ja-JP';
export default {
'en-US': en_us,
'zh-CN': zh_cn,
'zh-TW': zh_tw,
'ja-JP': ja_jp
};

View File

@ -0,0 +1 @@
export default {};

View File

@ -0,0 +1 @@
export default {};

View File

@ -0,0 +1 @@
export default {};

View File

@ -0,0 +1,140 @@
export default {
"skeleton": {
"config": {
"package": "@ali/lowcode-editor-skeleton",
"version": "^0.8.0"
}
},
"theme": {
"fusion": {
"package": "@alife/theme-lowcode-light",
"version": "^0.1.0"
},
"scss": ""
},
"constants": {
"namespace": "page"
},
"utils": [],
"plugins": {
"topArea": [{
"pluginKey": "logo",
"type": "Custom",
"props": {
"align": "left",
"width": 100
},
"config": {
"package": "@ali/lowcode-plugin-sample-logo",
"version": "^0.8.0"
},
"pluginProps": {
"logo": "https://img.alicdn.com/tfs/TB1hoI9x1H2gK0jSZFEXXcqMpXa-146-40.png",
"href": "/"
}
}, {
"pluginKey": "undoRedo",
"type": "Custom",
"props": {
"align": "right",
"width": 88
},
"config": {
"package": "@ali/lowcode-plugin-undo-redo",
"version": "^0.8.0"
}
}, {
"pluginKey": "divider",
"type": "Divider",
"props": {
"align": "right"
}
}, {
"pluginKey": "samplePreview",
"type": "Custom",
"props": {
"align": "right",
"width": 64
},
"config": {
"package": "@ali/lowcode-plugin-sample-preview",
"version": "^0.8.0"
}
}],
"leftArea": [{
"pluginKey": "componentsPane",
"type": "PanelIcon",
"props": {
"align": "top",
"icon": "zujianku",
"title": "组件库",
"floatable": true
},
"config": {
"package": "@ali/lowcode-plugin-components-pane",
"version": "^0.8.0"
},
"pluginProps": {}
}, {
"pluginKey": "outlinePane",
"type": "PanelIcon",
"props": {
"align": "top",
"icon": "shuxingkongjian",
"title": "大纲树"
},
"config": {
"package": "@ali/lowcode-plugin-outline-pane",
"version": "^0.8.0"
},
"pluginProps": {}
}, {
"pluginKey": "zhEn",
"type": "Custom",
"props": {
"align": "bottom"
},
"config": {
"package": "@ali/lowcode-plugin-zh-en",
"version": "^0.8.0"
},
"pluginProps": {}
}],
"rightArea": [{
"pluginKey": "settingsPane",
"type": "Panel",
"props": {},
"config": {
"package": "@ali/lowcode-plugin-settings-pane",
"version": "^0.8.0"
},
"pluginProps": {}
}],
"centerArea": [{
"pluginKey": "designer",
"config": {
"package": "@ali/lowcode-plugin-designer",
"version": "^0.8.0"
}
}, {
"pluginKey": "eventBindDialog",
"config": {
"package": "@ali/lowcode-plugin-event-bind-dialog",
"version": "^0.8.0"
}
}]
},
"hooks": [],
"shortCuts": [],
"lifeCycles": {
"init": async function init(editor) {
const assets = await editor.utils.get('./assets.json');
editor.set('assets', assets);
editor.emit('assets.loaded', assets);
const schema = await editor.utils.get('./schema.json');
editor.set('schema', schema);
editor.emit('schema.loaded', schema);
}
}
};

View File

@ -0,0 +1,3 @@
export default {
};

View File

@ -1,6 +1,5 @@
import React from 'react';
import ReactDOM from 'react-dom';
import Skeleton from '@ali/lowcode-editor-skeleton';
import { registerSetters } from '@ali/lowcode-setters';
import config from './config/skeleton';
import components from './config/components';
@ -10,7 +9,7 @@ import './global.scss';
import './config/theme.scss';
registerSetters();
const Skeleton = components.LowcodeSkeleton;
const LCE_CONTAINER = document.getElementById('lce-container');
if (!LCE_CONTAINER) {

View File

@ -0,0 +1 @@
import './editor';

View File

@ -0,0 +1 @@
import './app';

View File

@ -1,9 +1,9 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"jsx": "react",
"target": "ES6"
"outDir": "lib"
},
"include": ["src/*"],
"exclude": ["node_modules", "build", "public"]
"include": [
"./src/"
]
}

View File

@ -0,0 +1,74 @@
# Change Log
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
<a name="0.9.1"></a>
## [0.9.1](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-designer@0.9.0...@ali/lowcode-designer@0.9.1) (2020-03-31)
**Note:** Version bump only for package @ali/lowcode-designer
<a name="0.9.0"></a>
# [0.9.0](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-designer@0.8.5...@ali/lowcode-designer@0.9.0) (2020-03-30)
### Bug Fixes
* **designer:** fix insertion style ([82c10d2](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/82c10d2))
### Features
* **designer:** add blank page logic ([aeeb9ba](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/aeeb9ba))
* **designer:** add builtin hotkeys ([2ec5883](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/2ec5883))
<a name="0.8.5"></a>
## [0.8.5](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-designer@0.8.4...@ali/lowcode-designer@0.8.5) (2020-03-30)
**Note:** Version bump only for package @ali/lowcode-designer
<a name="0.8.4"></a>
## [0.8.4](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-designer@0.8.3...@ali/lowcode-designer@0.8.4) (2020-03-30)
**Note:** Version bump only for package @ali/lowcode-designer
<a name="0.8.3"></a>
## 0.8.3 (2020-03-30)
### Features
* 🎸 merge material-parser ([b40c286](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/b40c286))
* history log ([fbb3577](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/fbb3577))
* import react-docgen to parse propTypes ([6e66168](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/6e66168))
<a name="0.8.2"></a>
## 0.8.2 (2020-03-30)
### Features
<<<<<<< HEAD
* 🎸 merge material-parser ([b40c286](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/b40c286))
* history log ([fbb3577](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/fbb3577))
* import react-docgen to parse propTypes ([6e66168](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/6e66168))
=======
* 🎸 merge material-parser ([b40c286](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/b40c2869a0bc901d855279735fe86b84dabaa04d))
* history log ([fbb3577](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/fbb3577bd434c0ac77cc907abc36e3efe110fe8c))
* import react-docgen to parse propTypes ([6e66168](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/6e661686e4693e69279c496f3be1dd173703c55e))
>>>>>>> df955e1db90ff104cd11160def80113cfd6faccc

View File

@ -1,6 +1,6 @@
{
"name": "@ali/lowcode-designer",
"version": "0.8.1",
"version": "0.9.1",
"description": "Designer for Ali LowCode Engine",
"main": "lib/index.js",
"module": "es/index.js",
@ -15,18 +15,18 @@
},
"license": "MIT",
"dependencies": {
"@ali/lowcode-globals": "^0.9.1",
"classnames": "^2.2.6",
"react": "^16",
"react-dom": "^16.7.0",
"@ali/lowcode-globals": "^0.8"
"react-dom": "^16.7.0"
},
"devDependencies": {
"@types/medium-editor": "^5.0.3",
"@alib/build-scripts": "^0.1.18",
"@types/classnames": "^2.2.7",
"@types/medium-editor": "^5.0.3",
"@types/node": "^13.7.1",
"@types/react": "^16",
"@types/react-dom": "^16",
"@alib/build-scripts": "^0.1.18",
"build-plugin-component": "^0.2.10"
},
"ava": {

View File

@ -1,25 +1,27 @@
.lc-insertion {
position: absolute;
top: -1.5px;
top: -2px;
left: 0;
z-index: 12;
pointer-events: none !important;
background-color: var(--color-brand-light);
height: 3px;
height: 4px;
&.cover {
top: 0;
height: auto;
width: auto;
border: none;
opacity: 0.3;
}
&.vertical {
top: 0;
left: -1.5px;
width: 3px;
left: -2px;
width: 4px;
height: auto;
}
&.invalid {
background-color: red;
}

View File

@ -20,11 +20,13 @@ import {
getRectTarget,
Rect,
CanvasPoint,
hotkey,
} from '../designer';
import { parseProps } from './utils/parse-props';
import { isElement } from '@ali/lowcode-globals';
import { ComponentMetadata } from '@ali/lowcode-globals';
import { BuiltinSimulatorRenderer } from './renderer';
import clipboard from '../designer/clipboard';
export interface LibraryItem {
package: string;
@ -196,6 +198,8 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
// wait 准备 iframe 内容、依赖库注入
const renderer = await createSimulator(this, iframe, vendors);
// TODO: !!! thinkof reload onload
// wait 业务组件被第一次消费,否则会渲染出错
await this.componentsConsumer.waitFirstConsume();
@ -209,11 +213,17 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
this._contentDocument = this._contentWindow.document;
this.viewport.setScrollTarget(this._contentWindow);
this.setupEvents();
// hotkey.mount(this.contentWindow);
// clipboard.injectCopyPaster(this.ownerDocument);
// bind hotkey & clipboard
hotkey.mount(this._contentWindow);
clipboard.injectCopyPaster(this._contentDocument);
// TODO: dispose the bindings
}
setupEvents() {
// TODO: Thinkof move events control to simulator renderer
// just listen special callback
// because iframe maybe reload
this.setupDragAndClick();
this.setupHovering();
}
@ -786,6 +796,7 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
const inline = el ? isChildInline(el) : false;
const row = el ? isRowContainer(el.parentElement!) : false;
const vertical = inline || row;
// TODO: fix type
const near: any = {
node: nearNode,

View File

@ -1,9 +1,4 @@
import {
IconRemove,
IconClone,
IconPage,
IconContainer,
IconComponent,
ComponentMetadata,
NpmInfo,
NodeData,
@ -18,6 +13,11 @@ import {
import { Node, NodeParent } from './document';
import { Designer } from './designer';
import { intl } from './locale';
import { IconContainer } from './icons/container';
import { IconPage } from './icons/page';
import { IconComponent } from './icons/component';
import { IconRemove } from './icons/remove';
import { IconClone } from './icons/clone';
function ensureAList(list?: string | string[]): string[] | null {
if (!list) {

View File

@ -5,6 +5,7 @@ function getDataFromPasteEvent(event: ClipboardEvent) {
}
try {
// { componentsMap, componentsTree, ... }
return JSON.parse(clipboardData.getData('text/plain'));
} catch (error) {
/*
@ -17,11 +18,13 @@ function getDataFromPasteEvent(event: ClipboardEvent) {
};
}
*/
// paste the text by div
// TODO: open the parser implement
return null;
/*
return {
code: clipboardData.getData('text/plain'),
maps: {},
};
};*/
}
}
@ -33,7 +36,7 @@ class Clipboard {
this.isCopyPaster(e.target);
}
isCopyPaster(el: any) {
private isCopyPaster(el: any) {
return this.copyPasters.includes(el);
}
@ -57,6 +60,9 @@ class Clipboard {
}
injectCopyPaster(document: Document) {
if (this.copyPasters.find(x => x.ownerDocument === document)) {
return;
}
const copyPaster = document.createElement<'textarea'>('textarea');
copyPaster.style.cssText = 'position: relative;left: -9999px;';
document.body.appendChild(copyPaster);

View File

@ -5,6 +5,7 @@ import BuiltinDragGhostComponent from './drag-ghost';
import { Designer, DesignerProps } from './designer';
import { ProjectView } from '../project';
import './designer.less';
import clipboard from './clipboard';
export class DesignerView extends Component<DesignerProps> {
readonly designer: Designer;
@ -32,6 +33,7 @@ export class DesignerView extends Component<DesignerProps> {
if (onMount) {
onMount(this.designer);
}
clipboard.injectCopyPaster(document)
this.designer.postEvent('mount', this.designer);
}

View File

@ -10,7 +10,7 @@ import {
autorun,
} from '@ali/lowcode-globals';
import { Project } from '../project';
import { Node, DocumentModel, insertChildren, isRootNode } from '../document';
import { Node, DocumentModel, insertChildren, isRootNode, NodeParent } from '../document';
import { ComponentMeta } from '../component-meta';
import { INodeSelector } from '../simulator';
import { Scroller, IScrollable } from './scroller';
@ -19,6 +19,7 @@ import { ActiveTracker } from './active-tracker';
import { Hovering } from './hovering';
import { DropLocation, LocationData, isLocationChildrenDetail } from './location';
import { OffsetObserver, createOffsetObserver } from './offset-observer';
import { focusing } from './focusing';
export interface DesignerProps {
className?: string;
@ -40,7 +41,6 @@ export interface DesignerProps {
}
export class Designer {
// readonly hotkey: Hotkey;
readonly dragon = new Dragon(this);
readonly activeTracker = new ActiveTracker();
readonly hovering = new Hovering();
@ -156,6 +156,9 @@ export class Designer {
this.postEvent('designer.init', this);
setupSelection();
setupHistory();
// TODO: 先简单实现,后期通过焦点赋值
focusing.focusDesigner = this;
}
postEvent(event: string, ...args: any[]) {
@ -198,7 +201,7 @@ export class Designer {
/**
*
*/
getSuitableInsertion() {
getSuitableInsertion(): { target: NodeParent; index?: number } | null {
const activedDoc = this.project.currentDocument;
if (!activedDoc) {
return null;
@ -296,7 +299,7 @@ export class Designer {
}
setSchema(schema?: ProjectSchema) {
this.project.setSchema(schema);
this.project.load(schema);
}
@obx.val private _componentMetasMap = new Map<string, ComponentMeta>();

View File

@ -427,8 +427,9 @@ export class Dragon {
};
const sourceSensor = getSourceSensor(dragObject);
const sensors: ISensor[] = (masterSensors as ISensor[]).concat(this.sensors);
const chooseSensor = (e: LocateEvent) => {
// this.sensors will change on dragstart
const sensors: ISensor[] = (masterSensors as ISensor[]).concat(this.sensors);
let sensor = e.sensor && e.sensor.isEnter(e) ? e.sensor : sensors.find((s) => s.sensorAvailable && s.isEnter(e));
if (!sensor) {
// TODO: enter some area like componentspanel cancel

View File

@ -0,0 +1,9 @@
import { Designer } from './designer';
// TODO:
// 当前激活区域管理
class Focusing {
focusDesigner?: Designer;
}
export const focusing = new Focusing();

View File

@ -1,618 +1,117 @@
interface KeyMap {
[key: number]: string;
}
import { Hotkey, isFormEvent } from '@ali/lowcode-globals';
import { focusing } from './focusing';
import { insertChildren } from '../document';
import clipboard from './clipboard';
interface CtrlKeyMap {
[key: string]: string;
}
export const hotkey = new Hotkey();
interface ActionEvent {
type: string;
}
interface HotkeyCallbacks {
[key: string]: HotkeyCallbackCfg[];
}
interface HotkeyDirectMap {
[key: string]: HotkeyCallback;
}
export type HotkeyCallback = (e: KeyboardEvent, combo?: string) => any | false;
interface HotkeyCallbackCfg {
callback: HotkeyCallback;
modifiers: string[];
action: string;
seq?: string;
level?: number;
combo?: string;
}
interface KeyInfo {
key: string;
modifiers: string[];
action: string;
}
interface SequenceLevels {
[key: string]: number;
}
const MAP: KeyMap = {
8: 'backspace',
9: 'tab',
13: 'enter',
16: 'shift',
17: 'ctrl',
18: 'alt',
20: 'capslock',
27: 'esc',
32: 'space',
33: 'pageup',
34: 'pagedown',
35: 'end',
36: 'home',
37: 'left',
38: 'up',
39: 'right',
40: 'down',
45: 'ins',
46: 'del',
91: 'meta',
93: 'meta',
224: 'meta',
};
const KEYCODE_MAP: KeyMap = {
106: '*',
107: '+',
109: '-',
110: '.',
111: '/',
186: ';',
187: '=',
188: ',',
189: '-',
190: '.',
191: '/',
192: '`',
219: '[',
220: '\\',
221: ']',
222: "'",
};
const SHIFT_MAP: CtrlKeyMap = {
'~': '`',
'!': '1',
'@': '2',
'#': '3',
$: '4',
'%': '5',
'^': '6',
'&': '7',
'*': '8',
'(': '9',
')': '0',
_: '-',
'+': '=',
':': ';',
'"': "'",
'<': ',',
'>': '.',
'?': '/',
'|': '\\',
};
const SPECIAL_ALIASES: CtrlKeyMap = {
option: 'alt',
command: 'meta',
return: 'enter',
escape: 'esc',
plus: '+',
mod: /Mac|iPod|iPhone|iPad/.test(navigator.platform) ? 'meta' : 'ctrl',
};
let REVERSE_MAP: CtrlKeyMap;
/**
* loop through the f keys, f1 to f19 and add them to the map
* programatically
*/
for (let i = 1; i < 20; ++i) {
MAP[111 + i] = 'f' + i;
}
/**
* loop through to map numbers on the numeric keypad
*/
for (let i = 0; i <= 9; ++i) {
MAP[i + 96] = String(i);
}
/**
* takes the event and returns the key character
*/
function characterFromEvent(e: KeyboardEvent): string {
const keyCode = e.keyCode || e.which;
// for keypress events we should return the character as is
if (e.type === 'keypress') {
let character = String.fromCharCode(keyCode);
// if the shift key is not pressed then it is safe to assume
// that we want the character to be lowercase. this means if
// you accidentally have caps lock on then your key bindings
// will continue to work
//
// the only side effect that might not be desired is if you
// bind something like 'A' cause you want to trigger an
// event when capital A is pressed caps lock will no longer
// trigger the event. shift+a will though.
if (!e.shiftKey) {
character = character.toLowerCase();
}
return character;
// hotkey binding
hotkey.bind(['backspace', 'del'], (e: KeyboardEvent) => {
const doc = focusing.focusDesigner?.currentDocument;
if (isFormEvent(e) || !doc) {
return;
}
// for non keypress events the special maps are needed
if (MAP[keyCode]) {
return MAP[keyCode];
e.preventDefault();
const sel = doc.selection;
const topItems = sel.getTopNodes();
// TODO: check can remove
topItems.forEach(node => {
doc.removeNode(node);
});
sel.clear();
});
hotkey.bind('escape', (e: KeyboardEvent) => {
// const currentFocus = focusing.current;
const sel = focusing.focusDesigner?.currentDocument?.selection;
if (isFormEvent(e) || !sel) {
return;
}
if (KEYCODE_MAP[keyCode]) {
return KEYCODE_MAP[keyCode];
e.preventDefault();
sel.clear();
// currentFocus.esc();
});
// command + c copy command + x cut
hotkey.bind(['command+c', 'ctrl+c', 'command+x', 'ctrl+x'], (e, action) => {
const doc = focusing.focusDesigner?.currentDocument;
if (isFormEvent(e) || !doc) {
return;
}
// if it is not in the special map
// with keydown and keyup events the character seems to always
// come in as an uppercase character whether you are pressing shift
// or not. we should make sure it is always lowercase for comparisons
return String.fromCharCode(keyCode).toLowerCase();
}
e.preventDefault();
interface KeypressEvent extends KeyboardEvent {
type: 'keypress';
}
function isPressEvent(e: KeyboardEvent | ActionEvent): e is KeypressEvent {
return e.type === 'keypress';
}
export function isFormEvent(e: KeyboardEvent) {
const t = e.target as HTMLFormElement;
if (!t) {
return false;
/*
const doc = getCurrentDocument();
if (isFormEvent(e) || !doc || !(focusing.id === 'outline' || focusing.id === 'canvas')) {
return;
}
e.preventDefault();
*/
if (t.form || /^(INPUT|SELECT|TEXTAREA)$/.test(t.tagName)) {
return true;
const selected = doc.selection.getTopNodes(true);
if (!selected || selected.length < 1) return;
const componentsMap = {};
const componentsTree = selected.map(item => item.export(false));
const data = { type: 'nodeSchema', componentsMap, componentsTree };
clipboard.setData(data);
/*
const cutMode = action.indexOf('x') > 0;
if (cutMode) {
const parentNode = selected.getParent();
parentNode.select();
selected.remove();
}
if (/write/.test(window.getComputedStyle(t).getPropertyValue('-webkit-user-modify'))) {
return true;
*/
});
// command + v paste
hotkey.bind(['command+v', 'ctrl+v'], (e) => {
const designer = focusing.focusDesigner;
const doc = designer?.currentDocument;
if (isFormEvent(e) || !designer || !doc) {
return;
}
return false;
}
/**
* checks if two arrays are equal
*/
function modifiersMatch(modifiers1: string[], modifiers2: string[]): boolean {
return modifiers1.sort().join(',') === modifiers2.sort().join(',');
}
/**
* takes a key event and figures out what the modifiers are
*/
function eventModifiers(e: KeyboardEvent): string[] {
const modifiers = [];
if (e.shiftKey) {
modifiers.push('shift');
}
if (e.altKey) {
modifiers.push('alt');
}
if (e.ctrlKey) {
modifiers.push('ctrl');
}
if (e.metaKey) {
modifiers.push('meta');
}
return modifiers;
}
/**
* determines if the keycode specified is a modifier key or not
*/
function isModifier(key: string): boolean {
return key === 'shift' || key === 'ctrl' || key === 'alt' || key === 'meta';
}
/**
* reverses the map lookup so that we can look for specific keys
* to see what can and can't use keypress
*
* @return {Object}
*/
function getReverseMap(): CtrlKeyMap {
if (!REVERSE_MAP) {
REVERSE_MAP = {};
for (const key in MAP) {
// pull out the numeric keypad from here cause keypress should
// be able to detect the keys from the character
if (Number(key) > 95 && Number(key) < 112) {
continue;
clipboard.waitPasteData(e, ({ componentsTree }) => {
if (componentsTree) {
const { target, index } = designer.getSuitableInsertion() || {};
if (!target) {
return;
}
if (MAP.hasOwnProperty(key)) {
REVERSE_MAP[MAP[key]] = key;
const nodes = insertChildren(target, componentsTree, index);
if (nodes) {
doc.selection.selectAll(nodes.map(o => o.id));
setTimeout(() => designer.activeTracker.track(nodes[0]), 10);
}
}
}
return REVERSE_MAP;
}
});
});
/**
* picks the best action based on the key combination
*/
function pickBestAction(key: string, modifiers: string[], action?: string): string {
// if no action was picked in we should try to pick the one
// that we think would work best for this key
if (!action) {
action = getReverseMap()[key] ? 'keydown' : 'keypress';
}
// modifier keys don't work as expected with keypress,
// switch to keydown
if (action === 'keypress' && modifiers.length) {
action = 'keydown';
}
return action;
}
/**
* Converts from a string key combination to an array
*
* @param {string} combination like "command+shift+l"
* @return {Array}
*/
function keysFromString(combination: string): string[] {
if (combination === '+') {
return ['+'];
// command + z undo
hotkey.bind(['command+z', 'ctrl+z'], (e) => {
const his = focusing.focusDesigner?.currentHistory;
if (isFormEvent(e) || !his) {
return;
}
combination = combination.replace(/\+{2}/g, '+plus');
return combination.split('+');
}
e.preventDefault();
his.back();
});
/**
* Gets info for a specific key combination
*
* @param combination key combination ("command+s" or "a" or "*")
*/
function getKeyInfo(combination: string, action?: string): KeyInfo {
let keys: string[] = [];
let key = '';
let i: number;
const modifiers: string[] = [];
// take the keys from this pattern and figure out what the actual
// pattern is all about
keys = keysFromString(combination);
for (i = 0; i < keys.length; ++i) {
key = keys[i];
// normalize key names
if (SPECIAL_ALIASES[key]) {
key = SPECIAL_ALIASES[key];
}
// if this is not a keypress event then we should
// be smart about using shift keys
// this will only work for US keyboards however
if (action && action !== 'keypress' && SHIFT_MAP[key]) {
key = SHIFT_MAP[key];
modifiers.push('shift');
}
// if this key is a modifier then add it to the list of modifiers
if (isModifier(key)) {
modifiers.push(key);
}
// command + shift + z redo
hotkey.bind(['command+y', 'ctrl+y', 'command+shift+z'], (e) => {
const his = focusing.focusDesigner?.currentHistory;
if (isFormEvent(e) || !his) {
return;
}
e.preventDefault();
// depending on what the key combination is
// we will try to pick the best event for it
action = pickBestAction(key, modifiers, action);
his.forward();
});
return {
key,
modifiers,
action,
};
}
/**
* actually calls the callback function
*
* if your callback function returns false this will use the jquery
* convention - prevent default and stop propogation on the event
*/
function fireCallback(callback: HotkeyCallback, e: KeyboardEvent, combo?: string, sequence?: string): void {
if (callback(e, combo) === false) {
e.preventDefault();
e.stopPropagation();
}
}
export class Hotkey {
private callBacks: HotkeyCallbacks = {};
private directMap: HotkeyDirectMap = {};
private sequenceLevels: SequenceLevels = {};
private resetTimer = 0;
private ignoreNextKeyup: boolean | string = false;
private ignoreNextKeypress = false;
private nextExpectedAction: boolean | string = false;
mount(window: Window) {
const document = window.document;
const handleKeyEvent = this.handleKeyEvent.bind(this);
document.addEventListener('keypress', handleKeyEvent, false);
document.addEventListener('keydown', handleKeyEvent, false);
document.addEventListener('keyup', handleKeyEvent, false);
return () => {
document.removeEventListener('keypress', handleKeyEvent, false);
document.removeEventListener('keydown', handleKeyEvent, false);
document.removeEventListener('keyup', handleKeyEvent, false);
};
}
bind(combos: string[] | string, callback: HotkeyCallback, action?: string): Hotkey {
this.bindMultiple(Array.isArray(combos) ? combos : [combos], callback, action);
return this;
}
/**
* resets all sequence counters except for the ones passed in
*/
private resetSequences(doNotReset?: SequenceLevels): void {
// doNotReset = doNotReset || {};
let activeSequences = false;
let key = '';
for (key in this.sequenceLevels) {
if (doNotReset && doNotReset[key]) {
activeSequences = true;
} else {
this.sequenceLevels[key] = 0;
}
}
if (!activeSequences) {
this.nextExpectedAction = false;
}
}
/**
* finds all callbacks that match based on the keycode, modifiers,
* and action
*/
private getMatches(
character: string,
modifiers: string[],
e: KeyboardEvent | ActionEvent,
sequenceName?: string,
combination?: string,
level?: number,
): HotkeyCallbackCfg[] {
let i: number;
let callback: HotkeyCallbackCfg;
const matches: HotkeyCallbackCfg[] = [];
const action: string = e.type;
// if there are no events related to this keycode
if (!this.callBacks[character]) {
return [];
}
// if a modifier key is coming up on its own we should allow it
if (action === 'keyup' && isModifier(character)) {
modifiers = [character];
}
// loop through all callbacks for the key that was pressed
// and see if any of them match
for (i = 0; i < this.callBacks[character].length; ++i) {
callback = this.callBacks[character][i];
// if a sequence name is not specified, but this is a sequence at
// the wrong level then move onto the next match
if (!sequenceName && callback.seq && this.sequenceLevels[callback.seq] !== callback.level) {
continue;
}
// if the action we are looking for doesn't match the action we got
// then we should keep going
if (action !== callback.action) {
continue;
}
// if this is a keypress event and the meta key and control key
// are not pressed that means that we need to only look at the
// character, otherwise check the modifiers as well
//
// chrome will not fire a keypress if meta or control is down
// safari will fire a keypress if meta or meta+shift is down
// firefox will fire a keypress if meta or control is down
if ((isPressEvent(e) && !e.metaKey && !e.ctrlKey) || modifiersMatch(modifiers, callback.modifiers)) {
const deleteCombo = !sequenceName && callback.combo === combination;
const deleteSequence = sequenceName && callback.seq === sequenceName && callback.level === level;
if (deleteCombo || deleteSequence) {
this.callBacks[character].splice(i, 1);
}
matches.push(callback);
}
}
return matches;
}
private handleKey(character: string, modifiers: string[], e: KeyboardEvent): void {
const callbacks: HotkeyCallbackCfg[] = this.getMatches(character, modifiers, e);
let i: number;
const doNotReset: SequenceLevels = {};
let maxLevel = 0;
let processedSequenceCallback = false;
// Calculate the maxLevel for sequences so we can only execute the longest callback sequence
for (i = 0; i < callbacks.length; ++i) {
if (callbacks[i].seq) {
maxLevel = Math.max(maxLevel, callbacks[i].level || 0);
}
}
// loop through matching callbacks for this key event
for (i = 0; i < callbacks.length; ++i) {
// fire for all sequence callbacks
// this is because if for example you have multiple sequences
// bound such as "g i" and "g t" they both need to fire the
// callback for matching g cause otherwise you can only ever
// match the first one
if (callbacks[i].seq) {
// only fire callbacks for the maxLevel to prevent
// subsequences from also firing
//
// for example 'a option b' should not cause 'option b' to fire
// even though 'option b' is part of the other sequence
//
// any sequences that do not match here will be discarded
// below by the resetSequences call
if (callbacks[i].level !== maxLevel) {
continue;
}
processedSequenceCallback = true;
// keep a list of which sequences were matches for later
doNotReset[callbacks[i].seq || ''] = 1;
fireCallback(callbacks[i].callback, e, callbacks[i].combo, callbacks[i].seq);
continue;
}
// if there were no sequence matches but we are still here
// that means this is a regular match so we should fire that
if (!processedSequenceCallback) {
fireCallback(callbacks[i].callback, e, callbacks[i].combo);
}
}
const ignoreThisKeypress = e.type === 'keypress' && this.ignoreNextKeypress;
if (e.type === this.nextExpectedAction && !isModifier(character) && !ignoreThisKeypress) {
this.resetSequences(doNotReset);
}
this.ignoreNextKeypress = processedSequenceCallback && e.type === 'keydown';
}
private handleKeyEvent(e: KeyboardEvent): void {
const character = characterFromEvent(e);
// no character found then stop
if (!character) {
return;
}
// need to use === for the character check because the character can be 0
if (e.type === 'keyup' && this.ignoreNextKeyup === character) {
this.ignoreNextKeyup = false;
return;
}
this.handleKey(character, eventModifiers(e), e);
}
private resetSequenceTimer(): void {
if (this.resetTimer) {
clearTimeout(this.resetTimer);
}
this.resetTimer = window.setTimeout(this.resetSequences, 1000);
}
private bindSequence(combo: string, keys: string[], callback: HotkeyCallback, action?: string): void {
// const self: any = this;
this.sequenceLevels[combo] = 0;
const increaseSequence = (nextAction: string) => {
return () => {
this.nextExpectedAction = nextAction;
++this.sequenceLevels[combo];
this.resetSequenceTimer();
};
};
const callbackAndReset = (e: KeyboardEvent): void => {
fireCallback(callback, e, combo);
if (action !== 'keyup') {
this.ignoreNextKeyup = characterFromEvent(e);
}
setTimeout(this.resetSequences, 10);
};
for (let i = 0; i < keys.length; ++i) {
const isFinal = i + 1 === keys.length;
const wrappedCallback = isFinal ? callbackAndReset : increaseSequence(action || getKeyInfo(keys[i + 1]).action);
this.bindSingle(keys[i], wrappedCallback, action, combo, i);
}
}
private bindSingle(
combination: string,
callback: HotkeyCallback,
action?: string,
sequenceName?: string,
level?: number,
): void {
// store a direct mapped reference for use with HotKey.trigger
this.directMap[`${combination}:${action}`] = callback;
// make sure multiple spaces in a row become a single space
combination = combination.replace(/\s+/g, ' ');
const sequence: string[] = combination.split(' ');
let info: KeyInfo;
// if this pattern is a sequence of keys then run through this method
// to reprocess each pattern one key at a time
if (sequence.length > 1) {
this.bindSequence(combination, sequence, callback, action);
return;
}
info = getKeyInfo(combination, action);
// make sure to initialize array if this is the first time
// a callback is added for this key
this.callBacks[info.key] = this.callBacks[info.key] || [];
// remove an existing match if there is one
this.getMatches(info.key, info.modifiers, { type: info.action }, sequenceName, combination, level);
// add this call back to the array
// if it is a sequence put it at the beginning
// if not put it at the end
//
// this is important because the way these are processed expects
// the sequence ones to come first
this.callBacks[info.key][sequenceName ? 'unshift' : 'push']({
callback,
modifiers: info.modifiers,
action: info.action,
seq: sequenceName,
level,
combo: combination,
});
}
private bindMultiple(combinations: string[], callback: HotkeyCallback, action?: string) {
for (const item of combinations) {
this.bindSingle(item, callback, action);
}
}
}
hotkey.mount(window);

View File

@ -86,7 +86,7 @@ export function isChildInline(child: Element | Text, win?: Window) {
return true;
}
const style = (win || getWindow(child)).getComputedStyle(child);
return /^inline/.test(style.getPropertyValue('display'));
return /^inline/.test(style.getPropertyValue('display')) || /^(left|right)$/.test(style.getPropertyValue('float'));
}
export function getRectTarget(rect: Rect | null) {

View File

@ -59,6 +59,7 @@ export class DocumentModel {
}
private _modalNode?: NodeParent;
private _blank?: boolean;
get modalNode() {
return this._modalNode;
}
@ -67,7 +68,7 @@ export class DocumentModel {
return this.modalNode || this.rootNode;
}
constructor(readonly project: Project, schema: RootSchema) {
constructor(readonly project: Project, schema?: RootSchema) {
autorun(() => {
this.nodes.forEach((item) => {
if (item.parent == null && item !== this.rootNode) {
@ -75,7 +76,16 @@ export class DocumentModel {
}
});
}, true);
this.rootNode = this.createRootNode(schema);
if (!schema) {
this._blank = true;
}
this.rootNode = this.createRootNode(schema || {
componentName: 'Page',
fileName: ''
});
this.history = new History(
() => this.schema,
(schema) => this.import(schema as RootSchema, true),
@ -83,6 +93,10 @@ export class DocumentModel {
this.setupListenActiveNodes();
}
@computed isBlank() {
return this._blank && !this.isModified();
}
readonly designer = this.project.designer;
/**
@ -295,6 +309,7 @@ export class DocumentModel {
}
private mountSimulator(simulator: ISimulatorHost) {
// TODO: 多设备 simulator 支持
this._simulator = simulator;
// TODO: emit simulator mounted
}
@ -386,7 +401,8 @@ export class DocumentModel {
*
*/
remove() {
// todo:
// this.project.removeDocument(this);
// todo: ...
}
purge() {

View File

@ -1,10 +1,10 @@
import { IconBase, IconProps } from "./icon-base";
import { SVGIcon, IconProps } from "@ali/lowcode-globals";
export function IconClone(props: IconProps) {
return (
<IconBase viewBox="0 0 1024 1024" {...props}>
<SVGIcon viewBox="0 0 1024 1024" {...props}>
<path d="M192 256.16C192 220.736 220.704 192 256.16 192h639.68C931.264 192 960 220.704 960 256.16v639.68A64.16 64.16 0 0 1 895.84 960H256.16A64.16 64.16 0 0 1 192 895.84V256.16z m64 31.584v576.512a32 32 0 0 0 31.744 31.744h576.512a32 32 0 0 0 31.744-31.744V287.744A32 32 0 0 0 864.256 256H287.744A32 32 0 0 0 256 287.744zM288 192v64h64V192H288z m128 0v64h64V192h-64z m128 0v64h64V192h-64z m128 0v64h64V192h-64z m128 0v64h64V192h-64z m96 96v64h64V288h-64z m0 128v64h64v-64h-64z m0 128v64h64v-64h-64z m0 128v64h64v-64h-64z m0 128v64h64v-64h-64z m-96 96v64h64v-64h-64z m-128 0v64h64v-64h-64z m-128 0v64h64v-64h-64z m-128 0v64h64v-64h-64z m-128 0v64h64v-64H288z m-96-96v64h64v-64H192z m0-128v64h64v-64H192z m0-128v64h64v-64H192z m0-128v64h64v-64H192z m0-128v64h64V288H192z m160 416c0-17.664 14.592-32 32.064-32h319.872a31.968 31.968 0 1 1 0 64h-319.872A31.968 31.968 0 0 1 352 704z m0-128c0-17.664 14.4-32 32.224-32h383.552c17.792 0 32.224 14.208 32.224 32 0 17.664-14.4 32-32.224 32H384.224A32.032 32.032 0 0 1 352 576z m0-128c0-17.664 14.4-32 32.224-32h383.552c17.792 0 32.224 14.208 32.224 32 0 17.664-14.4 32-32.224 32H384.224A32.032 32.032 0 0 1 352 448z m512 47.936V192h-64V159.968A31.776 31.776 0 0 0 768.032 128H160A31.776 31.776 0 0 0 128 159.968V768c0 17.92 14.304 31.968 31.968 31.968H192v64h303.936H128.128A63.968 63.968 0 0 1 64 799.872V128.128C64 92.704 92.48 64 128.128 64h671.744C835.296 64 864 92.48 864 128.128v367.808z"/>
</IconBase>
</SVGIcon>
);
}

View File

@ -1,10 +1,10 @@
import { IconBase, IconProps } from "./icon-base";
import { SVGIcon, IconProps } from "@ali/lowcode-globals";
export function IconComponent(props: IconProps) {
return (
<IconBase viewBox="0 0 1024 1024" {...props}>
<SVGIcon viewBox="0 0 1024 1024" {...props}>
<path d="M783.5648 437.4528h-18.0224V336.6912c0-43.8272-35.6352-79.4624-79.4624-79.4624h-110.592V241.664c0-90.9312-73.728-164.6592-164.6592-164.6592-90.9312 0-164.6592 73.728-164.6592 164.6592v15.5648H155.2384c-43.8272 0-79.4624 35.6352-79.4624 79.4624v131.4816c0 16.7936 13.9264 30.72 30.72 30.72h56.1152c56.9344 0 103.2192 46.2848 103.2192 103.2192s-46.2848 103.2192-103.2192 103.2192H106.496c-16.7936 0-30.72 13.9264-30.72 30.72v131.4816c0 43.8272 35.6352 79.4624 79.4624 79.4624h531.2512c43.8272 0 79.4624-35.6352 79.4624-79.4624v-100.7616h18.0224c90.9312 0 164.6592-73.728 164.6592-164.6592-0.4096-90.9312-74.1376-164.6592-165.0688-164.6592z m0 267.8784h-48.7424c-16.7936 0-30.72 13.9264-30.72 30.72v131.4816c0 9.8304-8.192 18.0224-18.0224 18.0224H155.2384c-9.8304 0-18.0224-8.192-18.0224-18.0224v-100.7616h25.3952c90.9312 0 164.6592-73.728 164.6592-164.6592 0-90.9312-73.728-164.6592-164.6592-164.6592h-25.3952V336.6912c0-9.8304 8.192-18.0224 18.0224-18.0224h121.6512c16.7936 0 30.72-13.9264 30.72-30.72V241.664c0-56.9344 46.2848-103.2192 103.2192-103.2192s103.2192 46.2848 103.2192 103.2192v46.2848c0 16.7936 13.9264 30.72 30.72 30.72h141.312c9.8304 0 18.0224 8.192 18.0224 18.0224v131.4816c0 16.7936 13.9264 30.72 30.72 30.72h48.7424c56.9344 0 103.2192 46.2848 103.2192 103.2192s-46.2848 103.2192-103.2192 103.2192z" />
</IconBase>
</SVGIcon>
);
}
IconComponent.displayName = 'Component';

View File

@ -1,11 +1,11 @@
import { IconBase, IconProps } from "./icon-base";
import { SVGIcon, IconProps } from "@ali/lowcode-globals";
export function IconContainer(props: IconProps) {
return (
<IconBase viewBox="0 0 1024 1024" {...props}>
<SVGIcon viewBox="0 0 1024 1024" {...props}>
<path d="M800 800h64v64h-64v-64z m-128 0h64v64h-64v-64z m-128 0h64v64h-64v-64z m-128 0h64v64h-64v-64z m-256 0h64v64h-64v-64z m0-640h64v64h-64v-64z m128 640h64v64h-64v-64zM160 672h64v64h-64v-64z m0-128h64v64h-64v-64z m0-128h64v64h-64v-64z m0-128h64v64h-64v-64z m640 384h64v64h-64v-64z m0-128h64v64h-64v-64z m0-128h64v64h-64v-64z m0-128h64v64h-64v-64z m0-128h64v64h-64v-64z m-128 0h64v64h-64v-64z m-128 0h64v64h-64v-64z m-128 0h64v64h-64v-64z m-128 0h64v64h-64v-64z" />
<path d="M896 64H128c-35.2 0-64 28.8-64 64v768c0 35.2 28.8 64 64 64h768c35.2 0 64-28.8 64-64V128c0-35.2-28.8-64-64-64z m0 800c0 19.2-12.8 32-32 32H160c-19.2 0-32-12.8-32-32V160c0-19.2 12.8-32 32-32h704c19.2 0 32 12.8 32 32v704z" />
</IconBase>
</SVGIcon>
);
}
IconContainer.displayName = 'Container';

View File

@ -1,10 +1,10 @@
import { IconBase, IconProps } from "./icon-base";
import { SVGIcon, IconProps } from "@ali/lowcode-globals";
export function IconHidden(props: IconProps) {
return (
<IconBase viewBox="0 0 1024 1024" {...props}>
<SVGIcon viewBox="0 0 1024 1024" {...props}>
<path d="M183.423543 657.078213l163.499771-98.484012c-4.233418-14.908548-6.646374-30.585599-6.646374-46.852074 0-94.665033 76.739778-171.404812 171.404812-171.404812 45.983287 0 87.641059 18.20871 118.42518 47.679929l129.791042-78.17957c-73.254398-41.73145-157.866471-65.812915-248.216221-65.812915-192.742792 0-360.068705 108.505249-444.453604 267.715321C96.636944 567.228859 136.301316 616.355743 183.423543 657.078213zM841.253886 367.552144l-164.382884 99.015108c3.934612 14.415314 6.215562 29.513174 6.215562 45.174875 0 94.665033-76.739778 171.404812-171.404812 171.404812-45.361117 0-86.484723-17.747199-117.142977-46.515407l-129.419582 77.955466c72.874751 41.149189 156.893306 64.871473 246.563582 64.871473 192.742792 0 360.068705-108.505249 444.453604-267.717368C927.000805 456.773188 887.794875 408.054603 841.253886 367.552144zM420.280042 511.741104c0 0.550539 0.152473 1.060145 0.161682 1.608637l135.080511-81.366146c-13.065574-7.198959-27.854395-11.658528-43.826158-11.658528C461.20922 420.325068 420.280042 461.254246 420.280042 511.741104zM447.739441 576.947198l69.02098-41.574884L948.364369 275.395234c10.812253-6.512321 14.297634-20.558222 7.785314-31.369452-6.512321-10.812253-20.556175-14.296611-31.368428-7.785314L575.654762 446.537056l0 0-151.20577 91.078345 0 0L75.027787 748.090043c-10.812253 6.512321-14.297634 20.556175-7.785314 31.368428 6.512321 10.812253 20.556175 14.297634 31.369452 7.785314L447.739441 576.947198 447.739441 576.947198zM511.696078 603.157139c50.487881 0 91.416036-40.928155 91.416036-91.416036 0-0.549515-0.152473-1.057075-0.161682-1.605567l-135.079488 81.364099C480.935494 598.699618 495.724315 603.157139 511.696078 603.157139z" />
</IconBase>
</SVGIcon>
);
}
IconHidden.displayName = 'Hidden';

View File

@ -1,12 +1,12 @@
import { IconBase, IconProps } from "./icon-base";
import { SVGIcon, IconProps } from "@ali/lowcode-globals";
export function IconPage(props: IconProps) {
return (
<IconBase viewBox="0 0 1024 1024" {...props}>
<SVGIcon viewBox="0 0 1024 1024" {...props}>
<path d="M381.6 864H162.4c-6.9 0-12.4 4.6-12.4 10.3v19.3c0 5.7 5.6 10.3 12.4 10.3h219.1c6.8 0 12.4-4.6 12.4-10.3v-19.3c0.1-5.7-5.5-10.3-12.3-10.3zM382 780.6H162c-6.9 0-12.5 4.6-12.5 10.3v19.3c0 5.7 5.6 10.3 12.5 10.3h220c6.9 0 12.5-4.6 12.5-10.3v-19.3c0-5.7-5.6-10.3-12.5-10.3zM162.4 737.2h219.1c6.8 0 12.4-4.6 12.4-10.3v-19.3c0-5.7-5.6-10.3-12.4-10.3H162.4c-6.9 0-12.4 4.6-12.4 10.3v19.3c0 5.7 5.6 10.3 12.4 10.3z" />
<path d="M977.1 0H46.9C21 0 0 21 0 46.9v930.2c0 25.9 21 46.9 46.9 46.9h930.2c25.9 0 46.9-21 46.9-46.9V46.9C1024 21 1003 0 977.1 0z m-18.7 911.6c0 25.9-21 46.9-46.9 46.9H112.4c-25.9 0-46.9-21-46.9-47V112.4c0-25.9 21-46.9 46.9-46.9h799.1c25.9 0 46.9 21 46.9 46.9v799.2z" />
<path d="M207.9 342.7h608.2c32 0 57.9-25.9 57.9-57.9v-83c0-32-25.9-57.9-57.9-57.9H207.9c-32 0-57.9 25.9-57.9 57.9v83c0 32 25.9 57.9 57.9 57.9zM200 201.8c0-4.4 3.5-7.9 7.9-7.9h608.2c4.4 0 7.9 3.5 7.9 7.9v83c0 4.4-3.5 7.9-7.9 7.9H207.9c-4.4 0-7.9-3.5-7.9-7.9v-83zM806.4 405.7h-277c-37.3 0-67.6 30.2-67.6 67.6v363.2c0 37.3 30.2 67.6 67.6 67.6h277c37.3 0 67.6-30.2 67.6-67.6V473.3c0-37.4-30.2-67.6-67.6-67.6zM824 836.4c0 9.7-7.9 17.6-17.6 17.6h-277c-9.7 0-17.6-7.9-17.6-17.6V473.3c0-9.7 7.9-17.6 17.6-17.6h277c9.7 0 17.6 7.9 17.6 17.6v363.1zM272 649.7c67.4 0 122-54.6 122-122s-54.6-122-122-122-122 54.6-122 122 54.6 122 122 122z m0-204c45.2 0 82 36.8 82 82s-36.8 82-82 82-82-36.8-82-82 36.8-82 82-82z" />
</IconBase>
</SVGIcon>
);
}
IconPage.displayName = 'Page';

View File

@ -1,10 +1,10 @@
import { IconBase, IconProps } from './icon-base';
import { SVGIcon, IconProps } from '@ali/lowcode-globals';
export function IconRemove(props: IconProps) {
return (
<IconBase viewBox="0 0 1024 1024" {...props}>
<SVGIcon viewBox="0 0 1024 1024" {...props}>
<path d="M224 256v639.84A64 64 0 0 0 287.84 960h448.32A64 64 0 0 0 800 895.84V256h64a32 32 0 1 0 0-64H160a32 32 0 1 0 0 64h64zM384 96c0-17.664 14.496-32 31.904-32h192.192C625.696 64 640 78.208 640 96c0 17.664-14.496 32-31.904 32H415.904A31.872 31.872 0 0 1 384 96z m-96 191.744C288 270.208 302.4 256 320.224 256h383.552C721.6 256 736 270.56 736 287.744v576.512C736 881.792 721.6 896 703.776 896H320.224A32.224 32.224 0 0 1 288 864.256V287.744zM352 352c0-17.696 14.208-32.032 32-32.032 17.664 0 32 14.24 32 32v448c0 17.664-14.208 32-32 32-17.664 0-32-14.24-32-32V352z m128 0c0-17.696 14.208-32.032 32-32.032 17.664 0 32 14.24 32 32v448c0 17.664-14.208 32-32 32-17.664 0-32-14.24-32-32V352z m128 0c0-17.696 14.208-32.032 32-32.032 17.664 0 32 14.24 32 32v448c0 17.664-14.208 32-32 32-17.664 0-32-14.24-32-32V352z" />
</IconBase>
</SVGIcon>
);
}
IconRemove.displayName = 'Remove';

View File

@ -1,11 +1,11 @@
import { IconBase, IconProps } from './icon-base';
import { SVGIcon, IconProps } from '@ali/lowcode-globals';
export function IconSetting(props: IconProps) {
return (
<IconBase viewBox="0 0 1024 1024" {...props}>
<SVGIcon viewBox="0 0 1024 1024" {...props}>
<path d="M965.824 405.952a180.48 180.48 0 0 1-117.12-85.376 174.464 174.464 0 0 1-16-142.08 22.208 22.208 0 0 0-7.04-23.552 480.576 480.576 0 0 0-153.6-89.216 23.104 23.104 0 0 0-24.32 5.76 182.208 182.208 0 0 1-135.68 57.92 182.208 182.208 0 0 1-133.12-56.64 23.104 23.104 0 0 0-26.88-7.04 478.656 478.656 0 0 0-153.6 89.856 22.208 22.208 0 0 0-7.04 23.552 174.464 174.464 0 0 1-16 141.44A180.48 180.48 0 0 1 58.24 405.952a22.4 22.4 0 0 0-17.28 17.792 455.08 455.08 0 0 0 0 176.512 22.4 22.4 0 0 0 17.28 17.792 180.48 180.48 0 0 1 117.12 84.736c25.408 42.944 31.232 94.592 16 142.08a22.208 22.208 0 0 0 7.04 23.552A480.576 480.576 0 0 0 352 957.632h7.68a23.04 23.04 0 0 0 16.64-7.04 184.128 184.128 0 0 1 266.944 0c6.592 8.96 18.752 11.968 28.8 7.04a479.36 479.36 0 0 0 156.16-88.576 22.208 22.208 0 0 0 7.04-23.552 174.464 174.464 0 0 1 13.44-142.72 180.48 180.48 0 0 1 117.12-84.736 22.4 22.4 0 0 0 17.28-17.792 452.613 452.613 0 0 0 0-176.512 23.04 23.04 0 0 0-17.28-17.792z m-42.88 169.408a218.752 218.752 0 0 0-128 98.112 211.904 211.904 0 0 0-21.76 156.736 415.936 415.936 0 0 1-112 63.68 217.472 217.472 0 0 0-149.12-63.68 221.312 221.312 0 0 0-149.12 63.68 414.592 414.592 0 0 1-112-63.68c12.8-53.12 4.288-109.12-23.68-156.096A218.752 218.752 0 0 0 101.12 575.36a386.176 386.176 0 0 1 0-127.36 218.752 218.752 0 0 0 128-98.112c27.2-47.552 34.944-103.68 21.76-156.8a415.296 415.296 0 0 1 112-63.68A221.44 221.44 0 0 0 512 187.392a218.24 218.24 0 0 0 149.12-57.984 413.952 413.952 0 0 1 112 63.744 211.904 211.904 0 0 0 23.04 156.096 218.752 218.752 0 0 0 128 98.112 386.65 386.65 0 0 1 0 127.36l-1.28 0.64z" />
<path d="M512 320.576c-105.984 0-192 85.568-192 191.104a191.552 191.552 0 0 0 192 191.104c106.112 0 192.064-85.568 192.064-191.104a190.72 190.72 0 0 0-56.256-135.168 192.448 192.448 0 0 0-135.744-55.936z m0 318.528c-70.656 0-128-57.088-128-127.424 0-70.4 57.344-127.36 128-127.36 70.72 0 128 56.96 128 127.36 0 33.792-13.44 66.176-37.44 90.112a128.32 128.32 0 0 1-90.496 37.312z" />
</IconBase>
</SVGIcon>
);
}

View File

@ -1,5 +1,6 @@
{
"copy": "Copy",
"remove": "Remove",
"Condition Group": "Condition Group"
"Condition Group": "Condition Group",
"No opened document": "No opened document, open some document to editing"
}

View File

@ -1,5 +1,6 @@
{
"copy": "复制",
"remove": "删除",
"Condition Group": "条件组"
"Condition Group": "条件组",
"No opened document": "没有打开的页面,请选择页面打开编辑"
}

View File

@ -2,6 +2,7 @@ import { Component } from 'react';
import { observer } from '@ali/lowcode-globals';
import { Designer } from '../designer';
import { DocumentView } from '../document';
import { intl } from '../locale';
import './project.less';
@observer
@ -9,14 +10,14 @@ export class ProjectView extends Component<{ designer: Designer }> {
render() {
const { designer } = this.props;
// TODO: support splitview
const opens = designer.project.documents.filter((doc) => doc.opened);
return (
<div className="lc-project">
{designer.project.documents.map(doc => {
if (!doc.opened) {
return null;
}
return <DocumentView key={doc.id} document={doc} />;
})}
{opens.length > 0 ? (
opens.map((doc) => <DocumentView key={doc.id} document={doc} />)
) : (
<div className="lc-project-empty">{intl('No opened document')}</div>
)}
</div>
);
}

View File

@ -4,6 +4,14 @@
right: 0;
width: 100%;
height: 100%;
.lc-project-empty {
width: 100%;
height: 100%;
font-size: 16px;
text-align: center;
background: transparent url(//img.alicdn.com/tfs/TB1xLKQAbj1gK0jSZFuXXcrHpXa-90-90.png) center 30% no-repeat;
padding-top: 50%;
}
.lc-document {
width: 100%;
height: 100%;

View File

@ -14,11 +14,11 @@ export class Project {
// TODO: 考虑项目级别 History
constructor(readonly designer: Designer, schema?: ProjectSchema) {
this.setSchema(schema);
this.load(schema);
}
@computed get currentDocument() {
return this.documents.find(doc => doc.actived);
return this.documents.find((doc) => doc.actived);
}
/**
@ -27,30 +27,45 @@ export class Project {
getSchema(): ProjectSchema {
return {
...this.data,
componentsTree: this.documents.map(doc => doc.schema),
// todo: future change this filter
componentsTree: this.documents.filter((doc) => !doc.isBlank()).map((doc) => doc.schema),
};
}
/**
* schema
*
* @param autoOpen true string
*/
setSchema(schema?: ProjectSchema) {
load(schema?: ProjectSchema, autoOpen?: boolean | string) {
this.unload();
// load new document
this.data = {
version: '1.0.0',
componentsMap: [],
componentsTree: [],
...schema,
};
if (this.documents.length > 0) {
this.documents.forEach(doc => doc.purge());
this.documents.length = 0;
if (autoOpen) {
if (autoOpen === true) {
// auto open first document or open a blank page
this.open(this.data.componentsTree[0]);
} else {
// auto open should be string of fileName
this.open(autoOpen);
}
}
this.open(
this.data.componentsTree[0] || {
componentName: 'Page',
fileName: '',
},
);
}
/**
*
*/
unload() {
if (this.documents.length < 1) {
return;
}
this.documents.forEach((doc) => doc.remove());
}
/**
@ -86,14 +101,23 @@ export class Project {
| string,
): any {}
open(doc: string | DocumentModel | RootSchema): void {
open(doc?: string | DocumentModel | RootSchema): void {
if (!doc) {
const got = this.documents.find((item) => item.isBlank());
if (got) {
return got.open();
}
doc = new DocumentModel(this);
this.documents.push(doc);
return doc.open();
}
if (typeof doc === 'string') {
const got = this.documents.find(item => item.fileName === doc);
const got = this.documents.find((item) => item.fileName === doc);
if (got) {
return got.open();
}
const data = this.data.componentsTree.find(data => data.fileName === doc);
const data = this.data.componentsTree.find((data) => data.fileName === doc);
if (data) {
doc = new DocumentModel(this, data);
this.documents.push(doc);
@ -113,7 +137,7 @@ export class Project {
}
checkExclusive(actived: DocumentModel) {
this.documents.forEach(doc => {
this.documents.forEach((doc) => {
if (doc !== actived) {
doc.suspense();
}
@ -122,7 +146,7 @@ export class Project {
}
closeOthers(opened: DocumentModel) {
this.documents.forEach(doc => {
this.documents.forEach((doc) => {
if (doc !== opened) {
doc.close();
}

View File

@ -0,0 +1,28 @@
# Change Log
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
<a name="0.8.4"></a>
## [0.8.4](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-editor-core@0.8.3...@ali/lowcode-editor-core@0.8.4) (2020-03-30)
**Note:** Version bump only for package @ali/lowcode-editor-core
<a name="0.8.3"></a>
## 0.8.3 (2020-03-30)
**Note:** Version bump only for package @ali/lowcode-editor-core
<a name="0.8.2"></a>
## 0.8.2 (2020-03-30)
**Note:** Version bump only for package @ali/lowcode-editor-core

View File

@ -1,6 +1,6 @@
{
"name": "@ali/lowcode-editor-core",
"version": "0.8.0",
"version": "0.8.4",
"description": "alibaba lowcode editor core",
"main": "lib/index.js",
"module": "es/index.js",
@ -20,15 +20,15 @@
],
"author": "xiayang.xy",
"dependencies": {
"@alifd/next": "1.x",
"debug": "^4.1.1",
"events": "^3.1.0",
"intl-messageformat": "^8.3.1",
"lodash": "^4.17.15",
"prop-types": "^15.5.8",
"store": "^2.0.12",
"whatwg-fetch": "^3.0.0",
"react": "^16.8.0",
"@alifd/next": "1.x"
"store": "^2.0.12",
"whatwg-fetch": "^3.0.0"
},
"devDependencies": {
"@alib/build-scripts": "^0.1.3",

View File

@ -11,6 +11,8 @@ import {
PluginSet,
} from './definitions';
import pluginFactory from './pluginFactory';
import * as editorUtils from './utils';
const { registShortCuts, transformToPromise, unRegistShortCuts } = editorUtils;
@ -92,7 +94,10 @@ export default class Editor extends EventEmitter {
constructor(config: EditorConfig, components: PluginClassSet, utils?: Utils) {
super();
this.config = config;
this.components = components;
this.components = {};
Object.entries(components).forEach(([key, value]): void => {
this.components[key] = pluginFactory(value);
});
this.utils = { ...editorUtils, ...utils };
instance = this;
}

View File

@ -1,9 +1,7 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"outDir": "lib",
"target": "es6",
"jsx": "react"
"outDir": "lib"
},
"include": [
"./src/"

View File

@ -0,0 +1,43 @@
# Change Log
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
<a name="0.8.5"></a>
## [0.8.5](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-editor-skeleton@0.8.4...@ali/lowcode-editor-skeleton@0.8.5) (2020-03-30)
**Note:** Version bump only for package @ali/lowcode-editor-skeleton
<a name="0.8.4"></a>
## [0.8.4](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-editor-skeleton@0.8.3...@ali/lowcode-editor-skeleton@0.8.4) (2020-03-30)
**Note:** Version bump only for package @ali/lowcode-editor-skeleton
<a name="0.8.3"></a>
## 0.8.3 (2020-03-30)
### Features
* 🎸 merge material-parser ([b40c286](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/b40c286))
<a name="0.8.2"></a>
## 0.8.2 (2020-03-30)
### Features
<<<<<<< HEAD
* 🎸 merge material-parser ([b40c286](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/b40c286))
=======
* 🎸 merge material-parser ([b40c286](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/b40c2869a0bc901d855279735fe86b84dabaa04d))
>>>>>>> df955e1db90ff104cd11160def80113cfd6faccc

View File

@ -1,6 +1,6 @@
{
"name": "@ali/lowcode-editor-skeleton",
"version": "0.8.0",
"version": "0.8.5",
"description": "alibaba lowcode editor skeleton",
"main": "lib/index.js",
"module": "es/index.js",
@ -20,7 +20,7 @@
],
"author": "xiayang.xy",
"dependencies": {
"@ali/lowcode-editor-core": "^0.8.0",
"@ali/lowcode-editor-core": "^0.8.4",
"@alifd/next": "^1.x",
"prop-types": "^15.5.8",
"react": "^16.8.1",

View File

@ -1,9 +1,7 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"outDir": "lib",
"target": "es6",
"jsx": "react"
"outDir": "lib"
},
"include": [
"./src/"

View File

@ -0,0 +1,62 @@
# Change Log
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
<a name="0.9.1"></a>
## [0.9.1](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-globals@0.9.0...@ali/lowcode-globals@0.9.1) (2020-03-31)
**Note:** Version bump only for package @ali/lowcode-globals
<a name="0.9.0"></a>
# [0.9.0](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-globals@0.8.4...@ali/lowcode-globals@0.9.0) (2020-03-30)
### Features
* **designer:** add builtin hotkeys ([2ec5883](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/2ec5883))
<a name="0.8.4"></a>
## [0.8.4](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-globals@0.8.3...@ali/lowcode-globals@0.8.4) (2020-03-30)
**Note:** Version bump only for package @ali/lowcode-globals
<a name="0.8.3"></a>
## [0.8.3](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-globals@0.8.2...@ali/lowcode-globals@0.8.3) (2020-03-30)
**Note:** Version bump only for package @ali/lowcode-globals
<a name="0.8.2"></a>
## 0.8.2 (2020-03-30)
### Features
* double outline & ZH_EN support ([b379bd7](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/b379bd7))
<a name="0.8.1"></a>
## 0.8.1 (2020-03-30)
### Features
<<<<<<< HEAD
* double outline & ZH_EN support ([b379bd7](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/b379bd7))
=======
* double outline & ZH_EN support ([b379bd7](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/b379bd7c0c488ef24f825760750a13d3fa083c96))
>>>>>>> df955e1db90ff104cd11160def80113cfd6faccc

View File

@ -1,7 +1,8 @@
{
"name": "@ali/lowcode-globals",
"version": "0.8.0",
"version": "0.9.1",
"description": "Globals api for Ali lowCode engine",
"license": "MIT",
"main": "lib/index.js",
"module": "es/index.js",
"files": [
@ -14,6 +15,16 @@
"test": "ava",
"test:snapshot": "ava --update-snapshots"
},
"ava": {
"compileEnhancements": false,
"extensions": [
"ts"
],
"require": [
"ts-node/register"
],
"snapshotDir": "test/fixtures/__snapshots__"
},
"dependencies": {
"@alifd/next": "^1.19.16",
"@recore/obx": "^1.0.8",
@ -23,26 +34,15 @@
"react-dom": "^16.7.0"
},
"devDependencies": {
"@alib/build-scripts": "^0.1.18",
"@types/classnames": "^2.2.7",
"@types/node": "^13.7.1",
"@types/react": "^16",
"@types/react-dom": "^16",
"@alib/build-scripts": "^0.1.18",
"build-plugin-component": "^0.2.11",
"build-plugin-fusion": "^0.1.0",
"build-plugin-moment-locales": "^0.1.0"
},
"ava": {
"compileEnhancements": false,
"snapshotDir": "test/fixtures/__snapshots__",
"extensions": [
"ts"
],
"require": [
"ts-node/register"
]
},
"license": "MIT",
"publishConfig": {
"registry": "https://registry.npm.alibaba-inc.com"
}

View File

@ -1,2 +1,3 @@
export * from './tip';
export * from './title';
export * from './svg-icon';

View File

@ -16,7 +16,7 @@ export interface IconProps {
style?: object;
}
export function IconBase({
export function SVGIcon({
fill,
size = 'medium',
viewBox,

View File

@ -16,7 +16,7 @@ function findTip(target: HTMLElement | null): TipOptions | null {
if (target.dataset && target.dataset.tip) {
return {
children: target.dataset.tip,
direction: target.dataset.direction || target.dataset.dir,
direction: (target.dataset.direction || target.dataset.dir) as any,
theme: target.dataset.theme,
target,
};

View File

@ -1,8 +0,0 @@
export * from './clone';
export * from './hidden';
export * from './remove';
export * from './setting';
export * from './icon-base';
export * from './component';
export * from './container';
export * from './page';

View File

@ -1,7 +1,6 @@
export * from './intl';
export * from './components';
export * from './utils';
export * from './icons';
export * from './types';
export * from './di';
export * from './obx';

View File

@ -5,7 +5,7 @@ export interface TipConfig {
className?: string;
children?: I18nData | ReactNode;
theme?: string;
direction?: string; // 'n|s|w|e|top|bottom|left|right';
direction?: 'top' | 'bottom' | 'left' | 'right';
}
export type TipContent = string | I18nData | ReactElement | TipConfig;

View File

@ -0,0 +1,604 @@
interface KeyMap {
[key: number]: string;
}
interface CtrlKeyMap {
[key: string]: string;
}
interface ActionEvent {
type: string;
}
interface HotkeyCallbacks {
[key: string]: HotkeyCallbackCfg[];
}
interface HotkeyDirectMap {
[key: string]: HotkeyCallback;
}
export type HotkeyCallback = (e: KeyboardEvent, combo?: string) => any | false;
interface HotkeyCallbackCfg {
callback: HotkeyCallback;
modifiers: string[];
action: string;
seq?: string;
level?: number;
combo?: string;
}
interface KeyInfo {
key: string;
modifiers: string[];
action: string;
}
interface SequenceLevels {
[key: string]: number;
}
const MAP: KeyMap = {
8: 'backspace',
9: 'tab',
13: 'enter',
16: 'shift',
17: 'ctrl',
18: 'alt',
20: 'capslock',
27: 'esc',
32: 'space',
33: 'pageup',
34: 'pagedown',
35: 'end',
36: 'home',
37: 'left',
38: 'up',
39: 'right',
40: 'down',
45: 'ins',
46: 'del',
91: 'meta',
93: 'meta',
224: 'meta',
};
const KEYCODE_MAP: KeyMap = {
106: '*',
107: '+',
109: '-',
110: '.',
111: '/',
186: ';',
187: '=',
188: ',',
189: '-',
190: '.',
191: '/',
192: '`',
219: '[',
220: '\\',
221: ']',
222: "'",
};
const SHIFT_MAP: CtrlKeyMap = {
'~': '`',
'!': '1',
'@': '2',
'#': '3',
$: '4',
'%': '5',
'^': '6',
'&': '7',
'*': '8',
'(': '9',
')': '0',
_: '-',
'+': '=',
':': ';',
'"': "'",
'<': ',',
'>': '.',
'?': '/',
'|': '\\',
};
const SPECIAL_ALIASES: CtrlKeyMap = {
option: 'alt',
command: 'meta',
return: 'enter',
escape: 'esc',
plus: '+',
mod: /Mac|iPod|iPhone|iPad/.test(navigator.platform) ? 'meta' : 'ctrl',
};
let REVERSE_MAP: CtrlKeyMap;
/**
* loop through the f keys, f1 to f19 and add them to the map
* programatically
*/
for (let i = 1; i < 20; ++i) {
MAP[111 + i] = 'f' + i;
}
/**
* loop through to map numbers on the numeric keypad
*/
for (let i = 0; i <= 9; ++i) {
MAP[i + 96] = String(i);
}
/**
* takes the event and returns the key character
*/
function characterFromEvent(e: KeyboardEvent): string {
const keyCode = e.keyCode || e.which;
// for keypress events we should return the character as is
if (e.type === 'keypress') {
let character = String.fromCharCode(keyCode);
// if the shift key is not pressed then it is safe to assume
// that we want the character to be lowercase. this means if
// you accidentally have caps lock on then your key bindings
// will continue to work
//
// the only side effect that might not be desired is if you
// bind something like 'A' cause you want to trigger an
// event when capital A is pressed caps lock will no longer
// trigger the event. shift+a will though.
if (!e.shiftKey) {
character = character.toLowerCase();
}
return character;
}
// for non keypress events the special maps are needed
if (MAP[keyCode]) {
return MAP[keyCode];
}
if (KEYCODE_MAP[keyCode]) {
return KEYCODE_MAP[keyCode];
}
// if it is not in the special map
// with keydown and keyup events the character seems to always
// come in as an uppercase character whether you are pressing shift
// or not. we should make sure it is always lowercase for comparisons
return String.fromCharCode(keyCode).toLowerCase();
}
interface KeypressEvent extends KeyboardEvent {
type: 'keypress';
}
function isPressEvent(e: KeyboardEvent | ActionEvent): e is KeypressEvent {
return e.type === 'keypress';
}
/**
* checks if two arrays are equal
*/
function modifiersMatch(modifiers1: string[], modifiers2: string[]): boolean {
return modifiers1.sort().join(',') === modifiers2.sort().join(',');
}
/**
* takes a key event and figures out what the modifiers are
*/
function eventModifiers(e: KeyboardEvent): string[] {
const modifiers = [];
if (e.shiftKey) {
modifiers.push('shift');
}
if (e.altKey) {
modifiers.push('alt');
}
if (e.ctrlKey) {
modifiers.push('ctrl');
}
if (e.metaKey) {
modifiers.push('meta');
}
return modifiers;
}
/**
* determines if the keycode specified is a modifier key or not
*/
function isModifier(key: string): boolean {
return key === 'shift' || key === 'ctrl' || key === 'alt' || key === 'meta';
}
/**
* reverses the map lookup so that we can look for specific keys
* to see what can and can't use keypress
*
* @return {Object}
*/
function getReverseMap(): CtrlKeyMap {
if (!REVERSE_MAP) {
REVERSE_MAP = {};
for (const key in MAP) {
// pull out the numeric keypad from here cause keypress should
// be able to detect the keys from the character
if (Number(key) > 95 && Number(key) < 112) {
continue;
}
if (MAP.hasOwnProperty(key)) {
REVERSE_MAP[MAP[key]] = key;
}
}
}
return REVERSE_MAP;
}
/**
* picks the best action based on the key combination
*/
function pickBestAction(key: string, modifiers: string[], action?: string): string {
// if no action was picked in we should try to pick the one
// that we think would work best for this key
if (!action) {
action = getReverseMap()[key] ? 'keydown' : 'keypress';
}
// modifier keys don't work as expected with keypress,
// switch to keydown
if (action === 'keypress' && modifiers.length) {
action = 'keydown';
}
return action;
}
/**
* Converts from a string key combination to an array
*
* @param {string} combination like "command+shift+l"
* @return {Array}
*/
function keysFromString(combination: string): string[] {
if (combination === '+') {
return ['+'];
}
combination = combination.replace(/\+{2}/g, '+plus');
return combination.split('+');
}
/**
* Gets info for a specific key combination
*
* @param combination key combination ("command+s" or "a" or "*")
*/
function getKeyInfo(combination: string, action?: string): KeyInfo {
let keys: string[] = [];
let key = '';
let i: number;
const modifiers: string[] = [];
// take the keys from this pattern and figure out what the actual
// pattern is all about
keys = keysFromString(combination);
for (i = 0; i < keys.length; ++i) {
key = keys[i];
// normalize key names
if (SPECIAL_ALIASES[key]) {
key = SPECIAL_ALIASES[key];
}
// if this is not a keypress event then we should
// be smart about using shift keys
// this will only work for US keyboards however
if (action && action !== 'keypress' && SHIFT_MAP[key]) {
key = SHIFT_MAP[key];
modifiers.push('shift');
}
// if this key is a modifier then add it to the list of modifiers
if (isModifier(key)) {
modifiers.push(key);
}
}
// depending on what the key combination is
// we will try to pick the best event for it
action = pickBestAction(key, modifiers, action);
return {
key,
modifiers,
action,
};
}
/**
* actually calls the callback function
*
* if your callback function returns false this will use the jquery
* convention - prevent default and stop propogation on the event
*/
function fireCallback(callback: HotkeyCallback, e: KeyboardEvent, combo?: string, sequence?: string): void {
if (callback(e, combo) === false) {
e.preventDefault();
e.stopPropagation();
}
}
export class Hotkey {
private callBacks: HotkeyCallbacks = {};
private directMap: HotkeyDirectMap = {};
private sequenceLevels: SequenceLevels = {};
private resetTimer = 0;
private ignoreNextKeyup: boolean | string = false;
private ignoreNextKeypress = false;
private nextExpectedAction: boolean | string = false;
mount(window: Window) {
const document = window.document;
const handleKeyEvent = this.handleKeyEvent.bind(this);
document.addEventListener('keypress', handleKeyEvent, false);
document.addEventListener('keydown', handleKeyEvent, false);
document.addEventListener('keyup', handleKeyEvent, false);
return () => {
document.removeEventListener('keypress', handleKeyEvent, false);
document.removeEventListener('keydown', handleKeyEvent, false);
document.removeEventListener('keyup', handleKeyEvent, false);
};
}
bind(combos: string[] | string, callback: HotkeyCallback, action?: string): Hotkey {
this.bindMultiple(Array.isArray(combos) ? combos : [combos], callback, action);
return this;
}
/**
* resets all sequence counters except for the ones passed in
*/
private resetSequences(doNotReset?: SequenceLevels): void {
// doNotReset = doNotReset || {};
let activeSequences = false;
let key = '';
for (key in this.sequenceLevels) {
if (doNotReset && doNotReset[key]) {
activeSequences = true;
} else {
this.sequenceLevels[key] = 0;
}
}
if (!activeSequences) {
this.nextExpectedAction = false;
}
}
/**
* finds all callbacks that match based on the keycode, modifiers,
* and action
*/
private getMatches(
character: string,
modifiers: string[],
e: KeyboardEvent | ActionEvent,
sequenceName?: string,
combination?: string,
level?: number,
): HotkeyCallbackCfg[] {
let i: number;
let callback: HotkeyCallbackCfg;
const matches: HotkeyCallbackCfg[] = [];
const action: string = e.type;
// if there are no events related to this keycode
if (!this.callBacks[character]) {
return [];
}
// if a modifier key is coming up on its own we should allow it
if (action === 'keyup' && isModifier(character)) {
modifiers = [character];
}
// loop through all callbacks for the key that was pressed
// and see if any of them match
for (i = 0; i < this.callBacks[character].length; ++i) {
callback = this.callBacks[character][i];
// if a sequence name is not specified, but this is a sequence at
// the wrong level then move onto the next match
if (!sequenceName && callback.seq && this.sequenceLevels[callback.seq] !== callback.level) {
continue;
}
// if the action we are looking for doesn't match the action we got
// then we should keep going
if (action !== callback.action) {
continue;
}
// if this is a keypress event and the meta key and control key
// are not pressed that means that we need to only look at the
// character, otherwise check the modifiers as well
//
// chrome will not fire a keypress if meta or control is down
// safari will fire a keypress if meta or meta+shift is down
// firefox will fire a keypress if meta or control is down
if ((isPressEvent(e) && !e.metaKey && !e.ctrlKey) || modifiersMatch(modifiers, callback.modifiers)) {
const deleteCombo = !sequenceName && callback.combo === combination;
const deleteSequence = sequenceName && callback.seq === sequenceName && callback.level === level;
if (deleteCombo || deleteSequence) {
this.callBacks[character].splice(i, 1);
}
matches.push(callback);
}
}
return matches;
}
private handleKey(character: string, modifiers: string[], e: KeyboardEvent): void {
const callbacks: HotkeyCallbackCfg[] = this.getMatches(character, modifiers, e);
let i: number;
const doNotReset: SequenceLevels = {};
let maxLevel = 0;
let processedSequenceCallback = false;
// Calculate the maxLevel for sequences so we can only execute the longest callback sequence
for (i = 0; i < callbacks.length; ++i) {
if (callbacks[i].seq) {
maxLevel = Math.max(maxLevel, callbacks[i].level || 0);
}
}
// loop through matching callbacks for this key event
for (i = 0; i < callbacks.length; ++i) {
// fire for all sequence callbacks
// this is because if for example you have multiple sequences
// bound such as "g i" and "g t" they both need to fire the
// callback for matching g cause otherwise you can only ever
// match the first one
if (callbacks[i].seq) {
// only fire callbacks for the maxLevel to prevent
// subsequences from also firing
//
// for example 'a option b' should not cause 'option b' to fire
// even though 'option b' is part of the other sequence
//
// any sequences that do not match here will be discarded
// below by the resetSequences call
if (callbacks[i].level !== maxLevel) {
continue;
}
processedSequenceCallback = true;
// keep a list of which sequences were matches for later
doNotReset[callbacks[i].seq || ''] = 1;
fireCallback(callbacks[i].callback, e, callbacks[i].combo, callbacks[i].seq);
continue;
}
// if there were no sequence matches but we are still here
// that means this is a regular match so we should fire that
if (!processedSequenceCallback) {
fireCallback(callbacks[i].callback, e, callbacks[i].combo);
}
}
const ignoreThisKeypress = e.type === 'keypress' && this.ignoreNextKeypress;
if (e.type === this.nextExpectedAction && !isModifier(character) && !ignoreThisKeypress) {
this.resetSequences(doNotReset);
}
this.ignoreNextKeypress = processedSequenceCallback && e.type === 'keydown';
}
private handleKeyEvent(e: KeyboardEvent): void {
const character = characterFromEvent(e);
// no character found then stop
if (!character) {
return;
}
// need to use === for the character check because the character can be 0
if (e.type === 'keyup' && this.ignoreNextKeyup === character) {
this.ignoreNextKeyup = false;
return;
}
this.handleKey(character, eventModifiers(e), e);
}
private resetSequenceTimer(): void {
if (this.resetTimer) {
clearTimeout(this.resetTimer);
}
this.resetTimer = window.setTimeout(this.resetSequences, 1000);
}
private bindSequence(combo: string, keys: string[], callback: HotkeyCallback, action?: string): void {
// const self: any = this;
this.sequenceLevels[combo] = 0;
const increaseSequence = (nextAction: string) => {
return () => {
this.nextExpectedAction = nextAction;
++this.sequenceLevels[combo];
this.resetSequenceTimer();
};
};
const callbackAndReset = (e: KeyboardEvent): void => {
fireCallback(callback, e, combo);
if (action !== 'keyup') {
this.ignoreNextKeyup = characterFromEvent(e);
}
setTimeout(this.resetSequences, 10);
};
for (let i = 0; i < keys.length; ++i) {
const isFinal = i + 1 === keys.length;
const wrappedCallback = isFinal ? callbackAndReset : increaseSequence(action || getKeyInfo(keys[i + 1]).action);
this.bindSingle(keys[i], wrappedCallback, action, combo, i);
}
}
private bindSingle(
combination: string,
callback: HotkeyCallback,
action?: string,
sequenceName?: string,
level?: number,
): void {
// store a direct mapped reference for use with HotKey.trigger
this.directMap[`${combination}:${action}`] = callback;
// make sure multiple spaces in a row become a single space
combination = combination.replace(/\s+/g, ' ');
const sequence: string[] = combination.split(' ');
let info: KeyInfo;
// if this pattern is a sequence of keys then run through this method
// to reprocess each pattern one key at a time
if (sequence.length > 1) {
this.bindSequence(combination, sequence, callback, action);
return;
}
info = getKeyInfo(combination, action);
// make sure to initialize array if this is the first time
// a callback is added for this key
this.callBacks[info.key] = this.callBacks[info.key] || [];
// remove an existing match if there is one
this.getMatches(info.key, info.modifiers, { type: info.action }, sequenceName, combination, level);
// add this call back to the array
// if it is a sequence put it at the beginning
// if not put it at the end
//
// this is important because the way these are processed expects
// the sequence ones to come first
this.callBacks[info.key][sequenceName ? 'unshift' : 'push']({
callback,
modifiers: info.modifiers,
action: info.action,
seq: sequenceName,
level,
combo: combination,
});
}
private bindMultiple(combinations: string[], callback: HotkeyCallback, action?: string) {
for (const item of combinations) {
this.bindSingle(item, callback, action);
}
}
}

View File

@ -19,3 +19,4 @@ export * from './shallow-equal';
export * from './unique-id';
export * from './get-public-path';
export * from './is-form-event';
export * from './hotkey';

View File

@ -0,0 +1,118 @@
# Change Log
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
<a name="0.9.0"></a>
# [0.9.0](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-material-parser@0.8.4...@ali/lowcode-material-parser@0.9.0) (2020-03-31)
### Bug Fixes
* [material-parser]fix bug of main field & remove useless debugger ([8fde0ec](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/8fde0ec))
* fix bug of build errors ([770a1b6](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/770a1b6))
* fix bug of missing types in material-parser ([9ce0a73](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/9ce0a73))
### Features
* 🎸 support parsing fusion source code ([5895cf1](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/5895cf1))
* support localizing ([e1faa84](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/e1faa84))
<a name="0.8.4"></a>
## [0.8.4](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-material-parser@0.8.3...@ali/lowcode-material-parser@0.8.4) (2020-03-30)
**Note:** Version bump only for package @ali/lowcode-material-parser
<a name="0.8.3"></a>
## [0.8.3](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-material-parser@0.8.2...@ali/lowcode-material-parser@0.8.3) (2020-03-30)
**Note:** Version bump only for package @ali/lowcode-material-parser
<a name="0.8.2"></a>
## 0.8.2 (2020-03-30)
### Bug Fixes
* 🐛 fix bug of transforming type ([ebbe58d](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/ebbe58d))
* 🐛 fix bug of validate schema ([3f97523](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/3f97523))
### Code Refactoring
* 💡 refactor with react-docgen ([64c9daa](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/64c9daa))
### Features
* complete component protocol json schema & validate method ([3df360d](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/3df360d))
* immigrate aimake materialin ([44ac85f](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/44ac85f))
* import react-docgen to parse propTypes ([6e66168](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/6e66168))
* remove -p tslint.json for test ([6d013e1](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/6d013e1))
* remove useless codes & modify generator ([dcd1b33](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/dcd1b33))
* support multiple exported components ([db1b6de](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/db1b6de))
### BREAKING CHANGES
* 🧨 use react-docgen to replace parser
<a name="0.8.1"></a>
## 0.8.1 (2020-03-30)
### Bug Fixes
<<<<<<< HEAD
* 🐛 fix bug of transforming type ([ebbe58d](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/ebbe58d))
* 🐛 fix bug of validate schema ([3f97523](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/3f97523))
=======
* 🐛 fix bug of transforming type ([ebbe58d](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/ebbe58df70f047f4b5fe367ac4b4a08de8a65e5d))
* 🐛 fix bug of validate schema ([3f97523](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/3f975232c7cd551bc9c74962095dcc9b127af489))
>>>>>>> df955e1db90ff104cd11160def80113cfd6faccc
### Code Refactoring
<<<<<<< HEAD
* 💡 refactor with react-docgen ([64c9daa](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/64c9daa))
=======
* 💡 refactor with react-docgen ([64c9daa](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/64c9daa1f451fdfeab2777e4beefc5d5e1890ba1))
>>>>>>> df955e1db90ff104cd11160def80113cfd6faccc
### Features
<<<<<<< HEAD
* complete component protocol json schema & validate method ([3df360d](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/3df360d))
* immigrate aimake materialin ([44ac85f](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/44ac85f))
* import react-docgen to parse propTypes ([6e66168](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/6e66168))
* remove -p tslint.json for test ([6d013e1](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/6d013e1))
* remove useless codes & modify generator ([dcd1b33](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/dcd1b33))
* support multiple exported components ([db1b6de](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/db1b6de))
=======
* complete component protocol json schema & validate method ([3df360d](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/3df360de85d425b2926ea50ff26a8df27ec36a78))
* immigrate aimake materialin ([44ac85f](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/44ac85f8a6a35bcd50f2e2b74a022e3cebe3cdef))
* import react-docgen to parse propTypes ([6e66168](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/6e661686e4693e69279c496f3be1dd173703c55e))
* remove -p tslint.json for test ([6d013e1](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/6d013e18f93bad5647cb9ea0a497336f64e1459a))
* remove useless codes & modify generator ([dcd1b33](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/dcd1b33d3bf8bdf5577dcc980608d9eac8d99372))
* support multiple exported components ([db1b6de](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/db1b6deaca256b0d107fe607de6cd0fc90517a9c))
>>>>>>> df955e1db90ff104cd11160def80113cfd6faccc
### BREAKING CHANGES
* 🧨 use react-docgen to replace parser

View File

@ -1,6 +1,6 @@
{
"name": "@ali/lowcode-material-parser",
"version": "0.8.0",
"version": "0.9.0",
"description": "material parser for Ali lowCode engine",
"main": "lib/index.js",
"files": [
@ -20,6 +20,7 @@
"jest-watch-typeahead": "^0.3.1",
"js-yaml": "^3.13.1",
"json-schema-to-typescript": "^8.2.0",
"tslib": "^1.11.1",
"typescript": "^3.8.3"
},
"scripts": {
@ -47,6 +48,7 @@
"@babel/parser": "^7.8.4",
"@babel/traverse": "^7.8.4",
"@babel/types": "^7.8.3",
"ast-types": "^0.13.3",
"cross-spawn-promise": "^0.10.2",
"debug": "^4.1.1",
"fs-extra": "^8.1.0",
@ -54,5 +56,8 @@
"react-docgen": "^5.3.0",
"semver": "^7.1.3",
"short-uuid": "^3.1.1"
},
"publishConfig": {
"registry": "https://registry.npm.alibaba-inc.com"
}
}

View File

@ -17,7 +17,7 @@ const tsPath = path.resolve(__dirname, '../src/otter-core/schema/types.ts');
ajv.compile(schema);
fs.writeFileSync(JsonPath, JSON.stringify(schema, null, 2), 'utf-8');
console.log('yaml file is successfully transformed into json');
const ts = await compile(schema, 'IComponentMaterial');
const ts = await compile(schema, 'ComponentMeta');
fs.writeFileSync(tsPath, ts);
console.log('schema.d.ts is successfully generated');
} catch (e) {

Some files were not shown because too many files have changed in this diff Show More