mirror of
https://github.com/alibaba/lowcode-engine.git
synced 2026-03-12 02:46:08 +00:00
chore: lint fixed
This commit is contained in:
parent
6b8d0c13bc
commit
764e841336
@ -1,23 +1,18 @@
|
|||||||
import stylistic from '@stylistic/eslint-plugin';
|
import stylistic from '@stylistic/eslint-plugin';
|
||||||
import tseslint from 'typescript-eslint'
|
import tseslint from 'typescript-eslint';
|
||||||
import js from '@eslint/js';
|
import js from '@eslint/js';
|
||||||
import react from 'eslint-plugin-react'
|
import react from 'eslint-plugin-react';
|
||||||
import reactHooks from 'eslint-plugin-react-hooks';
|
import reactHooks from 'eslint-plugin-react-hooks';
|
||||||
import reactRefresh from 'eslint-plugin-react-refresh';
|
import globals from 'globals';
|
||||||
import globals from 'globals'
|
|
||||||
|
|
||||||
export default tseslint.config({
|
export default tseslint.config({
|
||||||
files: ['packages/*/src/**/*.{ts?(x),js?(x)}'],
|
files: ['packages/*/{src,__tests__}/**/*.{ts?(x),js?(x)}'],
|
||||||
ignores: ["**/*.test.ts"],
|
ignores: ['**/*.test.ts'],
|
||||||
extends: [
|
extends: [js.configs.recommended, ...tseslint.configs.recommended],
|
||||||
js.configs.recommended,
|
|
||||||
...tseslint.configs.recommended,
|
|
||||||
],
|
|
||||||
plugins: {
|
plugins: {
|
||||||
'@stylistic': stylistic,
|
'@stylistic': stylistic,
|
||||||
react,
|
react,
|
||||||
'react-hooks': reactHooks,
|
'react-hooks': reactHooks,
|
||||||
'react-refresh': reactRefresh
|
|
||||||
},
|
},
|
||||||
languageOptions: {
|
languageOptions: {
|
||||||
parserOptions: {
|
parserOptions: {
|
||||||
@ -28,18 +23,22 @@ export default tseslint.config({
|
|||||||
globals: {
|
globals: {
|
||||||
...globals.browser,
|
...globals.browser,
|
||||||
...globals.nodeBuiltin,
|
...globals.nodeBuiltin,
|
||||||
...globals.jest
|
...globals.jest,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
rules: {
|
rules: {
|
||||||
'@stylistic/indent': ['error', 2],
|
'@stylistic/indent': ['error', 2],
|
||||||
'@stylistic/indent-binary-ops': ['error', 2],
|
'@stylistic/indent-binary-ops': ['error', 2],
|
||||||
'@stylistic/max-len': ['error', { tabWidth: 2, "ignoreStrings": true }],
|
'@stylistic/max-len': ['error', { code: 100, tabWidth: 2, ignoreStrings: true, ignoreComments: true }],
|
||||||
'@stylistic/no-tabs': 'error',
|
'@stylistic/no-tabs': 'error',
|
||||||
'@stylistic/quotes': ['error', 'single'],
|
'@stylistic/quotes': ['error', 'single'],
|
||||||
'@stylistic/jsx-pascal-case': [2],
|
'@stylistic/jsx-pascal-case': [2],
|
||||||
'@stylistic/jsx-indent': [2, 2, { checkAttributes: true, indentLogicalExpressions: true }],
|
'@stylistic/jsx-indent': [2, 2, { checkAttributes: true, indentLogicalExpressions: true }],
|
||||||
'@stylistic/semi': ['error', 'always'],
|
'@stylistic/semi': ['error', 'always'],
|
||||||
|
'@stylistic/eol-last': ['error', 'always'],
|
||||||
|
'@stylistic/jsx-quotes': ['error', 'prefer-double'],
|
||||||
|
|
||||||
|
"@typescript-eslint/ban-ts-comment": ["error", { 'ts-expect-error': 'allow-with-description' }],
|
||||||
|
|
||||||
'react/jsx-no-undef': 'error',
|
'react/jsx-no-undef': 'error',
|
||||||
'react/jsx-uses-vars': 'error',
|
'react/jsx-uses-vars': 'error',
|
||||||
@ -50,7 +49,5 @@ export default tseslint.config({
|
|||||||
|
|
||||||
'react-hooks/rules-of-hooks': 'error', // Checks rules of Hooks
|
'react-hooks/rules-of-hooks': 'error', // Checks rules of Hooks
|
||||||
'react-hooks/exhaustive-deps': 'warn', // Checks effect dependencies
|
'react-hooks/exhaustive-deps': 'warn', // Checks effect dependencies
|
||||||
|
|
||||||
'react-refresh/only-export-components': 'warn',
|
|
||||||
},
|
},
|
||||||
})
|
});
|
||||||
|
|||||||
@ -4,8 +4,8 @@
|
|||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"playground": "pnpm --filter playground dev",
|
"playground": "pnpm --filter playground dev",
|
||||||
"test": "pnpm -r test",
|
|
||||||
"build": "node ./scripts/build.js",
|
"build": "node ./scripts/build.js",
|
||||||
|
"test": "vitest",
|
||||||
"clean": "rimraf ./packages/*/dist",
|
"clean": "rimraf ./packages/*/dist",
|
||||||
"clean:lib": "rimraf ./node_modules ./packages/*/node_modules",
|
"clean:lib": "rimraf ./node_modules ./packages/*/node_modules",
|
||||||
"lint": "eslint . --cache",
|
"lint": "eslint . --cache",
|
||||||
@ -35,7 +35,6 @@
|
|||||||
"eslint": "^8.57.0",
|
"eslint": "^8.57.0",
|
||||||
"eslint-plugin-react": "^7.34.1",
|
"eslint-plugin-react": "^7.34.1",
|
||||||
"eslint-plugin-react-hooks": "^4.6.0",
|
"eslint-plugin-react-hooks": "^4.6.0",
|
||||||
"eslint-plugin-react-refresh": "^0.4.6",
|
|
||||||
"globals": "^15.0.0",
|
"globals": "^15.0.0",
|
||||||
"husky": "^9.0.11",
|
"husky": "^9.0.11",
|
||||||
"less": "^4.2.0",
|
"less": "^4.2.0",
|
||||||
|
|||||||
@ -11,6 +11,10 @@
|
|||||||
"import": "./dist/low-code-designer.js",
|
"import": "./dist/low-code-designer.js",
|
||||||
"require": "./dist/low-code-designer.cjs",
|
"require": "./dist/low-code-designer.cjs",
|
||||||
"types": "./dist/index.d.ts"
|
"types": "./dist/index.d.ts"
|
||||||
|
},
|
||||||
|
"./dist/": {
|
||||||
|
"import": "./dist/",
|
||||||
|
"require": "./dist/"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
|
|||||||
@ -70,7 +70,7 @@ export class BorderContainer extends Component<{
|
|||||||
const { host } = this.props;
|
const { host } = this.props;
|
||||||
|
|
||||||
host.designer.editor.eventBus.on('designer.dropLocation.change', (loc: DropLocation) => {
|
host.designer.editor.eventBus.on('designer.dropLocation.change', (loc: DropLocation) => {
|
||||||
let { target } = this.state;
|
const { target } = this.state;
|
||||||
if (target === loc?.target) return;
|
if (target === loc?.target) return;
|
||||||
this.setState({
|
this.setState({
|
||||||
target: loc?.target,
|
target: loc?.target,
|
||||||
|
|||||||
@ -45,7 +45,7 @@ export class GlobalContextMenuActions {
|
|||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
|
||||||
const actions: IPublicTypeContextMenuAction[] = [];
|
const actions: IPublicTypeContextMenuAction[] = [];
|
||||||
let contextMenu: ContextMenuActions = this.contextMenuActionsMap.values().next().value;
|
const contextMenu: ContextMenuActions = this.contextMenuActionsMap.values().next().value;
|
||||||
this.contextMenuActionsMap.forEach((contextMenu) => {
|
this.contextMenuActionsMap.forEach((contextMenu) => {
|
||||||
actions.push(...contextMenu.actions);
|
actions.push(...contextMenu.actions);
|
||||||
});
|
});
|
||||||
|
|||||||
@ -406,8 +406,8 @@ export class Designer {
|
|||||||
|
|
||||||
if (components) {
|
if (components) {
|
||||||
// 合并 assets
|
// 合并 assets
|
||||||
let assets = this.editor.get('assets') || {};
|
const assets = this.editor.get('assets') || {};
|
||||||
let newAssets = mergeAssets(assets, incrementalAssets);
|
const newAssets = mergeAssets(assets, incrementalAssets);
|
||||||
// 对于 assets 存在需要二次网络下载的过程,必须 await 等待结束之后,再进行事件触发
|
// 对于 assets 存在需要二次网络下载的过程,必须 await 等待结束之后,再进行事件触发
|
||||||
await this.editor.set('assets', newAssets);
|
await this.editor.set('assets', newAssets);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -191,7 +191,7 @@ export class Node<Schema extends IPublicTypeNodeSchema = IPublicTypeNodeSchema>
|
|||||||
}
|
}
|
||||||
|
|
||||||
@computed get title(): string | IPublicTypeI18nData | ReactElement {
|
@computed get title(): string | IPublicTypeI18nData | ReactElement {
|
||||||
let t = this.getExtraProp('title');
|
const t = this.getExtraProp('title');
|
||||||
// TODO: 暂时走不到这个分支
|
// TODO: 暂时走不到这个分支
|
||||||
// if (!t && this.componentMeta.descriptor) {
|
// if (!t && this.componentMeta.descriptor) {
|
||||||
// t = this.getProp(this.componentMeta.descriptor, false);
|
// t = this.getProp(this.componentMeta.descriptor, false);
|
||||||
@ -1164,7 +1164,7 @@ export class Node<Schema extends IPublicTypeNodeSchema = IPublicTypeNodeSchema>
|
|||||||
const isRGLContainerNode = this.isRGLContainer;
|
const isRGLContainerNode = this.isRGLContainer;
|
||||||
const isRGLNode = this.getParent()?.isRGLContainer as boolean;
|
const isRGLNode = this.getParent()?.isRGLContainer as boolean;
|
||||||
const isRGL = isRGLContainerNode || (isRGLNode && (!isContainerNode || !isEmptyNode));
|
const isRGL = isRGLContainerNode || (isRGLNode && (!isContainerNode || !isEmptyNode));
|
||||||
let rglNode = isRGLContainerNode ? this : isRGL ? this?.getParent() : null;
|
const rglNode = isRGLContainerNode ? this : isRGL ? this?.getParent() : null;
|
||||||
return { isContainerNode, isEmptyNode, isRGLContainerNode, isRGLNode, isRGL, rglNode };
|
return { isContainerNode, isEmptyNode, isRGLContainerNode, isRGLNode, isRGL, rglNode };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -646,7 +646,7 @@ export class Prop implements IProp, IPropParent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
const prop = isProp(value) ? value : new Prop(this, value, key);
|
const prop = isProp(value) ? value : new Prop(this, value, key);
|
||||||
let items = this._items! || [];
|
const items = this._items! || [];
|
||||||
if (this.type === 'list') {
|
if (this.type === 'list') {
|
||||||
if (!isValidArrayIndex(key)) {
|
if (!isValidArrayIndex(key)) {
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@ -138,13 +138,13 @@ export class Props implements Omit<IBaseModelProps<IProp>, | 'getExtraProp' | 'g
|
|||||||
if (this.items.length < 1) {
|
if (this.items.length < 1) {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
let allProps = {} as any;
|
const allProps = {} as any;
|
||||||
let props: any = {};
|
let props: any = {};
|
||||||
const extras: any = {};
|
const extras: any = {};
|
||||||
if (this.type === 'list') {
|
if (this.type === 'list') {
|
||||||
props = [];
|
props = [];
|
||||||
this.items.forEach((item) => {
|
this.items.forEach((item) => {
|
||||||
let value = item.export(stage);
|
const value = item.export(stage);
|
||||||
let name = item.key as string;
|
let name = item.key as string;
|
||||||
if (name && typeof name === 'string' && name.startsWith(EXTRA_KEY_PREFIX)) {
|
if (name && typeof name === 'string' && name.startsWith(EXTRA_KEY_PREFIX)) {
|
||||||
name = getOriginalExtraKey(name);
|
name = getOriginalExtraKey(name);
|
||||||
@ -159,9 +159,9 @@ export class Props implements Omit<IBaseModelProps<IProp>, | 'getExtraProp' | 'g
|
|||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
this.items.forEach((item) => {
|
this.items.forEach((item) => {
|
||||||
let name = item.key as string;
|
const name = item.key as string;
|
||||||
if (name == null || item.isUnset() || item.isVirtual()) return;
|
if (name == null || item.isUnset() || item.isVirtual()) return;
|
||||||
let value = item.export(stage);
|
const value = item.export(stage);
|
||||||
if (value != null) {
|
if (value != null) {
|
||||||
allProps[name] = value;
|
allProps[name] = value;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -14,7 +14,7 @@ function propertyNameRequiresQuotes(propertyName: string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function quoteString(str: string, { doubleQuote }: any) {
|
function quoteString(str: string, { doubleQuote }: any) {
|
||||||
return doubleQuote ? `"${str.replace(/"/gu, '\\"')}"` : `'${str.replace(/'/gu, "\\'")}'`;
|
return doubleQuote ? `"${str.replace(/"/gu, '\\"')}"` : `'${str.replace(/'/gu, '\\\'')}'`;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function valueToSource(
|
export function valueToSource(
|
||||||
|
|||||||
0
packages/editor-core/__tests__/command.spec.ts
Normal file
0
packages/editor-core/__tests__/command.spec.ts
Normal file
@ -11,6 +11,10 @@
|
|||||||
".": {
|
".": {
|
||||||
"import": "./dist/low-code-editor-core.js",
|
"import": "./dist/low-code-editor-core.js",
|
||||||
"types": "./dist/index.d.ts"
|
"types": "./dist/index.d.ts"
|
||||||
|
},
|
||||||
|
"./dist/": {
|
||||||
|
"import": "./dist/",
|
||||||
|
"require": "./dist/"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"sideEffects": [
|
"sideEffects": [
|
||||||
|
|||||||
@ -75,7 +75,7 @@ const KEYCODE_MAP: KeyMap = {
|
|||||||
219: '[',
|
219: '[',
|
||||||
220: '\\',
|
220: '\\',
|
||||||
221: ']',
|
221: ']',
|
||||||
222: "'",
|
222: '\'',
|
||||||
};
|
};
|
||||||
|
|
||||||
const SHIFT_MAP: CtrlKeyMap = {
|
const SHIFT_MAP: CtrlKeyMap = {
|
||||||
@ -93,7 +93,7 @@ const SHIFT_MAP: CtrlKeyMap = {
|
|||||||
_: '-',
|
_: '-',
|
||||||
'+': '=',
|
'+': '=',
|
||||||
':': ';',
|
':': ';',
|
||||||
'"': "'",
|
'"': '\'',
|
||||||
'<': ',',
|
'<': ',',
|
||||||
'>': '.',
|
'>': '.',
|
||||||
'?': '/',
|
'?': '/',
|
||||||
|
|||||||
@ -61,7 +61,7 @@ class GlobalLocale {
|
|||||||
}
|
}
|
||||||
if (!result) {
|
if (!result) {
|
||||||
// store 2: config from window
|
// store 2: config from window
|
||||||
let localeFromConfig: string = getConfig('locale');
|
const localeFromConfig: string = getConfig('locale');
|
||||||
if (localeFromConfig) {
|
if (localeFromConfig) {
|
||||||
result = languageMap[localeFromConfig] || localeFromConfig.replace('_', '-');
|
result = languageMap[localeFromConfig] || localeFromConfig.replace('_', '-');
|
||||||
logger.debug(`getting locale from config: ${result}`);
|
logger.debug(`getting locale from config: ${result}`);
|
||||||
@ -147,6 +147,6 @@ function hasLocalStorage(obj: any): obj is WindowLocalStorage {
|
|||||||
return obj.localStorage;
|
return obj.localStorage;
|
||||||
}
|
}
|
||||||
|
|
||||||
let globalLocale = new GlobalLocale();
|
const globalLocale = new GlobalLocale();
|
||||||
|
|
||||||
export { globalLocale };
|
export { globalLocale };
|
||||||
|
|||||||
@ -59,7 +59,7 @@ export class Title extends Component<IPublicTypeTitleProps> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
renderLabel = (label: string | IPublicTypeI18nData | ReactNode) => {
|
renderLabel = (label: string | IPublicTypeI18nData | ReactNode) => {
|
||||||
let { match, keywords } = this.props;
|
const { match, keywords } = this.props;
|
||||||
|
|
||||||
if (!label) {
|
if (!label) {
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@ -0,0 +1,5 @@
|
|||||||
|
import { defineProject } from 'vitest/config'
|
||||||
|
|
||||||
|
export default defineProject({
|
||||||
|
test: {}
|
||||||
|
})
|
||||||
@ -11,6 +11,10 @@
|
|||||||
"import": "./dist/low-code-editor-skeleton.js",
|
"import": "./dist/low-code-editor-skeleton.js",
|
||||||
"require": "./dist/low-code-editor-skeleton.cjs",
|
"require": "./dist/low-code-editor-skeleton.cjs",
|
||||||
"types": "./dist/index.d.ts"
|
"types": "./dist/index.d.ts"
|
||||||
|
},
|
||||||
|
"./dist/": {
|
||||||
|
"import": "./dist/",
|
||||||
|
"require": "./dist/"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"sideEffects": [
|
"sideEffects": [
|
||||||
|
|||||||
@ -251,8 +251,8 @@ class SettingFieldView extends Component<SettingFieldViewProps, SettingFieldView
|
|||||||
|
|
||||||
const value = this.value;
|
const value = this.value;
|
||||||
|
|
||||||
let onChangeAPI = extraProps?.onChange;
|
const onChangeAPI = extraProps?.onChange;
|
||||||
let stageName = this.stageName;
|
const stageName = this.stageName;
|
||||||
|
|
||||||
return createField(
|
return createField(
|
||||||
{
|
{
|
||||||
|
|||||||
@ -52,7 +52,7 @@ class Contents extends Component<{ area: Area; itemClassName?: string }> {
|
|||||||
right.push(content);
|
right.push(content);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
let children = [];
|
const children = [];
|
||||||
if (left && left.length) {
|
if (left && left.length) {
|
||||||
children.push(
|
children.push(
|
||||||
<div className="lc-workspace-sub-top-area-left lc-sub-top-area-left">{left}</div>,
|
<div className="lc-workspace-sub-top-area-left lc-sub-top-area-left">{left}</div>,
|
||||||
|
|||||||
@ -425,7 +425,10 @@ export class Skeleton implements Omit<IPublicApiSkeleton,
|
|||||||
return this.configTransducers;
|
return this.configTransducers;
|
||||||
}
|
}
|
||||||
|
|
||||||
add(config: IPublicTypeSkeletonConfig, extraConfig?: Record<string, any>): IWidget | Widget | Panel | Stage | Dock | PanelDock | undefined {
|
add(
|
||||||
|
config: IPublicTypeSkeletonConfig,
|
||||||
|
extraConfig?: Record<string, any>
|
||||||
|
): IWidget | Widget | Panel | Stage | Dock | PanelDock | undefined {
|
||||||
const registeredTransducers = this.getRegisteredConfigTransducers();
|
const registeredTransducers = this.getRegisteredConfigTransducers();
|
||||||
|
|
||||||
const parsedConfig = registeredTransducers.reduce((prevConfig, current) => {
|
const parsedConfig = registeredTransducers.reduce((prevConfig, current) => {
|
||||||
|
|||||||
@ -20,7 +20,7 @@ function transformStringToFunction(str: string) {
|
|||||||
if (leadingFnNameRe.test(str) && !leadingFnRe.test(str)) {
|
if (leadingFnNameRe.test(str) && !leadingFnRe.test(str)) {
|
||||||
str = `function ${str}`;
|
str = `function ${str}`;
|
||||||
}
|
}
|
||||||
let fnBody = `
|
const fnBody = `
|
||||||
return function() {
|
return function() {
|
||||||
const self = this;
|
const self = this;
|
||||||
try {
|
try {
|
||||||
|
|||||||
@ -11,6 +11,10 @@
|
|||||||
"import": "./dist/ali-low-code-engine.js",
|
"import": "./dist/ali-low-code-engine.js",
|
||||||
"require": "./dist/ali-low-code-engine.cjs",
|
"require": "./dist/ali-low-code-engine.cjs",
|
||||||
"types": "./dist/index.d.ts"
|
"types": "./dist/index.d.ts"
|
||||||
|
},
|
||||||
|
"./dist/": {
|
||||||
|
"import": "./dist/",
|
||||||
|
"require": "./dist/"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import { createElement } from 'react';
|
import { createElement } from 'react';
|
||||||
import { createRoot, type Root } from 'react-dom/client';
|
import { createRoot, type Root } from 'react-dom/client';
|
||||||
|
import { isPlainObject } from '@alilc/lowcode-utils';
|
||||||
import {
|
import {
|
||||||
globalContext,
|
globalContext,
|
||||||
Editor,
|
Editor,
|
||||||
@ -28,16 +29,13 @@ import {
|
|||||||
PluginPreference,
|
PluginPreference,
|
||||||
IDesigner,
|
IDesigner,
|
||||||
} from '@alilc/lowcode-designer';
|
} from '@alilc/lowcode-designer';
|
||||||
import {
|
import { Skeleton as InnerSkeleton, registerDefaults } from '@alilc/lowcode-editor-skeleton';
|
||||||
Skeleton as InnerSkeleton,
|
|
||||||
registerDefaults,
|
|
||||||
} from '@alilc/lowcode-editor-skeleton';
|
|
||||||
import {
|
import {
|
||||||
Workspace as InnerWorkspace,
|
Workspace as InnerWorkspace,
|
||||||
Workbench as WorkSpaceWorkbench,
|
Workbench as WorkSpaceWorkbench,
|
||||||
IWorkspace,
|
IWorkspace,
|
||||||
} from './workspace';
|
} from './workspace';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Hotkey,
|
Hotkey,
|
||||||
Project,
|
Project,
|
||||||
@ -54,10 +52,10 @@ import {
|
|||||||
CommonUI,
|
CommonUI,
|
||||||
Command,
|
Command,
|
||||||
} from './shell';
|
} from './shell';
|
||||||
import { isPlainObject } from '@alilc/lowcode-utils';
|
|
||||||
import './modules/live-editing';
|
import './modules/live-editing';
|
||||||
import * as classes from './modules/classes';
|
import * as classes from './modules/classes';
|
||||||
import symbols from './modules/symbols';
|
import symbols from './modules/symbols';
|
||||||
|
|
||||||
import { componentMetaParser } from './inner-plugins/component-meta-parser';
|
import { componentMetaParser } from './inner-plugins/component-meta-parser';
|
||||||
import { setterRegistry } from './inner-plugins/setter-registry';
|
import { setterRegistry } from './inner-plugins/setter-registry';
|
||||||
import { defaultPanelRegistry } from './inner-plugins/default-panel-registry';
|
import { defaultPanelRegistry } from './inner-plugins/default-panel-registry';
|
||||||
@ -66,13 +64,19 @@ import { builtinHotkey } from './inner-plugins/builtin-hotkey';
|
|||||||
import { defaultContextMenu } from './inner-plugins/default-context-menu';
|
import { defaultContextMenu } from './inner-plugins/default-context-menu';
|
||||||
import { CommandPlugin } from '@alilc/lowcode-plugin-command';
|
import { CommandPlugin } from '@alilc/lowcode-plugin-command';
|
||||||
import { OutlinePlugin } from '@alilc/lowcode-plugin-outline-pane';
|
import { OutlinePlugin } from '@alilc/lowcode-plugin-outline-pane';
|
||||||
import { version } from '../package.json'
|
import { version } from '../package.json';
|
||||||
|
|
||||||
|
import '@alilc/lowcode-editor-skeleton/dist/style.css';
|
||||||
|
|
||||||
export * from './modules/skeleton-types';
|
export * from './modules/skeleton-types';
|
||||||
export * from './modules/designer-types';
|
export * from './modules/designer-types';
|
||||||
export * from './modules/lowcode-types';
|
export * from './modules/lowcode-types';
|
||||||
|
|
||||||
async function registryInnerPlugin(designer: IDesigner, editor: IEditor, plugins: IPublicApiPlugins): Promise<IPublicTypeDisposable> {
|
async function registryInnerPlugin(
|
||||||
|
designer: IDesigner,
|
||||||
|
editor: IEditor,
|
||||||
|
plugins: IPublicApiPlugins
|
||||||
|
): Promise<IPublicTypeDisposable> {
|
||||||
// 注册一批内置插件
|
// 注册一批内置插件
|
||||||
const componentMetaParserPlugin = componentMetaParser(designer);
|
const componentMetaParserPlugin = componentMetaParser(designer);
|
||||||
const defaultPanelRegistryPlugin = defaultPanelRegistry(editor);
|
const defaultPanelRegistryPlugin = defaultPanelRegistry(editor);
|
||||||
@ -97,9 +101,13 @@ async function registryInnerPlugin(designer: IDesigner, editor: IEditor, plugins
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const innerWorkspace: IWorkspace = new InnerWorkspace(registryInnerPlugin, shellModelFactory);
|
const innerWorkspace: IWorkspace = new InnerWorkspace(
|
||||||
|
registryInnerPlugin,
|
||||||
|
shellModelFactory
|
||||||
|
);
|
||||||
const workspace: IPublicApiWorkspace = new Workspace(innerWorkspace);
|
const workspace: IPublicApiWorkspace = new Workspace(innerWorkspace);
|
||||||
const editor = new Editor();
|
const editor = new Editor();
|
||||||
|
|
||||||
globalContext.register(editor, Editor);
|
globalContext.register(editor, Editor);
|
||||||
globalContext.register(editor, 'editor');
|
globalContext.register(editor, 'editor');
|
||||||
globalContext.register(innerWorkspace, 'workspace');
|
globalContext.register(innerWorkspace, 'workspace');
|
||||||
@ -121,24 +129,30 @@ const skeleton = new Skeleton(innerSkeleton, 'any', false);
|
|||||||
const innerSetters = new InnerSetters();
|
const innerSetters = new InnerSetters();
|
||||||
const setters = new Setters(innerSetters);
|
const setters = new Setters(innerSetters);
|
||||||
const innerCommand = new InnerCommand();
|
const innerCommand = new InnerCommand();
|
||||||
const command = new Command(innerCommand, engineContext as IPublicModelPluginContext);
|
const command = new Command(
|
||||||
|
innerCommand,
|
||||||
|
engineContext as IPublicModelPluginContext
|
||||||
|
);
|
||||||
const material = new Material(editor);
|
const material = new Material(editor);
|
||||||
const commonUI = new CommonUI(editor);
|
const commonUI = new CommonUI(editor);
|
||||||
|
|
||||||
editor.set('project', project);
|
editor.set('project', project);
|
||||||
editor.set('setters' as any, setters);
|
editor.set('setters' as any, setters);
|
||||||
editor.set('material', material);
|
editor.set('material', material);
|
||||||
editor.set('innerHotkey', innerHotkey);
|
editor.set('innerHotkey', innerHotkey);
|
||||||
|
|
||||||
const config = new Config(engineConfig);
|
const config = new Config(engineConfig);
|
||||||
const event = new Event(commonEvent, { prefix: 'common' });
|
const event = new Event(commonEvent, { prefix: 'common' });
|
||||||
const logger = new Logger({ level: 'warn', bizName: 'common' });
|
const logger = new Logger({ level: 'warn', bizName: 'common' });
|
||||||
const common = new Common(editor, innerSkeleton);
|
const common = new Common(editor, innerSkeleton);
|
||||||
const canvas = new Canvas(editor);
|
const canvas = new Canvas(editor);
|
||||||
let plugins: Plugins;
|
|
||||||
|
|
||||||
const pluginContextApiAssembler: ILowCodePluginContextApiAssembler = {
|
const pluginContextApiAssembler: ILowCodePluginContextApiAssembler = {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
assembleApis: (
|
||||||
assembleApis: (context: ILowCodePluginContextPrivate, pluginName: string, meta: IPublicTypePluginMeta) => {
|
context: ILowCodePluginContextPrivate,
|
||||||
|
pluginName: string,
|
||||||
|
meta: IPublicTypePluginMeta
|
||||||
|
) => {
|
||||||
context.hotkey = hotkey;
|
context.hotkey = hotkey;
|
||||||
context.project = project;
|
context.project = project;
|
||||||
context.skeleton = new Skeleton(innerSkeleton, pluginName, false);
|
context.skeleton = new Skeleton(innerSkeleton, pluginName, false);
|
||||||
@ -154,7 +168,8 @@ const pluginContextApiAssembler: ILowCodePluginContextApiAssembler = {
|
|||||||
context.logger = new Logger({ level: 'warn', bizName: `plugin:${pluginName}` });
|
context.logger = new Logger({ level: 'warn', bizName: `plugin:${pluginName}` });
|
||||||
context.workspace = workspace;
|
context.workspace = workspace;
|
||||||
context.commonUI = commonUI;
|
context.commonUI = commonUI;
|
||||||
context.command = new Command(innerCommand, context as IPublicModelPluginContext, {
|
context.command = new Command(
|
||||||
|
innerCommand, context as IPublicModelPluginContext, {
|
||||||
commandScope,
|
commandScope,
|
||||||
});
|
});
|
||||||
context.registerLevel = IPublicEnumPluginRegisterLevel.Default;
|
context.registerLevel = IPublicEnumPluginRegisterLevel.Default;
|
||||||
@ -164,7 +179,7 @@ const pluginContextApiAssembler: ILowCodePluginContextApiAssembler = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const innerPlugins = new LowCodePluginManager(pluginContextApiAssembler);
|
const innerPlugins = new LowCodePluginManager(pluginContextApiAssembler);
|
||||||
plugins = new Plugins(innerPlugins).toProxy();
|
const plugins = new Plugins(innerPlugins).toProxy();
|
||||||
editor.set('innerPlugins' as any, innerPlugins);
|
editor.set('innerPlugins' as any, innerPlugins);
|
||||||
editor.set('plugins' as any, plugins);
|
editor.set('plugins' as any, plugins);
|
||||||
|
|
||||||
@ -198,19 +213,25 @@ export {
|
|||||||
commonUI,
|
commonUI,
|
||||||
command,
|
command,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// declare this is open-source version
|
// declare this is open-source version
|
||||||
|
/**
|
||||||
|
* @deprecated
|
||||||
|
*/
|
||||||
export const isOpenSource = true;
|
export const isOpenSource = true;
|
||||||
|
engineConfig.set('isOpenSource', isOpenSource);
|
||||||
|
|
||||||
|
engineConfig.set('ENGINE_VERSION', version);
|
||||||
|
export { version };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated
|
||||||
|
*/
|
||||||
export const __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED = {
|
export const __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED = {
|
||||||
symbols,
|
symbols,
|
||||||
classes,
|
classes,
|
||||||
};
|
};
|
||||||
engineConfig.set('isOpenSource', isOpenSource);
|
|
||||||
|
|
||||||
// container which will host LowCodeEngine DOM
|
|
||||||
let engineContainer: HTMLElement;
|
|
||||||
|
|
||||||
export { version }
|
|
||||||
engineConfig.set('ENGINE_VERSION', version);
|
|
||||||
|
|
||||||
const pluginPromise = registryInnerPlugin(designer, editor, plugins);
|
const pluginPromise = registryInnerPlugin(designer, editor, plugins);
|
||||||
|
|
||||||
@ -219,10 +240,14 @@ let root: Root | undefined;
|
|||||||
export async function init(
|
export async function init(
|
||||||
container?: HTMLElement,
|
container?: HTMLElement,
|
||||||
options?: IPublicTypeEngineOptions,
|
options?: IPublicTypeEngineOptions,
|
||||||
pluginPreference?: PluginPreference,
|
pluginPreference?: PluginPreference
|
||||||
) {
|
) {
|
||||||
await destroy();
|
await destroy();
|
||||||
|
|
||||||
|
// container which will host LowCodeEngine DOM
|
||||||
|
let engineContainer: HTMLElement;
|
||||||
let engineOptions = null;
|
let engineOptions = null;
|
||||||
|
|
||||||
if (isPlainObject(container)) {
|
if (isPlainObject(container)) {
|
||||||
engineOptions = container;
|
engineOptions = container;
|
||||||
engineContainer = document.createElement('div');
|
engineContainer = document.createElement('div');
|
||||||
@ -237,6 +262,7 @@ export async function init(
|
|||||||
document.body.appendChild(engineContainer);
|
document.body.appendChild(engineContainer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
engineConfig.setEngineOptions(engineOptions as any);
|
engineConfig.setEngineOptions(engineOptions as any);
|
||||||
|
|
||||||
const { Workbench } = common.skeletonCabin;
|
const { Workbench } = common.skeletonCabin;
|
||||||
@ -245,15 +271,15 @@ export async function init(
|
|||||||
disposeFun && disposeFun();
|
disposeFun && disposeFun();
|
||||||
|
|
||||||
if (!root) {
|
if (!root) {
|
||||||
root = createRoot(
|
root = createRoot(engineContainer);
|
||||||
engineContainer,
|
root.render(
|
||||||
);
|
createElement(WorkSpaceWorkbench, {
|
||||||
root.render(createElement(WorkSpaceWorkbench, {
|
|
||||||
workspace: innerWorkspace,
|
workspace: innerWorkspace,
|
||||||
// skeleton: workspace.skeleton,
|
// skeleton: workspace.skeleton,
|
||||||
className: 'engine-main',
|
className: 'engine-main',
|
||||||
topAreaItemClassName: 'engine-actionitem',
|
topAreaItemClassName: 'engine-actionitem',
|
||||||
}))
|
})
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
innerWorkspace.enableAutoOpenFirstWindow = engineConfig.get('enableAutoOpenFirstWindow', true);
|
innerWorkspace.enableAutoOpenFirstWindow = engineConfig.get('enableAutoOpenFirstWindow', true);
|
||||||
@ -267,12 +293,14 @@ export async function init(
|
|||||||
await plugins.init(pluginPreference as any);
|
await plugins.init(pluginPreference as any);
|
||||||
|
|
||||||
if (!root) {
|
if (!root) {
|
||||||
root = createRoot(engineContainer)
|
root = createRoot(engineContainer);
|
||||||
root.render(createElement(Workbench, {
|
root.render(
|
||||||
|
createElement(Workbench, {
|
||||||
skeleton: innerSkeleton,
|
skeleton: innerSkeleton,
|
||||||
className: 'engine-main',
|
className: 'engine-main',
|
||||||
topAreaItemClassName: 'engine-actionitem',
|
topAreaItemClassName: 'engine-actionitem',
|
||||||
}))
|
})
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -280,7 +308,9 @@ export async function destroy() {
|
|||||||
// remove all documents
|
// remove all documents
|
||||||
const { documents } = project;
|
const { documents } = project;
|
||||||
if (Array.isArray(documents) && documents.length > 0) {
|
if (Array.isArray(documents) && documents.length > 0) {
|
||||||
documents.forEach(((doc: IPublicModelDocumentModel) => project.removeDocument(doc)));
|
documents.forEach(
|
||||||
|
(doc: IPublicModelDocumentModel) => project.removeDocument(doc)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: delete plugins except for core plugins
|
// TODO: delete plugins except for core plugins
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
import { version } from './engine-core';
|
import { version } from './engine-core';
|
||||||
|
|
||||||
export * from './engine-core';
|
export * from './engine-core';
|
||||||
|
|
||||||
console.log(
|
console.log(
|
||||||
`%c AliLowCodeEngine %c v${version} `,
|
`%c AliLowCodeEngine %c v${version} `,
|
||||||
'padding: 2px 1px; border-radius: 3px 0 0 3px; color: #fff; background: #606060; font-weight: bold;',
|
'padding: 2px 1px; border-radius: 3px 0 0 3px; color: #fff; background: #606060; font-weight: bold;',
|
||||||
|
|||||||
@ -328,7 +328,7 @@ export const builtinHotkey = (ctx: IPublicModelPluginContext) => {
|
|||||||
if (!target) {
|
if (!target) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let canAddComponentsTree = componentsTree.filter((node: IPublicModelNode) => {
|
const canAddComponentsTree = componentsTree.filter((node: IPublicModelNode) => {
|
||||||
const dragNodeObject: IPublicTypeDragNodeObject = {
|
const dragNodeObject: IPublicTypeDragNodeObject = {
|
||||||
type: IPublicEnumDragObjectType.Node,
|
type: IPublicEnumDragObjectType.Node,
|
||||||
nodes: [node],
|
nodes: [node],
|
||||||
|
|||||||
@ -129,7 +129,7 @@ export const defaultContextMenu = (ctx: IPublicModelPluginContext) => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (parent) {
|
if (parent) {
|
||||||
let canAddNodes = nodeSchema.filter((nodeSchema: IPublicTypeNodeSchema) => {
|
const canAddNodes = nodeSchema.filter((nodeSchema: IPublicTypeNodeSchema) => {
|
||||||
const dragNodeObject: IPublicTypeDragNodeDataObject = {
|
const dragNodeObject: IPublicTypeDragNodeDataObject = {
|
||||||
type: IPublicEnumDragObjectType.NodeData,
|
type: IPublicEnumDragObjectType.NodeData,
|
||||||
data: nodeSchema,
|
data: nodeSchema,
|
||||||
@ -177,7 +177,7 @@ export const defaultContextMenu = (ctx: IPublicModelPluginContext) => {
|
|||||||
if (nodeSchema.length === 0) {
|
if (nodeSchema.length === 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let canAddNodes = nodeSchema.filter((nodeSchema: IPublicTypeNodeSchema) => {
|
const canAddNodes = nodeSchema.filter((nodeSchema: IPublicTypeNodeSchema) => {
|
||||||
const dragNodeObject: IPublicTypeDragNodeDataObject = {
|
const dragNodeObject: IPublicTypeDragNodeDataObject = {
|
||||||
type: IPublicEnumDragObjectType.NodeData,
|
type: IPublicEnumDragObjectType.NodeData,
|
||||||
data: nodeSchema,
|
data: nodeSchema,
|
||||||
|
|||||||
@ -6,11 +6,13 @@ export const setterRegistry = (ctx: IPublicModelPluginContext) => {
|
|||||||
init() {
|
init() {
|
||||||
const { config } = ctx;
|
const { config } = ctx;
|
||||||
if (config.get('disableDefaultSetters')) return;
|
if (config.get('disableDefaultSetters')) return;
|
||||||
// todo: 互相依赖
|
|
||||||
// const builtinSetters = require('@alilc/lowcode-engine-ext')?.setters;
|
// const builtinSetters = require('@alilc/lowcode-engine-ext')?.setters;
|
||||||
// if (builtinSetters) {
|
// @ts-expect-error: todo remove
|
||||||
// ctx.setters.registerSetter(builtinSetters);
|
const builtinSetters = window.AliLowCodeEngineExt?.setters;
|
||||||
// }
|
if (builtinSetters) {
|
||||||
|
ctx.setters.registerSetter(builtinSetters);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@ -13,4 +13,3 @@ export {
|
|||||||
SkeletonItem,
|
SkeletonItem,
|
||||||
} from '../shell';
|
} from '../shell';
|
||||||
export { Node as InnerNode } from '@alilc/lowcode-designer';
|
export { Node as InnerNode } from '@alilc/lowcode-designer';
|
||||||
|
|
||||||
|
|||||||
@ -26,13 +26,6 @@ export class Hotkey implements IPublicApiHotkey {
|
|||||||
return this[hotkeySymbol].callBacks;
|
return this[hotkeySymbol].callBacks;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated
|
|
||||||
*/
|
|
||||||
get callBacks() {
|
|
||||||
return this.callbacks;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 绑定快捷键
|
* 绑定快捷键
|
||||||
* @param combos 快捷键,格式如:['command + s'] 、['ctrl + shift + s'] 等
|
* @param combos 快捷键,格式如:['command + s'] 、['ctrl + shift + s'] 等
|
||||||
|
|||||||
@ -141,7 +141,7 @@ export class Material implements IPublicApiMaterial {
|
|||||||
getComponentMetasMap(): Map<string, IPublicModelComponentMeta> {
|
getComponentMetasMap(): Map<string, IPublicModelComponentMeta> {
|
||||||
const map = new Map<string, IPublicModelComponentMeta>();
|
const map = new Map<string, IPublicModelComponentMeta>();
|
||||||
const originalMap = this[designerSymbol].getComponentMetasMap();
|
const originalMap = this[designerSymbol].getComponentMetasMap();
|
||||||
for (let componentName of originalMap.keys()) {
|
for (const componentName of originalMap.keys()) {
|
||||||
map.set(componentName, this.getComponentMeta(componentName)!);
|
map.set(componentName, this.getComponentMeta(componentName)!);
|
||||||
}
|
}
|
||||||
return map;
|
return map;
|
||||||
|
|||||||
@ -121,7 +121,7 @@ export class DocumentModel implements IPublicModelDocumentModel {
|
|||||||
*/
|
*/
|
||||||
get nodesMap(): Map<string, IPublicModelNode> {
|
get nodesMap(): Map<string, IPublicModelNode> {
|
||||||
const map = new Map<string, IPublicModelNode>();
|
const map = new Map<string, IPublicModelNode>();
|
||||||
for (let id of this[documentSymbol].nodesMap.keys()) {
|
for (const id of this[documentSymbol].nodesMap.keys()) {
|
||||||
map.set(id, this.getNodeById(id)!);
|
map.set(id, this.getNodeById(id)!);
|
||||||
}
|
}
|
||||||
return map;
|
return map;
|
||||||
@ -230,7 +230,7 @@ export class DocumentModel implements IPublicModelDocumentModel {
|
|||||||
dropTarget: IPublicModelNode,
|
dropTarget: IPublicModelNode,
|
||||||
dragObject: IPublicTypeDragNodeObject | IPublicTypeDragNodeDataObject,
|
dragObject: IPublicTypeDragNodeObject | IPublicTypeDragNodeDataObject,
|
||||||
): boolean {
|
): boolean {
|
||||||
let innerDragObject = dragObject;
|
const innerDragObject = dragObject;
|
||||||
if (isDragNodeObject(dragObject)) {
|
if (isDragNodeObject(dragObject)) {
|
||||||
innerDragObject.nodes = innerDragObject.nodes?.map(
|
innerDragObject.nodes = innerDragObject.nodes?.map(
|
||||||
(node: IPublicModelNode) => ((node as any)[nodeSymbol] || node),
|
(node: IPublicModelNode) => ((node as any)[nodeSymbol] || node),
|
||||||
|
|||||||
@ -1,8 +1,5 @@
|
|||||||
import { defineConfig } from 'vitest/config'
|
import { defineProject } from 'vitest/config'
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineProject({
|
||||||
test: {
|
test: {}
|
||||||
include: ['tests/*.spec.ts'],
|
|
||||||
environment: 'jsdom'
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|||||||
@ -66,7 +66,7 @@ export class TreeMaster {
|
|||||||
'en-US': enUS,
|
'en-US': enUS,
|
||||||
'zh-CN': zhCN,
|
'zh-CN': zhCN,
|
||||||
});
|
});
|
||||||
let _pluginContext: IOutlinePanelPluginContext = Object.assign(pluginContext, {
|
const _pluginContext: IOutlinePanelPluginContext = Object.assign(pluginContext, {
|
||||||
intl,
|
intl,
|
||||||
intlNode,
|
intlNode,
|
||||||
getLocale,
|
getLocale,
|
||||||
|
|||||||
@ -232,7 +232,7 @@ export default class TreeNodeView extends PureComponent<{
|
|||||||
'condition-flow': this.state.conditionFlow,
|
'condition-flow': this.state.conditionFlow,
|
||||||
highlight: this.state.highlight,
|
highlight: this.state.highlight,
|
||||||
});
|
});
|
||||||
let shouldShowModalTreeNode: boolean = this.shouldShowModalTreeNode();
|
const shouldShowModalTreeNode: boolean = this.shouldShowModalTreeNode();
|
||||||
|
|
||||||
// filter 处理
|
// filter 处理
|
||||||
const { filterWorking, matchChild, matchSelf } = this.state;
|
const { filterWorking, matchChild, matchSelf } = this.state;
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@alilc/lowcode-react-renderer",
|
"name": "@alilc/lowcode-react-renderer",
|
||||||
"version": "2.0.0-beta.0",
|
"version": "2.0.0-alpha.0",
|
||||||
"description": "react renderer for ali lowcode engine",
|
"description": "react renderer for ali lowcode engine",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"bugs": "https://github.com/alibaba/lowcode-engine/issues",
|
"bugs": "https://github.com/alibaba/lowcode-engine/issues",
|
||||||
@ -18,7 +18,7 @@
|
|||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build:target": "vite build",
|
"build:target": "vite build",
|
||||||
"build:dts": "tsc -p tsconfig.declaration.json && node ../../scripts/rollup-dts.mjs",
|
"build:dts": "tsc -p tsconfig.declaration.json && node ../../scripts/rollup-dts.js",
|
||||||
"test": "vitest"
|
"test": "vitest"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|||||||
@ -3,3 +3,5 @@ import { createComponent as internalCreate, ComponentOptions } from '../componen
|
|||||||
export function createComponent(options: ComponentOptions) {
|
export function createComponent(options: ComponentOptions) {
|
||||||
return internalCreate(options);
|
return internalCreate(options);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type { ComponentOptions };
|
||||||
|
|||||||
@ -81,7 +81,7 @@ export function compile(tokens: Token[], values: Record<string, any> | any[] = {
|
|||||||
break;
|
break;
|
||||||
case 'unknown':
|
case 'unknown':
|
||||||
if (process.env.NODE_ENV !== 'production') {
|
if (process.env.NODE_ENV !== 'production') {
|
||||||
console.warn(`Detect 'unknown' type of token!`);
|
console.warn('Detect \'unknown\' type of token!');
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -98,7 +98,7 @@ async function appendExternalCss(
|
|||||||
}
|
}
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
let el: HTMLLinkElement = document.createElement('link');
|
const el: HTMLLinkElement = document.createElement('link');
|
||||||
el.rel = 'stylesheet';
|
el.rel = 'stylesheet';
|
||||||
el.href = url;
|
el.href = url;
|
||||||
|
|
||||||
@ -122,7 +122,7 @@ export async function appendExternalStyle(
|
|||||||
root: HTMLElement = document.head,
|
root: HTMLElement = document.head,
|
||||||
): Promise<HTMLElement> {
|
): Promise<HTMLElement> {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
let el: HTMLStyleElement = document.createElement('style');
|
const el: HTMLStyleElement = document.createElement('style');
|
||||||
el.innerText = cssText;
|
el.innerText = cssText;
|
||||||
|
|
||||||
el.addEventListener(
|
el.addEventListener(
|
||||||
|
|||||||
@ -1,9 +1,9 @@
|
|||||||
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
||||||
import { useEvent, createHookStore, type HookStore } from '../../src/utils/hook';
|
import { createEvent, createHookStore, type HookStore } from '../../src/utils/hook';
|
||||||
|
|
||||||
describe('event', () => {
|
describe('event', () => {
|
||||||
it("event's listener ops", () => {
|
it('event\'s listener ops', () => {
|
||||||
const event = useEvent();
|
const event = createEvent();
|
||||||
const fn = () => {};
|
const fn = () => {};
|
||||||
event.add(fn);
|
event.add(fn);
|
||||||
|
|
||||||
@ -1,17 +1,18 @@
|
|||||||
{
|
{
|
||||||
"name": "@alilc/lowcode-renderer-core",
|
"name": "@alilc/lowcode-renderer-core",
|
||||||
"version": "2.0.0-beta.0",
|
"version": "2.0.0-alpha.0",
|
||||||
"description": "",
|
"description": "core package for lowCode renderer",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"bugs": "https://github.com/alibaba/lowcode-engine/issues",
|
"bugs": "https://github.com/alibaba/lowcode-engine/issues",
|
||||||
"homepage": "https://github.com/alibaba/lowcode-engine/#readme",
|
"homepage": "https://github.com/alibaba/lowcode-engine/#readme",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"main": "dist/low-code-renderer-core.js",
|
"main": "dist/low-code-renderer-core.cjs",
|
||||||
"module": "dist/low-code-renderer-core.js",
|
"module": "dist/low-code-renderer-core.js",
|
||||||
"types": "dist/index.d.ts",
|
"types": "dist/index.d.ts",
|
||||||
"exports": {
|
"exports": {
|
||||||
".": {
|
".": {
|
||||||
"import": "./dist/low-code-renderer-core.js",
|
"import": "./dist/low-code-renderer-core.js",
|
||||||
|
"require": "./dist/low-code-renderer-core.cjs",
|
||||||
"types": "./dist/index.d.ts"
|
"types": "./dist/index.d.ts"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -22,7 +23,7 @@
|
|||||||
],
|
],
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build:target": "vite build",
|
"build:target": "vite build",
|
||||||
"build:dts": "tsc -p tsconfig.declaration.json && node ../../scripts/rollup-dts.mjs",
|
"build:dts": "tsc -p tsconfig.declaration.json && node ../../scripts/rollup-dts.js",
|
||||||
"test": "vitest --run",
|
"test": "vitest --run",
|
||||||
"test:watch": "vitest"
|
"test:watch": "vitest"
|
||||||
},
|
},
|
||||||
|
|||||||
@ -5,7 +5,7 @@ export { createCodeRuntime, createScope } from './code-runtime';
|
|||||||
export { definePlugin } from './plugin';
|
export { definePlugin } from './plugin';
|
||||||
export { createWidget } from './widget';
|
export { createWidget } from './widget';
|
||||||
export { createContainer } from './container';
|
export { createContainer } from './container';
|
||||||
export { createHookStore, useEvent } from './utils/hook';
|
export { createHookStore, createEvent } from './utils/hook';
|
||||||
export * from './utils/type-guard';
|
export * from './utils/type-guard';
|
||||||
export * from './utils/value';
|
export * from './utils/value';
|
||||||
export * from './widget';
|
export * from './widget';
|
||||||
|
|||||||
@ -8,7 +8,7 @@ export class RuntimeError extends Error {
|
|||||||
message: string,
|
message: string,
|
||||||
) {
|
) {
|
||||||
super(message);
|
super(message);
|
||||||
appBoosts.hookStore.call(`app:error`, this);
|
appBoosts.hookStore.call('app:error', this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -2,7 +2,7 @@ import type { AnyFunction } from '../types';
|
|||||||
|
|
||||||
export type EventName = string | number | symbol;
|
export type EventName = string | number | symbol;
|
||||||
|
|
||||||
export function useEvent<T = AnyFunction>() {
|
export function createEvent<T = AnyFunction>() {
|
||||||
let events: T[] = [];
|
let events: T[] = [];
|
||||||
|
|
||||||
function add(fn: T) {
|
function add(fn: T) {
|
||||||
@ -31,7 +31,7 @@ export function useEvent<T = AnyFunction>() {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export type Event<F = AnyFunction> = ReturnType<typeof useEvent<F>>;
|
export type Event<F = AnyFunction> = ReturnType<typeof createEvent<F>>;
|
||||||
|
|
||||||
export type HookCallback = (...args: any) => Promise<any> | any;
|
export type HookCallback = (...args: any) => Promise<any> | any;
|
||||||
|
|
||||||
@ -93,7 +93,7 @@ export function createHookStore<
|
|||||||
|
|
||||||
let hooks = hooksMap.get(name);
|
let hooks = hooksMap.get(name);
|
||||||
if (!hooks) {
|
if (!hooks) {
|
||||||
hooks = useEvent();
|
hooks = createEvent();
|
||||||
hooksMap.set(name, hooks);
|
hooksMap.set(name, hooks);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -4,5 +4,6 @@ import baseConfigFn from '../../vite.base.config'
|
|||||||
export default defineConfig(async () => {
|
export default defineConfig(async () => {
|
||||||
return baseConfigFn({
|
return baseConfigFn({
|
||||||
name: 'LowCodeRendererCore',
|
name: 'LowCodeRendererCore',
|
||||||
|
defaultFormats: ['es', 'cjs']
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|||||||
7
packages/renderer-router/__tests__/matcher.spec.ts
Normal file
7
packages/renderer-router/__tests__/matcher.spec.ts
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
import { createRouterMatcher } from '../src/matcher';
|
||||||
|
|
||||||
|
describe('RouterMatcher', () => {
|
||||||
|
it('', () => {
|
||||||
|
|
||||||
|
});
|
||||||
|
});
|
||||||
@ -1,22 +1,24 @@
|
|||||||
{
|
{
|
||||||
"name": "@alilc/lowcode-renderer-router",
|
"name": "@alilc/lowcode-renderer-router",
|
||||||
"version": "1.0.0-beta.0",
|
"version": "1.0.0-alpha.0",
|
||||||
"description": "",
|
"description": "router for lowCode renderer",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"bugs": "https://github.com/alibaba/lowcode-engine/issues",
|
"bugs": "https://github.com/alibaba/lowcode-engine/issues",
|
||||||
"homepage": "https://github.com/alibaba/lowcode-engine/#readme",
|
"homepage": "https://github.com/alibaba/lowcode-engine/#readme",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"main": "dist/low-code-runtime-router.cjs",
|
||||||
"module": "dist/low-code-runtime-router.js",
|
"module": "dist/low-code-runtime-router.js",
|
||||||
"types": "dist/index.d.ts",
|
"types": "dist/index.d.ts",
|
||||||
"exports": {
|
"exports": {
|
||||||
".": {
|
".": {
|
||||||
"import": "./dist/low-code-runtime-router.js",
|
"import": "./dist/low-code-runtime-router.js",
|
||||||
|
"require": "./dist/low-code-runtime-router.cjs",
|
||||||
"types": "./dist/index.d.ts"
|
"types": "./dist/index.d.ts"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build:target": "vite build",
|
"build:target": "vite build",
|
||||||
"build:dts": "tsc -p tsconfig.declaration.json && node ../../scripts/rollup-dts.mjs",
|
"build:dts": "tsc -p tsconfig.declaration.json && node ../../scripts/rollup-dts.js",
|
||||||
"test": "vitest"
|
"test": "vitest"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { useEvent } from '@alilc/lowcode-renderer-core';
|
import { createEvent } from '@alilc/lowcode-renderer-core';
|
||||||
|
|
||||||
export type HistoryState = History['state'];
|
export type HistoryState = History['state'];
|
||||||
export type HistoryLocation = string;
|
export type HistoryLocation = string;
|
||||||
@ -166,8 +166,8 @@ export function createBrowserHistory(base?: string): RouterHistory {
|
|||||||
currentLocation = to;
|
currentLocation = to;
|
||||||
}
|
}
|
||||||
|
|
||||||
let listeners = useEvent<NavigationCallback>();
|
const listeners = createEvent<NavigationCallback>();
|
||||||
let teardowns = useEvent<() => void>();
|
const teardowns = createEvent<() => void>();
|
||||||
|
|
||||||
let pauseState: HistoryLocation | null = null;
|
let pauseState: HistoryLocation | null = null;
|
||||||
|
|
||||||
@ -285,7 +285,7 @@ function createCurrentLocation(base: string, location: Location) {
|
|||||||
// hash bases like #, /#, #/, #!, #!/, /#!/, or even /folder#end
|
// hash bases like #, /#, #/, #!, #!/, /#!/, or even /folder#end
|
||||||
const hashPos = base.indexOf('#');
|
const hashPos = base.indexOf('#');
|
||||||
if (hashPos > -1) {
|
if (hashPos > -1) {
|
||||||
let slicePos = hash.includes(base.slice(hashPos)) ? base.slice(hashPos).length : 1;
|
const slicePos = hash.includes(base.slice(hashPos)) ? base.slice(hashPos).length : 1;
|
||||||
let pathFromHash = hash.slice(slicePos);
|
let pathFromHash = hash.slice(slicePos);
|
||||||
// prepend the starting slash to hash so the url starts with /#
|
// prepend the starting slash to hash so the url starts with /#
|
||||||
if (pathFromHash[0] !== '/') pathFromHash = '/' + pathFromHash;
|
if (pathFromHash[0] !== '/') pathFromHash = '/' + pathFromHash;
|
||||||
@ -348,7 +348,7 @@ export function createMemoryHistory(base = ''): RouterHistory {
|
|||||||
historyStack.push({ location, state });
|
historyStack.push({ location, state });
|
||||||
}
|
}
|
||||||
|
|
||||||
const listeners = useEvent<NavigationCallback>();
|
const listeners = createEvent<NavigationCallback>();
|
||||||
|
|
||||||
function triggerListeners(
|
function triggerListeners(
|
||||||
to: HistoryLocation,
|
to: HistoryLocation,
|
||||||
|
|||||||
@ -1,9 +1,11 @@
|
|||||||
|
// refer from https://github.com/vuejs/router/blob/main/packages/router/src/matcher/index.ts
|
||||||
|
|
||||||
import { type PlainObject, type RawLocation } from '@alilc/lowcode-renderer-core';
|
import { type PlainObject, type RawLocation } from '@alilc/lowcode-renderer-core';
|
||||||
import { pick } from 'lodash-es';
|
import { pick } from 'lodash-es';
|
||||||
import { createRouteRecordMatcher, type RouteRecordMatcher } from './utils/record-matcher';
|
import { createRouteRecordMatcher, type RouteRecordMatcher } from './utils/record-matcher';
|
||||||
import { type PathParserOptions } from './utils/path-parser';
|
import { type PathParserOptions, type PathParams, comparePathParserScore } from './utils/path-parser';
|
||||||
|
|
||||||
import type { RouteRecord, RouteParams, RouteLocationNormalized } from './types';
|
import type { RouteRecord, RouteLocationNormalized } from './types';
|
||||||
|
|
||||||
export interface RouteRecordNormalized {
|
export interface RouteRecordNormalized {
|
||||||
/**
|
/**
|
||||||
@ -58,7 +60,9 @@ export interface RouterMatcher {
|
|||||||
* @param location - MatcherLocationRaw to resolve to a url
|
* @param location - MatcherLocationRaw to resolve to a url
|
||||||
* @param currentLocation - MatcherLocation of the current location
|
* @param currentLocation - MatcherLocation of the current location
|
||||||
*/
|
*/
|
||||||
resolve: (location: RawLocation, currentLocation: MatcherLocation) => MatcherLocation;
|
resolve: (
|
||||||
|
location: RawLocation, currentLocation: MatcherLocation
|
||||||
|
) => MatcherLocation;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createRouterMatcher(
|
export function createRouterMatcher(
|
||||||
@ -83,7 +87,7 @@ export function createRouterMatcher(
|
|||||||
const parentPath = parent.record.path;
|
const parentPath = parent.record.path;
|
||||||
const connectingSlash = parentPath[parentPath.length - 1] === '/' ? '' : '/';
|
const connectingSlash = parentPath[parentPath.length - 1] === '/' ? '' : '/';
|
||||||
|
|
||||||
normalizedRecord.path = parent.record.path + (path && connectingSlash + path);
|
normalizedRecord.path = parent.record.path + (path ? connectingSlash + path : '');
|
||||||
}
|
}
|
||||||
|
|
||||||
const matcher = createRouteRecordMatcher(normalizedRecord, parent, options);
|
const matcher = createRouteRecordMatcher(normalizedRecord, parent, options);
|
||||||
@ -96,7 +100,16 @@ export function createRouterMatcher(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (matcher.record.path) {
|
if (matcher.record.path) {
|
||||||
matchers.push(matcher);
|
let i = 0;
|
||||||
|
while (
|
||||||
|
i < matchers.length &&
|
||||||
|
comparePathParserScore(matcher, matchers[i]) >= 0 &&
|
||||||
|
(matcher.record.path !== matchers[i].record.path ||
|
||||||
|
!isRecordChildOf(matcher, matchers[i]))
|
||||||
|
) {
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
matchers.splice(i, 0, matcher);
|
||||||
|
|
||||||
if (matcher.record.name) {
|
if (matcher.record.name) {
|
||||||
matcherMap.set(matcher.record.name, matcher);
|
matcherMap.set(matcher.record.name, matcher);
|
||||||
@ -126,9 +139,12 @@ export function createRouterMatcher(
|
|||||||
return matcherMap.get(name);
|
return matcherMap.get(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
function resolve(location: RawLocation, currentLocation: MatcherLocation): MatcherLocation {
|
function resolve(
|
||||||
|
location: RawLocation,
|
||||||
|
currentLocation: MatcherLocation
|
||||||
|
): MatcherLocation {
|
||||||
let matcher: RouteRecordMatcher | undefined;
|
let matcher: RouteRecordMatcher | undefined;
|
||||||
let params: RouteParams = {};
|
let params: PathParams = {};
|
||||||
let path: MatcherLocation['path'];
|
let path: MatcherLocation['path'];
|
||||||
let name: MatcherLocation['name'];
|
let name: MatcherLocation['name'];
|
||||||
|
|
||||||
@ -136,7 +152,9 @@ export function createRouterMatcher(
|
|||||||
matcher = matcherMap.get(location.name);
|
matcher = matcherMap.get(location.name);
|
||||||
|
|
||||||
if (!matcher) {
|
if (!matcher) {
|
||||||
throw new Error(`Router error: no match for ${JSON.stringify(location)}`);
|
throw new Error(`
|
||||||
|
Router error: no match for ${JSON.stringify(location)}
|
||||||
|
`);
|
||||||
}
|
}
|
||||||
|
|
||||||
name = matcher.record.name;
|
name = matcher.record.name;
|
||||||
@ -145,9 +163,10 @@ export function createRouterMatcher(
|
|||||||
paramsFromLocation(
|
paramsFromLocation(
|
||||||
currentLocation.params ?? {},
|
currentLocation.params ?? {},
|
||||||
matcher.keys
|
matcher.keys
|
||||||
.filter((k) => {
|
.filter(k => !k.optional)
|
||||||
return !(k.modifier === '?' || k.modifier === '*');
|
.concat(
|
||||||
})
|
matcher.parent ? matcher.parent.keys.filter(k => k.optional) : []
|
||||||
|
)
|
||||||
.map((k) => k.name),
|
.map((k) => k.name),
|
||||||
),
|
),
|
||||||
location.params
|
location.params
|
||||||
@ -157,7 +176,7 @@ export function createRouterMatcher(
|
|||||||
)
|
)
|
||||||
: {},
|
: {},
|
||||||
);
|
);
|
||||||
// throws if cannot be stringified
|
|
||||||
path = matcher.stringify(params);
|
path = matcher.stringify(params);
|
||||||
} else if ('path' in location) {
|
} else if ('path' in location) {
|
||||||
path = location.path;
|
path = location.path;
|
||||||
@ -214,8 +233,8 @@ export function createRouterMatcher(
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function paramsFromLocation(params: RouteParams, keys: (string | number)[]): RouteParams {
|
function paramsFromLocation(params: PathParams, keys: (string | number)[]): PathParams {
|
||||||
const newParams = {} as RouteParams;
|
const newParams = {} as PathParams;
|
||||||
for (const key of keys) {
|
for (const key of keys) {
|
||||||
if (key in params) newParams[key] = params[key];
|
if (key in params) newParams[key] = params[key];
|
||||||
}
|
}
|
||||||
@ -233,3 +252,12 @@ export function normalizeRouteRecord(record: RouteRecord): RouteRecordNormalized
|
|||||||
children: record.children || [],
|
children: record.children || [],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function isRecordChildOf(
|
||||||
|
record: RouteRecordMatcher,
|
||||||
|
parent: RouteRecordMatcher
|
||||||
|
): boolean {
|
||||||
|
return parent.children.some(
|
||||||
|
child => child === record || isRecordChildOf(record, child)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|||||||
@ -2,7 +2,7 @@ import {
|
|||||||
type RouterApi,
|
type RouterApi,
|
||||||
type RouterConfig,
|
type RouterConfig,
|
||||||
type RouteLocation,
|
type RouteLocation,
|
||||||
useEvent,
|
createEvent,
|
||||||
type RawRouteLocation,
|
type RawRouteLocation,
|
||||||
type RawLocationOptions,
|
type RawLocationOptions,
|
||||||
} from '@alilc/lowcode-renderer-core';
|
} from '@alilc/lowcode-renderer-core';
|
||||||
@ -14,10 +14,10 @@ import {
|
|||||||
type HistoryState,
|
type HistoryState,
|
||||||
} from './history';
|
} from './history';
|
||||||
import { createRouterMatcher } from './matcher';
|
import { createRouterMatcher } from './matcher';
|
||||||
import { type PathParserOptions } from './utils/path-parser';
|
import { type PathParserOptions, type PathParams } from './utils/path-parser';
|
||||||
import { parseURL, stringifyURL } from './utils/url';
|
import { parseURL, stringifyURL } from './utils/url';
|
||||||
import { isSameRouteLocation } from './utils/helper';
|
import { isSameRouteLocation } from './utils/helper';
|
||||||
import type { RouteParams, RouteRecord, RouteLocationNormalized } from './types';
|
import type { RouteRecord, RouteLocationNormalized } from './types';
|
||||||
import { type NavigationHookAfter, type NavigationGuard, guardToPromiseFn } from './guard';
|
import { type NavigationHookAfter, type NavigationGuard, guardToPromiseFn } from './guard';
|
||||||
|
|
||||||
export interface RouterOptions extends RouterConfig, PathParserOptions {
|
export interface RouterOptions extends RouterConfig, PathParserOptions {
|
||||||
@ -72,8 +72,8 @@ export function createRouter(options: RouterOptions = defaultRouterOptions): Rou
|
|||||||
? createMemoryHistory(baseName)
|
? createMemoryHistory(baseName)
|
||||||
: createBrowserHistory(baseName);
|
: createBrowserHistory(baseName);
|
||||||
|
|
||||||
const beforeGuards = useEvent<NavigationGuard>();
|
const beforeGuards = createEvent<NavigationGuard>();
|
||||||
const afterGuards = useEvent<NavigationHookAfter>();
|
const afterGuards = createEvent<NavigationHookAfter>();
|
||||||
|
|
||||||
let currentLocation: RouteLocationNormalized = START_LOCATION;
|
let currentLocation: RouteLocationNormalized = START_LOCATION;
|
||||||
let pendingLocation = currentLocation;
|
let pendingLocation = currentLocation;
|
||||||
@ -114,9 +114,9 @@ export function createRouter(options: RouterOptions = defaultRouterOptions): Rou
|
|||||||
|
|
||||||
matcherLocation = {
|
matcherLocation = {
|
||||||
...rawLocation,
|
...rawLocation,
|
||||||
params: rawLocation.params as RouteParams,
|
params: rawLocation.params as PathParams,
|
||||||
};
|
};
|
||||||
currentLocation.params = currentLocation.params;
|
currentLocation.params = matcherLocation.params;
|
||||||
}
|
}
|
||||||
|
|
||||||
const matchedRoute = matcher.resolve(matcherLocation, currentLocation);
|
const matchedRoute = matcher.resolve(matcherLocation, currentLocation);
|
||||||
@ -256,7 +256,7 @@ export function createRouter(options: RouterOptions = defaultRouterOptions): Rou
|
|||||||
to: RouteLocationNormalized,
|
to: RouteLocationNormalized,
|
||||||
from: RouteLocationNormalized,
|
from: RouteLocationNormalized,
|
||||||
): Promise<any> {
|
): Promise<any> {
|
||||||
let guards: ((...args: any[]) => Promise<any>)[] = [];
|
const guards: ((...args: any[]) => Promise<any>)[] = [];
|
||||||
|
|
||||||
const canceledNavigationCheck = async (): Promise<any> => {
|
const canceledNavigationCheck = async (): Promise<any> => {
|
||||||
if (pendingLocation !== to) {
|
if (pendingLocation !== to) {
|
||||||
@ -265,8 +265,6 @@ export function createRouter(options: RouterOptions = defaultRouterOptions): Rou
|
|||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
};
|
};
|
||||||
|
|
||||||
try {
|
|
||||||
guards = [];
|
|
||||||
const beforeGuardsList = beforeGuards.list();
|
const beforeGuardsList = beforeGuards.list();
|
||||||
|
|
||||||
for (const guard of beforeGuardsList) {
|
for (const guard of beforeGuardsList) {
|
||||||
@ -275,9 +273,6 @@ export function createRouter(options: RouterOptions = defaultRouterOptions): Rou
|
|||||||
if (beforeGuardsList.length > 0) guards.push(canceledNavigationCheck);
|
if (beforeGuardsList.length > 0) guards.push(canceledNavigationCheck);
|
||||||
|
|
||||||
return guards.reduce((promise, guard) => promise.then(() => guard()), Promise.resolve());
|
return guards.reduce((promise, guard) => promise.then(() => guard()), Promise.resolve());
|
||||||
} catch (err) {
|
|
||||||
throw err;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function finalizeNavigation(
|
function finalizeNavigation(
|
||||||
|
|||||||
@ -18,5 +18,3 @@ export interface RouteRecord extends RouterRecordSpec, PathParserOptions {
|
|||||||
export interface RouteLocationNormalized extends RouteLocation {
|
export interface RouteLocationNormalized extends RouteLocation {
|
||||||
matched: RouteRecord[];
|
matched: RouteRecord[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export type RouteParams = Record<string, string | string[]>;
|
|
||||||
|
|||||||
@ -1,53 +0,0 @@
|
|||||||
import {
|
|
||||||
pathToRegexp,
|
|
||||||
match,
|
|
||||||
compile,
|
|
||||||
type Key,
|
|
||||||
type TokensToRegexpOptions,
|
|
||||||
} from 'path-to-regexp';
|
|
||||||
import type { RouteParams } from '../types';
|
|
||||||
|
|
||||||
export interface PathParser {
|
|
||||||
re: RegExp;
|
|
||||||
/**
|
|
||||||
* optional = token.modifier === "?" || token.modifier === "*";
|
|
||||||
* repeat = token.modifier === "*" || token.modifier === "+";
|
|
||||||
*/
|
|
||||||
keys: Key[];
|
|
||||||
/**
|
|
||||||
* 解析路径中的参数
|
|
||||||
*/
|
|
||||||
parse: (path: string) => RouteParams | undefined;
|
|
||||||
stringify: (params: RouteParams) => string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export type PathParserOptions = Pick<
|
|
||||||
TokensToRegexpOptions,
|
|
||||||
'end' | 'strict' | 'sensitive'
|
|
||||||
>;
|
|
||||||
|
|
||||||
export function createPathParser(path: string, options: PathParserOptions) {
|
|
||||||
if (!path.startsWith('/')) {
|
|
||||||
throw new Error(
|
|
||||||
`Route paths should start with a "/": "${path}" should be "/${path}".`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const keys: Key[] = [];
|
|
||||||
const re = pathToRegexp(path, keys, options);
|
|
||||||
const parse = match(path);
|
|
||||||
const stringify = compile(path, { encode: encodeURIComponent });
|
|
||||||
|
|
||||||
return {
|
|
||||||
re,
|
|
||||||
keys,
|
|
||||||
parse: (path: string) => {
|
|
||||||
const parsed = parse(path);
|
|
||||||
if (!parsed) return undefined;
|
|
||||||
return parsed.params as RouteParams;
|
|
||||||
},
|
|
||||||
stringify: (params: RouteParams) => {
|
|
||||||
return stringify(params);
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
9
packages/renderer-router/src/utils/path-parser/index.ts
Normal file
9
packages/renderer-router/src/utils/path-parser/index.ts
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
import { type PathParserOptions, tokensToParser } from './parser-ranker';
|
||||||
|
import { tokenizePath } from './path-tokenizer';
|
||||||
|
|
||||||
|
export function createPathParser(path: string, options?: PathParserOptions) {
|
||||||
|
return tokensToParser(tokenizePath(path), options);
|
||||||
|
}
|
||||||
|
|
||||||
|
export { comparePathParserScore } from './parser-ranker';
|
||||||
|
export type { PathParser, PathParams, PathParserOptions } from './parser-ranker';
|
||||||
370
packages/renderer-router/src/utils/path-parser/parser-ranker.ts
Normal file
370
packages/renderer-router/src/utils/path-parser/parser-ranker.ts
Normal file
@ -0,0 +1,370 @@
|
|||||||
|
// fork from https://github.com/vuejs/router/blob/main/packages/router/src/matcher/pathParserRanker.ts
|
||||||
|
|
||||||
|
import { Token, TokenType } from './path-tokenizer';
|
||||||
|
|
||||||
|
export type PathParams = Record<string, string | string[]>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A param in a url like `/users/:id`
|
||||||
|
*/
|
||||||
|
interface PathParserParamKey {
|
||||||
|
name: string
|
||||||
|
repeatable: boolean
|
||||||
|
optional: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface PathParser {
|
||||||
|
/**
|
||||||
|
* The regexp used to match a url
|
||||||
|
*/
|
||||||
|
re: RegExp
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The score of the parser
|
||||||
|
*/
|
||||||
|
score: Array<number[]>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Keys that appeared in the path
|
||||||
|
*/
|
||||||
|
keys: PathParserParamKey[]
|
||||||
|
/**
|
||||||
|
* Parses a url and returns the matched params or null if it doesn't match. An
|
||||||
|
* optional param that isn't preset will be an empty string. A repeatable
|
||||||
|
* param will be an array if there is at least one value.
|
||||||
|
*
|
||||||
|
* @param path - url to parse
|
||||||
|
* @returns a Params object, empty if there are no params. `null` if there is
|
||||||
|
* no match
|
||||||
|
*/
|
||||||
|
parse(path: string): PathParams | null
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a string version of the url
|
||||||
|
*
|
||||||
|
* @param params - object of params
|
||||||
|
* @returns a url
|
||||||
|
*/
|
||||||
|
stringify(params: PathParams): string
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
export interface _PathParserOptions {
|
||||||
|
/**
|
||||||
|
* Makes the RegExp case-sensitive.
|
||||||
|
*
|
||||||
|
* @defaultValue `false`
|
||||||
|
*/
|
||||||
|
sensitive?: boolean
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether to disallow a trailing slash or not.
|
||||||
|
*
|
||||||
|
* @defaultValue `false`
|
||||||
|
*/
|
||||||
|
strict?: boolean
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Should the RegExp match from the beginning by prepending a `^` to it.
|
||||||
|
* @internal
|
||||||
|
*
|
||||||
|
* @defaultValue `true`
|
||||||
|
*/
|
||||||
|
start?: boolean
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Should the RegExp match until the end by appending a `$` to it.
|
||||||
|
*
|
||||||
|
* @defaultValue `true`
|
||||||
|
*/
|
||||||
|
end?: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
export type PathParserOptions = Pick<
|
||||||
|
_PathParserOptions,
|
||||||
|
'end' | 'sensitive' | 'strict'
|
||||||
|
>;
|
||||||
|
|
||||||
|
// default pattern for a param: non-greedy everything but /
|
||||||
|
const BASE_PARAM_PATTERN = '[^/]+?';
|
||||||
|
|
||||||
|
const BASE_PATH_PARSER_OPTIONS: Required<_PathParserOptions> = {
|
||||||
|
sensitive: false,
|
||||||
|
strict: false,
|
||||||
|
start: true,
|
||||||
|
end: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Scoring values used in tokensToParser
|
||||||
|
const enum PathScore {
|
||||||
|
_multiplier = 10,
|
||||||
|
Root = 9 * _multiplier, // just /
|
||||||
|
Segment = 4 * _multiplier, // /a-segment
|
||||||
|
SubSegment = 3 * _multiplier, // /multiple-:things-in-one-:segment
|
||||||
|
Static = 4 * _multiplier, // /static
|
||||||
|
Dynamic = 2 * _multiplier, // /:someId
|
||||||
|
BonusCustomRegExp = 1 * _multiplier, // /:someId(\\d+)
|
||||||
|
BonusWildcard = -4 * _multiplier - BonusCustomRegExp, // /:namedWildcard(.*) we remove the bonus added by the custom regexp
|
||||||
|
BonusRepeatable = -2 * _multiplier, // /:w+ or /:w*
|
||||||
|
BonusOptional = -0.8 * _multiplier, // /:w? or /:w*
|
||||||
|
// these two have to be under 0.1 so a strict /:page is still lower than /:a-:b
|
||||||
|
BonusStrict = 0.07 * _multiplier, // when options strict: true is passed, as the regex omits \/?
|
||||||
|
BonusCaseSensitive = 0.025 * _multiplier, // when options strict: true is passed, as the regex omits \/?
|
||||||
|
}
|
||||||
|
|
||||||
|
// Special Regex characters that must be escaped in static tokens
|
||||||
|
const REGEX_CHARS_RE = /[.+*?^${}()[\]/\\]/g;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a path parser from an array of Segments (a segment is an array of Tokens)
|
||||||
|
*
|
||||||
|
* @param segments - array of segments returned by tokenizePath
|
||||||
|
* @param extraOptions - optional options for the regexp
|
||||||
|
* @returns a PathParser
|
||||||
|
*/
|
||||||
|
export function tokensToParser(
|
||||||
|
segments: Array<Token[]>,
|
||||||
|
extraOptions?: _PathParserOptions
|
||||||
|
): PathParser {
|
||||||
|
const options = Object.assign({}, BASE_PATH_PARSER_OPTIONS, extraOptions);
|
||||||
|
|
||||||
|
// the amount of scores is the same as the length of segments except for the root segment "/"
|
||||||
|
const score: Array<number[]> = [];
|
||||||
|
// the regexp as a string
|
||||||
|
let pattern = options.start ? '^' : '';
|
||||||
|
// extracted keys
|
||||||
|
const keys: PathParserParamKey[] = [];
|
||||||
|
|
||||||
|
for (const segment of segments) {
|
||||||
|
// the root segment needs special treatment
|
||||||
|
const segmentScores: number[] = segment.length ? [] : [PathScore.Root];
|
||||||
|
|
||||||
|
// allow trailing slash
|
||||||
|
if (options.strict && !segment.length) pattern += '/';
|
||||||
|
for (let tokenIndex = 0; tokenIndex < segment.length; tokenIndex++) {
|
||||||
|
const token = segment[tokenIndex];
|
||||||
|
// resets the score if we are inside a sub-segment /:a-other-:b
|
||||||
|
let subSegmentScore: number =
|
||||||
|
PathScore.Segment +
|
||||||
|
(options.sensitive ? PathScore.BonusCaseSensitive : 0);
|
||||||
|
|
||||||
|
if (token.type === TokenType.Static) {
|
||||||
|
// prepend the slash if we are starting a new segment
|
||||||
|
if (!tokenIndex) pattern += '/';
|
||||||
|
pattern += token.value.replace(REGEX_CHARS_RE, '\\$&');
|
||||||
|
subSegmentScore += PathScore.Static;
|
||||||
|
} else if (token.type === TokenType.Param) {
|
||||||
|
const { value, repeatable, optional, regexp } = token;
|
||||||
|
keys.push({
|
||||||
|
name: value,
|
||||||
|
repeatable,
|
||||||
|
optional,
|
||||||
|
});
|
||||||
|
const re = regexp ? regexp : BASE_PARAM_PATTERN;
|
||||||
|
// the user provided a custom regexp /:id(\\d+)
|
||||||
|
if (re !== BASE_PARAM_PATTERN) {
|
||||||
|
subSegmentScore += PathScore.BonusCustomRegExp;
|
||||||
|
// make sure the regexp is valid before using it
|
||||||
|
try {
|
||||||
|
new RegExp(`(${re})`);
|
||||||
|
} catch (err) {
|
||||||
|
throw new Error(
|
||||||
|
`Invalid custom RegExp for param "${value}" (${re}): ` +
|
||||||
|
(err as Error).message
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// when we repeat we must take care of the repeating leading slash
|
||||||
|
let subPattern = repeatable ? `((?:${re})(?:/(?:${re}))*)` : `(${re})`;
|
||||||
|
|
||||||
|
// prepend the slash if we are starting a new segment
|
||||||
|
if (!tokenIndex)
|
||||||
|
subPattern =
|
||||||
|
// avoid an optional / if there are more segments e.g. /:p?-static
|
||||||
|
// or /:p?-:p2
|
||||||
|
optional && segment.length < 2
|
||||||
|
? `(?:/${subPattern})`
|
||||||
|
: '/' + subPattern;
|
||||||
|
if (optional) subPattern += '?';
|
||||||
|
|
||||||
|
pattern += subPattern;
|
||||||
|
|
||||||
|
subSegmentScore += PathScore.Dynamic;
|
||||||
|
if (optional) subSegmentScore += PathScore.BonusOptional;
|
||||||
|
if (repeatable) subSegmentScore += PathScore.BonusRepeatable;
|
||||||
|
if (re === '.*') subSegmentScore += PathScore.BonusWildcard;
|
||||||
|
}
|
||||||
|
|
||||||
|
segmentScores.push(subSegmentScore);
|
||||||
|
}
|
||||||
|
|
||||||
|
// an empty array like /home/ -> [[{home}], []]
|
||||||
|
// if (!segment.length) pattern += '/'
|
||||||
|
|
||||||
|
score.push(segmentScores);
|
||||||
|
}
|
||||||
|
|
||||||
|
// only apply the strict bonus to the last score
|
||||||
|
if (options.strict && options.end) {
|
||||||
|
const i = score.length - 1;
|
||||||
|
score[i][score[i].length - 1] += PathScore.BonusStrict;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: dev only warn double trailing slash
|
||||||
|
if (!options.strict) pattern += '/?';
|
||||||
|
|
||||||
|
if (options.end) pattern += '$';
|
||||||
|
// allow paths like /dynamic to only match dynamic or dynamic/... but not dynamic_something_else
|
||||||
|
else if (options.strict) pattern += '(?:/|$)';
|
||||||
|
|
||||||
|
const re = new RegExp(pattern, options.sensitive ? '' : 'i');
|
||||||
|
|
||||||
|
function parse(path: string): PathParams | null {
|
||||||
|
const match = path.match(re);
|
||||||
|
const params: PathParams = {};
|
||||||
|
|
||||||
|
if (!match) return null;
|
||||||
|
|
||||||
|
for (let i = 1; i < match.length; i++) {
|
||||||
|
const value: string = match[i] || '';
|
||||||
|
const key = keys[i - 1];
|
||||||
|
params[key.name] = value && key.repeatable ? value.split('/') : value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return params;
|
||||||
|
}
|
||||||
|
|
||||||
|
function stringify(params: PathParams): string {
|
||||||
|
let path = '';
|
||||||
|
// for optional parameters to allow to be empty
|
||||||
|
let avoidDuplicatedSlash: boolean = false;
|
||||||
|
for (const segment of segments) {
|
||||||
|
if (!avoidDuplicatedSlash || !path.endsWith('/')) path += '/';
|
||||||
|
avoidDuplicatedSlash = false;
|
||||||
|
|
||||||
|
for (const token of segment) {
|
||||||
|
if (token.type === TokenType.Static) {
|
||||||
|
path += token.value;
|
||||||
|
} else if (token.type === TokenType.Param) {
|
||||||
|
const { value, repeatable, optional } = token;
|
||||||
|
const param: string | readonly string[] =
|
||||||
|
value in params ? params[value] : '';
|
||||||
|
|
||||||
|
if (Array.isArray(param) && !repeatable) {
|
||||||
|
throw new Error(
|
||||||
|
`Provided param "${value}" is an array but it is not repeatable (* or + modifiers)`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const text: string = Array.isArray(param)
|
||||||
|
? (param as string[]).join('/')
|
||||||
|
: (param as string);
|
||||||
|
if (!text) {
|
||||||
|
if (optional) {
|
||||||
|
// if we have more than one optional param like /:a?-static we don't need to care about the optional param
|
||||||
|
if (segment.length < 2) {
|
||||||
|
// remove the last slash as we could be at the end
|
||||||
|
if (path.endsWith('/')) path = path.slice(0, -1);
|
||||||
|
// do not append a slash on the next iteration
|
||||||
|
else avoidDuplicatedSlash = true;
|
||||||
|
}
|
||||||
|
} else throw new Error(`Missing required param "${value}"`);
|
||||||
|
}
|
||||||
|
path += text;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// avoid empty path when we have multiple optional params
|
||||||
|
return path || '/';
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
re,
|
||||||
|
score,
|
||||||
|
keys,
|
||||||
|
parse,
|
||||||
|
stringify,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compares an array of numbers as used in PathParser.score and returns a
|
||||||
|
* number. This function can be used to `sort` an array
|
||||||
|
*
|
||||||
|
* @param a - first array of numbers
|
||||||
|
* @param b - second array of numbers
|
||||||
|
* @returns 0 if both are equal, < 0 if a should be sorted first, > 0 if b
|
||||||
|
* should be sorted first
|
||||||
|
*/
|
||||||
|
function compareScoreArray(a: number[], b: number[]): number {
|
||||||
|
let i = 0;
|
||||||
|
while (i < a.length && i < b.length) {
|
||||||
|
const diff = b[i] - a[i];
|
||||||
|
// only keep going if diff === 0
|
||||||
|
if (diff) return diff;
|
||||||
|
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if the last subsegment was Static, the shorter segments should be sorted first
|
||||||
|
// otherwise sort the longest segment first
|
||||||
|
if (a.length < b.length) {
|
||||||
|
return a.length === 1 && a[0] === PathScore.Static + PathScore.Segment
|
||||||
|
? -1
|
||||||
|
: 1;
|
||||||
|
} else if (a.length > b.length) {
|
||||||
|
return b.length === 1 && b[0] === PathScore.Static + PathScore.Segment
|
||||||
|
? 1
|
||||||
|
: -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compare function that can be used with `sort` to sort an array of PathParser
|
||||||
|
*
|
||||||
|
* @param a - first PathParser
|
||||||
|
* @param b - second PathParser
|
||||||
|
* @returns 0 if both are equal, < 0 if a should be sorted first, > 0 if b
|
||||||
|
*/
|
||||||
|
export function comparePathParserScore(a: PathParser, b: PathParser): number {
|
||||||
|
let i = 0;
|
||||||
|
const aScore = a.score;
|
||||||
|
const bScore = b.score;
|
||||||
|
while (i < aScore.length && i < bScore.length) {
|
||||||
|
const comp = compareScoreArray(aScore[i], bScore[i]);
|
||||||
|
// do not return if both are equal
|
||||||
|
if (comp) return comp;
|
||||||
|
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
if (Math.abs(bScore.length - aScore.length) === 1) {
|
||||||
|
if (isLastScoreNegative(aScore)) return 1;
|
||||||
|
if (isLastScoreNegative(bScore)) return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if a and b share the same score entries but b has more, sort b first
|
||||||
|
return bScore.length - aScore.length;
|
||||||
|
// this is the ternary version
|
||||||
|
// return aScore.length < bScore.length
|
||||||
|
// ? 1
|
||||||
|
// : aScore.length > bScore.length
|
||||||
|
// ? -1
|
||||||
|
// : 0
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This allows detecting splats at the end of a path: /home/:id(.*)*
|
||||||
|
*
|
||||||
|
* @param score - score to check
|
||||||
|
* @returns true if the last entry is negative
|
||||||
|
*/
|
||||||
|
function isLastScoreNegative(score: PathParser['score']): boolean {
|
||||||
|
const last = score[score.length - 1];
|
||||||
|
return score.length > 0 && last[last.length - 1] < 0;
|
||||||
|
}
|
||||||
200
packages/renderer-router/src/utils/path-parser/path-tokenizer.ts
Normal file
200
packages/renderer-router/src/utils/path-parser/path-tokenizer.ts
Normal file
@ -0,0 +1,200 @@
|
|||||||
|
// fork from https://github.com/vuejs/router/blob/main/packages/router/src/matcher/pathTokenizer.ts
|
||||||
|
|
||||||
|
export const enum TokenType {
|
||||||
|
Static,
|
||||||
|
Param,
|
||||||
|
Group,
|
||||||
|
}
|
||||||
|
|
||||||
|
const enum TokenizerState {
|
||||||
|
Static,
|
||||||
|
Param,
|
||||||
|
ParamRegExp, // custom re for a param
|
||||||
|
ParamRegExpEnd, // check if there is any ? + *
|
||||||
|
EscapeNext,
|
||||||
|
}
|
||||||
|
|
||||||
|
interface TokenStatic {
|
||||||
|
type: TokenType.Static
|
||||||
|
value: string
|
||||||
|
}
|
||||||
|
|
||||||
|
interface TokenParam {
|
||||||
|
type: TokenType.Param
|
||||||
|
regexp?: string
|
||||||
|
value: string
|
||||||
|
optional: boolean
|
||||||
|
repeatable: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
interface TokenGroup {
|
||||||
|
type: TokenType.Group
|
||||||
|
value: Exclude<Token, TokenGroup>[]
|
||||||
|
}
|
||||||
|
|
||||||
|
export type Token = TokenStatic | TokenParam | TokenGroup;
|
||||||
|
|
||||||
|
const ROOT_TOKEN: Token = {
|
||||||
|
type: TokenType.Static,
|
||||||
|
value: '',
|
||||||
|
};
|
||||||
|
|
||||||
|
const VALID_PARAM_RE = /[a-zA-Z0-9_]/;
|
||||||
|
// After some profiling, the cache seems to be unnecessary because tokenizePath
|
||||||
|
// (the slowest part of adding a route) is very fast
|
||||||
|
|
||||||
|
// const tokenCache = new Map<string, Token[][]>()
|
||||||
|
|
||||||
|
export function tokenizePath(path: string): Array<Token[]> {
|
||||||
|
if (!path) return [[]];
|
||||||
|
if (path === '/') return [[ROOT_TOKEN]];
|
||||||
|
if (!path.startsWith('/')) {
|
||||||
|
throw new Error(
|
||||||
|
`Route paths should start with a "/": "${path}" should be "/${path}".`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// if (tokenCache.has(path)) return tokenCache.get(path)!
|
||||||
|
|
||||||
|
function crash(message: string) {
|
||||||
|
throw new Error(`ERR (${state})/"${buffer}": ${message}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
let state: TokenizerState = TokenizerState.Static;
|
||||||
|
let previousState: TokenizerState = state;
|
||||||
|
const tokens: Array<Token[]> = [];
|
||||||
|
// the segment will always be valid because we get into the initial state
|
||||||
|
// with the leading /
|
||||||
|
let segment!: Token[];
|
||||||
|
|
||||||
|
function finalizeSegment() {
|
||||||
|
if (segment) tokens.push(segment);
|
||||||
|
segment = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
// index on the path
|
||||||
|
let i = 0;
|
||||||
|
// char at index
|
||||||
|
let char: string;
|
||||||
|
// buffer of the value read
|
||||||
|
let buffer: string = '';
|
||||||
|
// custom regexp for a param
|
||||||
|
let customRe: string = '';
|
||||||
|
|
||||||
|
function consumeBuffer() {
|
||||||
|
if (!buffer) return;
|
||||||
|
|
||||||
|
if (state === TokenizerState.Static) {
|
||||||
|
segment.push({
|
||||||
|
type: TokenType.Static,
|
||||||
|
value: buffer,
|
||||||
|
});
|
||||||
|
} else if (
|
||||||
|
state === TokenizerState.Param ||
|
||||||
|
state === TokenizerState.ParamRegExp ||
|
||||||
|
state === TokenizerState.ParamRegExpEnd
|
||||||
|
) {
|
||||||
|
if (segment.length > 1 && (char === '*' || char === '+'))
|
||||||
|
crash(
|
||||||
|
`A repeatable param (${buffer}) must be alone in its segment. eg: '/:ids+.`
|
||||||
|
);
|
||||||
|
segment.push({
|
||||||
|
type: TokenType.Param,
|
||||||
|
value: buffer,
|
||||||
|
regexp: customRe,
|
||||||
|
repeatable: char === '*' || char === '+',
|
||||||
|
optional: char === '*' || char === '?',
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
crash('Invalid state to consume buffer');
|
||||||
|
}
|
||||||
|
buffer = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
function addCharToBuffer() {
|
||||||
|
buffer += char;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (i < path.length) {
|
||||||
|
char = path[i++];
|
||||||
|
|
||||||
|
if (char === '\\' && state !== TokenizerState.ParamRegExp) {
|
||||||
|
previousState = state;
|
||||||
|
state = TokenizerState.EscapeNext;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (state) {
|
||||||
|
case TokenizerState.Static:
|
||||||
|
if (char === '/') {
|
||||||
|
if (buffer) {
|
||||||
|
consumeBuffer();
|
||||||
|
}
|
||||||
|
finalizeSegment();
|
||||||
|
} else if (char === ':') {
|
||||||
|
consumeBuffer();
|
||||||
|
state = TokenizerState.Param;
|
||||||
|
} else {
|
||||||
|
addCharToBuffer();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TokenizerState.EscapeNext:
|
||||||
|
addCharToBuffer();
|
||||||
|
state = previousState;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TokenizerState.Param:
|
||||||
|
if (char === '(') {
|
||||||
|
state = TokenizerState.ParamRegExp;
|
||||||
|
} else if (VALID_PARAM_RE.test(char)) {
|
||||||
|
addCharToBuffer();
|
||||||
|
} else {
|
||||||
|
consumeBuffer();
|
||||||
|
state = TokenizerState.Static;
|
||||||
|
// go back one character if we were not modifying
|
||||||
|
if (char !== '*' && char !== '?' && char !== '+') i--;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TokenizerState.ParamRegExp:
|
||||||
|
// TODO: is it worth handling nested regexp? like :p(?:prefix_([^/]+)_suffix)
|
||||||
|
// it already works by escaping the closing )
|
||||||
|
// https://paths.esm.dev/?p=AAMeJbiAwQEcDKbAoAAkP60PG2R6QAvgNaA6AFACM2ABuQBB#
|
||||||
|
// is this really something people need since you can also write
|
||||||
|
// /prefix_:p()_suffix
|
||||||
|
if (char === ')') {
|
||||||
|
// handle the escaped )
|
||||||
|
if (customRe[customRe.length - 1] == '\\')
|
||||||
|
customRe = customRe.slice(0, -1) + char;
|
||||||
|
else state = TokenizerState.ParamRegExpEnd;
|
||||||
|
} else {
|
||||||
|
customRe += char;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TokenizerState.ParamRegExpEnd:
|
||||||
|
// same as finalizing a param
|
||||||
|
consumeBuffer();
|
||||||
|
state = TokenizerState.Static;
|
||||||
|
// go back one character if we were not modifying
|
||||||
|
if (char !== '*' && char !== '?' && char !== '+') i--;
|
||||||
|
customRe = '';
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
crash('Unknown state');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state === TokenizerState.ParamRegExp)
|
||||||
|
crash(`Unfinished custom RegExp for param "${buffer}"`);
|
||||||
|
|
||||||
|
consumeBuffer();
|
||||||
|
finalizeSegment();
|
||||||
|
|
||||||
|
// tokenCache.set(path, tokens)
|
||||||
|
|
||||||
|
return tokens;
|
||||||
|
}
|
||||||
@ -4,5 +4,6 @@ import baseConfigFn from '../../vite.base.config'
|
|||||||
export default defineConfig(async () => {
|
export default defineConfig(async () => {
|
||||||
return baseConfigFn({
|
return baseConfigFn({
|
||||||
name: 'LowCodeRuntimeRouter',
|
name: 'LowCodeRuntimeRouter',
|
||||||
|
defaultFormats: ['es', 'cjs']
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|||||||
@ -0,0 +1,5 @@
|
|||||||
|
import { defineProject } from 'vitest/config'
|
||||||
|
|
||||||
|
export default defineProject({
|
||||||
|
test: {}
|
||||||
|
})
|
||||||
@ -86,4 +86,4 @@ export interface IBaseModelProps<
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IPublicModelProps extends IBaseModelProps<IPublicModelProp> {};
|
export interface IPublicModelProps extends IBaseModelProps<IPublicModelProp> {}
|
||||||
|
|||||||
@ -3,4 +3,4 @@ import { IPublicModelSettingField } from './';
|
|||||||
/**
|
/**
|
||||||
* @deprecated please use IPublicModelSettingField
|
* @deprecated please use IPublicModelSettingField
|
||||||
*/
|
*/
|
||||||
export type IPublicModelSettingPropEntry = IPublicModelSettingField
|
export type IPublicModelSettingPropEntry = IPublicModelSettingField;
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
import { IPublicTypeComponentSchema } from "@alilc/lowcode-types";
|
import { IPublicTypeComponentSchema } from '@alilc/lowcode-types';
|
||||||
|
|
||||||
export function isComponentSchema(schema: any): schema is IPublicTypeComponentSchema {
|
export function isComponentSchema(schema: any): schema is IPublicTypeComponentSchema {
|
||||||
if (typeof schema === 'object') {
|
if (typeof schema === 'object') {
|
||||||
return schema.componentName === 'Component';
|
return schema.componentName === 'Component';
|
||||||
}
|
}
|
||||||
return false
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -103,7 +103,7 @@ export function getNodeSchemaById(
|
|||||||
|
|
||||||
function getNodeSchemaFromPropsById(props: any, nodeId: string): IPublicTypeNodeSchema | undefined {
|
function getNodeSchemaFromPropsById(props: any, nodeId: string): IPublicTypeNodeSchema | undefined {
|
||||||
let found: IPublicTypeNodeSchema | undefined;
|
let found: IPublicTypeNodeSchema | undefined;
|
||||||
for (const [_key, value] of Object.entries(props)) {
|
for (const [, value] of Object.entries(props)) {
|
||||||
if (isJSSlot(value)) {
|
if (isJSSlot(value)) {
|
||||||
// value 是数组类型 { type: 'JSSlot', value: IPublicTypeNodeSchema[] }
|
// value 是数组类型 { type: 'JSSlot', value: IPublicTypeNodeSchema[] }
|
||||||
if (Array.isArray(value.value)) {
|
if (Array.isArray(value.value)) {
|
||||||
@ -130,7 +130,7 @@ export function applyActivities(
|
|||||||
pivotSchema: IPublicTypeRootSchema,
|
pivotSchema: IPublicTypeRootSchema,
|
||||||
activities: any,
|
activities: any,
|
||||||
): IPublicTypeRootSchema {
|
): IPublicTypeRootSchema {
|
||||||
let schema = { ...pivotSchema };
|
const schema = { ...pivotSchema };
|
||||||
if (!Array.isArray(activities)) {
|
if (!Array.isArray(activities)) {
|
||||||
activities = [activities];
|
activities = [activities];
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,12 +4,28 @@
|
|||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>Playground</title>
|
<title>Playground</title>
|
||||||
|
|
||||||
|
<!-- 低代码引擎的页面主题样式,可以替换为 theme-lowcode-dark -->
|
||||||
|
<link href="https://alifd.alicdn.com/npm/@alifd/theme-lowcode-light@0.2.1/variables.css" rel="stylesheet" />
|
||||||
|
<link href="https://alifd.alicdn.com/npm/@alifd/theme-lowcode-light@0.2.1/dist/next.var.min.css" rel="stylesheet" />
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="app"></div>
|
<div id="app"></div>
|
||||||
|
|
||||||
<!-- <script src=""></script> -->
|
<!-- React,可替换为 production 包 -->
|
||||||
|
<script src="https://g.alicdn.com/code/lib/react/18.2.0/umd/react.development.min.js"></script>
|
||||||
|
<!-- React DOM,可替换为 production 包 -->
|
||||||
|
<script src="https://g.alicdn.com/code/lib/react-dom/18.2.0/umd/react-dom.development.min.js"></script>
|
||||||
|
<!-- React 向下兼容,预防物料层的依赖 -->
|
||||||
|
<script src="https://g.alicdn.com/code/lib/prop-types/15.7.2/prop-types.js"></script>
|
||||||
|
<script src="https://g.alicdn.com/platform/c/react15-polyfill/0.0.1/dist/index.js"></script>
|
||||||
|
<!-- 日期处理包,Fusion Next 的依赖 -->
|
||||||
|
<script src="https://g.alicdn.com/mylib/moment/2.24.0/min/moment.min.js"></script>
|
||||||
|
<!-- lodash,低代码编辑器的依赖 -->
|
||||||
|
<script src="https://g.alicdn.com/platform/c/lodash/4.6.1/lodash.min.js"></script>
|
||||||
|
<!-- Fusion Next 的主包,低代码编辑器的依赖 -->
|
||||||
|
<script src="https://g.alicdn.com/code/lib/alifd__next/1.24.18/next.min.js"></script>
|
||||||
|
<!-- <script crossorigin="anonymous" src="https://uipaas-assets.com/prod/npm/@alilc/lowcode-engine-ext/1.0.6/dist/js/engine-ext.js"></script> -->
|
||||||
<script type="module" src="./src/index.ts"></script>
|
<script type="module" src="./src/index.ts"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@ -6,7 +6,7 @@ body * {
|
|||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
body, #lce-container {
|
body, #app {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
left: 0;
|
left: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
|
|||||||
@ -1,12 +1,44 @@
|
|||||||
import { init } from '@alilc/lowcode-engine';
|
import { init, plugins } from '@alilc/lowcode-engine';
|
||||||
|
import EditorInitPlugin from './plugins/plugin-editor-init';
|
||||||
|
|
||||||
|
import '@alilc/lowcode-engine/dist/style.css';
|
||||||
import './index.css';
|
import './index.css';
|
||||||
|
|
||||||
init(document.getElementById('app')!, {
|
async function run() {
|
||||||
|
await plugins.register(EditorInitPlugin, {
|
||||||
|
scenarioName: 'general',
|
||||||
|
displayName: '综合场景',
|
||||||
|
info: {
|
||||||
|
urls: [
|
||||||
|
{
|
||||||
|
key: '设计器',
|
||||||
|
value: 'https://github.com/alibaba/lowcode-demo/tree/main/demo-general',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'fusion-ui 物料',
|
||||||
|
value: 'https://github.com/alibaba/lowcode-materials/tree/main/packages/fusion-ui',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'fusion 物料',
|
||||||
|
value: 'https://github.com/alibaba/lowcode-materials/tree/main/packages/fusion-lowcode-materials',
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
await init(document.getElementById('app')!, {
|
||||||
locale: 'zh-CN',
|
locale: 'zh-CN',
|
||||||
enableCondition: true,
|
enableCondition: true,
|
||||||
enableCanvasLock: true,
|
enableCanvasLock: true,
|
||||||
// 默认绑定变量
|
// 默认绑定变量
|
||||||
supportVariableGlobally: true,
|
supportVariableGlobally: true,
|
||||||
requestHandlersMap: {},
|
requestHandlersMap: {},
|
||||||
|
simulatorUrl: [
|
||||||
|
'https://alifd.alicdn.com/npm/@alilc/lowcode-react-simulator-renderer@1.1.1/dist/css/react-simulator-renderer.css',
|
||||||
|
'https://alifd.alicdn.com/npm/@alilc/lowcode-react-simulator-renderer@1.1.1/dist/js/react-simulator-renderer.js'
|
||||||
|
],
|
||||||
|
enableContextMenu: true,
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
run()
|
||||||
|
|||||||
49
playground/engine/src/plugins/plugin-editor-init/index.tsx
Normal file
49
playground/engine/src/plugins/plugin-editor-init/index.tsx
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
import { IPublicModelPluginContext } from '@alilc/lowcode-types';
|
||||||
|
import assets from '../../services/assets.json';
|
||||||
|
import { getProjectSchema } from '../../services/mockService';
|
||||||
|
|
||||||
|
const EditorInitPlugin = (ctx: IPublicModelPluginContext, options: any) => {
|
||||||
|
return {
|
||||||
|
async init() {
|
||||||
|
const { material, project, config } = ctx;
|
||||||
|
const scenarioName = options['scenarioName'];
|
||||||
|
const scenarioDisplayName = options['displayName'] || scenarioName;
|
||||||
|
const scenarioInfo = options['info'] || {};
|
||||||
|
// 保存在 config 中用于引擎范围其他插件使用
|
||||||
|
config.set('scenarioName', scenarioName);
|
||||||
|
config.set('scenarioDisplayName', scenarioDisplayName);
|
||||||
|
config.set('scenarioInfo', scenarioInfo);
|
||||||
|
|
||||||
|
// 设置物料描述
|
||||||
|
await material.setAssets(assets as any);
|
||||||
|
|
||||||
|
const schema = await getProjectSchema(scenarioName);
|
||||||
|
// 加载 schema
|
||||||
|
project.importSchema(schema as any);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
EditorInitPlugin.pluginName = 'EditorInitPlugin';
|
||||||
|
EditorInitPlugin.meta = {
|
||||||
|
preferenceDeclaration: {
|
||||||
|
title: '保存插件配置',
|
||||||
|
properties: [
|
||||||
|
{
|
||||||
|
key: 'scenarioName',
|
||||||
|
type: 'string',
|
||||||
|
description: '用于localstorage存储key',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'displayName',
|
||||||
|
type: 'string',
|
||||||
|
description: '用于显示的场景名',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'info',
|
||||||
|
type: 'object',
|
||||||
|
description: '用于扩展信息',
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
export default EditorInitPlugin;
|
||||||
140
playground/engine/src/services/assets.json
Normal file
140
playground/engine/src/services/assets.json
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
{
|
||||||
|
"packages": [
|
||||||
|
{
|
||||||
|
"package": "moment",
|
||||||
|
"version": "2.24.0",
|
||||||
|
"urls": [
|
||||||
|
"https://g.alicdn.com/mylib/moment/2.24.0/min/moment.min.js"
|
||||||
|
],
|
||||||
|
"library": "moment"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"package": "lodash",
|
||||||
|
"library": "_",
|
||||||
|
"urls": [
|
||||||
|
"https://g.alicdn.com/platform/c/lodash/4.6.1/lodash.min.js"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "fusion组件库",
|
||||||
|
"package": "@alifd/next",
|
||||||
|
"version": "1.26.4",
|
||||||
|
"urls": [
|
||||||
|
"https://g.alicdn.com/code/lib/alifd__next/1.26.4/next.min.css",
|
||||||
|
"https://g.alicdn.com/code/lib/alifd__next/1.26.4/next-with-locales.min.js"
|
||||||
|
],
|
||||||
|
"library": "Next"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "NextTable",
|
||||||
|
"package": "NextTable",
|
||||||
|
"version": "1.0.1",
|
||||||
|
"urls": [
|
||||||
|
"https://g.alicdn.com/fusion-platform/pro-table/1.0.1/next-table.js",
|
||||||
|
"https://g.alicdn.com/fusion-platform/pro-table/1.0.1/next-table.css"
|
||||||
|
],
|
||||||
|
"library": "NextTable"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"package": "@alilc/lowcode-materials",
|
||||||
|
"version": "1.0.7",
|
||||||
|
"library": "AlilcLowcodeMaterials",
|
||||||
|
"urls": [
|
||||||
|
"https://alifd.alicdn.com/npm/@alilc/lowcode-materials@1.0.7/dist/AlilcLowcodeMaterials.js",
|
||||||
|
"https://alifd.alicdn.com/npm/@alilc/lowcode-materials@1.0.7/dist/AlilcLowcodeMaterials.css"
|
||||||
|
],
|
||||||
|
"editUrls": [
|
||||||
|
"https://alifd.alicdn.com/npm/@alilc/lowcode-materials@1.0.7/build/lowcode/view.js",
|
||||||
|
"https://alifd.alicdn.com/npm/@alilc/lowcode-materials@1.0.7/build/lowcode/view.css"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"package": "@alifd/layout",
|
||||||
|
"version": "2.4.1",
|
||||||
|
"library": "AlifdLayout",
|
||||||
|
"urls": [
|
||||||
|
"https://alifd.alicdn.com/npm/@alifd/layout@2.4.1/dist/AlifdLayout.js",
|
||||||
|
"https://alifd.alicdn.com/npm/@alifd/layout@2.4.1/dist/AlifdLayout.css"
|
||||||
|
],
|
||||||
|
"editUrls": [
|
||||||
|
"https://alifd.alicdn.com/npm/@alifd/layout@2.4.1/build/lowcode/view.js",
|
||||||
|
"https://alifd.alicdn.com/npm/@alifd/layout@2.4.1/build/lowcode/view.css"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"package": "@alifd/fusion-ui",
|
||||||
|
"version": "2.0.2",
|
||||||
|
"library": "AlifdFusionUi",
|
||||||
|
"urls": [
|
||||||
|
"https://alifd.alicdn.com/npm/@alifd/fusion-ui@2.0.2/dist/AlifdFusionUi.js",
|
||||||
|
"https://alifd.alicdn.com/npm/@alifd/fusion-ui@2.0.2/dist/AlifdFusionUi.css"
|
||||||
|
],
|
||||||
|
"editUrls": [
|
||||||
|
"https://alifd.alicdn.com/npm/@alifd/fusion-ui@2.0.2/build/lowcode/view.js",
|
||||||
|
"https://alifd.alicdn.com/npm/@alifd/fusion-ui@2.0.2/build/lowcode/view.css"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"components": [
|
||||||
|
{
|
||||||
|
"exportName": "AlilcLowcodeMaterialsMeta",
|
||||||
|
"npm": {
|
||||||
|
"package": "@alilc/lowcode-materials"
|
||||||
|
},
|
||||||
|
"url": "https://alifd.alicdn.com/npm/@alilc/lowcode-materials@1.0.7/build/lowcode/meta.js",
|
||||||
|
"urls": {
|
||||||
|
"default": "https://alifd.alicdn.com/npm/@alilc/lowcode-materials@1.0.7/build/lowcode/meta.js",
|
||||||
|
"design": "https://alifd.alicdn.com/npm/@alilc/lowcode-materials@1.0.7/build/lowcode/meta.design.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"exportName": "AlifdLayoutMeta",
|
||||||
|
"npm": {
|
||||||
|
"package": "@alifd/layout",
|
||||||
|
"version": "2.4.1"
|
||||||
|
},
|
||||||
|
"url": "https://alifd.alicdn.com/npm/@alifd/layout@2.4.1/build/lowcode/meta.js",
|
||||||
|
"urls": {
|
||||||
|
"default": "https://alifd.alicdn.com/npm/@alifd/layout@2.4.1/build/lowcode/meta.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"exportName": "AlifdFusionUiMeta",
|
||||||
|
"npm": {
|
||||||
|
"package": "@alifd/fusion-ui"
|
||||||
|
},
|
||||||
|
"url": "https://alifd.alicdn.com/npm/@alifd/fusion-ui@2.0.2/build/lowcode/meta.js",
|
||||||
|
"urls": {
|
||||||
|
"default": "https://alifd.alicdn.com/npm/@alifd/fusion-ui@2.0.2/build/lowcode/meta.js",
|
||||||
|
"design": "https://alifd.alicdn.com/npm/@alifd/fusion-ui@2.0.2/build/lowcode/meta.design.js"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"sort": {
|
||||||
|
"groupList": [
|
||||||
|
"精选组件",
|
||||||
|
"原子组件",
|
||||||
|
"低代码组件"
|
||||||
|
],
|
||||||
|
"categoryList": [
|
||||||
|
"基础元素",
|
||||||
|
"布局容器类",
|
||||||
|
"表格类",
|
||||||
|
"表单详情类",
|
||||||
|
"帮助类",
|
||||||
|
"对话框类",
|
||||||
|
"业务类",
|
||||||
|
"通用",
|
||||||
|
"引导",
|
||||||
|
"信息输入",
|
||||||
|
"信息展示",
|
||||||
|
"信息反馈"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"groupList": [
|
||||||
|
"精选组件",
|
||||||
|
"原子组件",
|
||||||
|
"低代码组件"
|
||||||
|
],
|
||||||
|
"ignoreComponents": {}
|
||||||
|
}
|
||||||
10
playground/engine/src/services/defaultI18nSchema.json
Normal file
10
playground/engine/src/services/defaultI18nSchema.json
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"zh-CN": {
|
||||||
|
"i18n-jwg27yo4": "你好 ",
|
||||||
|
"i18n-jwg27yo3": "{name} 博士"
|
||||||
|
},
|
||||||
|
"en-US": {
|
||||||
|
"i18n-jwg27yo4": "Hello ",
|
||||||
|
"i18n-jwg27yo3": "Doctor {name}"
|
||||||
|
}
|
||||||
|
}
|
||||||
580
playground/engine/src/services/defaultPageSchema.json
Normal file
580
playground/engine/src/services/defaultPageSchema.json
Normal file
@ -0,0 +1,580 @@
|
|||||||
|
{
|
||||||
|
"componentName": "Page",
|
||||||
|
"id": "node_dockcviv8fo1",
|
||||||
|
"props": {
|
||||||
|
"ref": "outerView",
|
||||||
|
"style": {
|
||||||
|
"height": "100%"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"docId": "doclaqkk3b9",
|
||||||
|
"fileName": "/",
|
||||||
|
"dataSource": {
|
||||||
|
"list": [
|
||||||
|
{
|
||||||
|
"type": "fetch",
|
||||||
|
"isInit": true,
|
||||||
|
"options": {
|
||||||
|
"params": {},
|
||||||
|
"method": "GET",
|
||||||
|
"isCors": true,
|
||||||
|
"timeout": 5000,
|
||||||
|
"headers": {},
|
||||||
|
"uri": "mock/info.json"
|
||||||
|
},
|
||||||
|
"id": "info",
|
||||||
|
"shouldFetch": {
|
||||||
|
"type": "JSFunction",
|
||||||
|
"value": "function() { \n console.log('should fetch.....');\n return true; \n}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"state": {
|
||||||
|
"text": {
|
||||||
|
"type": "JSExpression",
|
||||||
|
"value": "\"outer\""
|
||||||
|
},
|
||||||
|
"isShowDialog": {
|
||||||
|
"type": "JSExpression",
|
||||||
|
"value": "false"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"css": "body {\n font-size: 12px;\n}\n\n.button {\n width: 100px;\n color: #ff00ff\n}",
|
||||||
|
"lifeCycles": {
|
||||||
|
"componentDidMount": {
|
||||||
|
"type": "JSFunction",
|
||||||
|
"value": "function componentDidMount() {\n console.log('did mount');\n}"
|
||||||
|
},
|
||||||
|
"componentWillUnmount": {
|
||||||
|
"type": "JSFunction",
|
||||||
|
"value": "function componentWillUnmount() {\n console.log('will unmount');\n}"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"methods": {
|
||||||
|
"testFunc": {
|
||||||
|
"type": "JSFunction",
|
||||||
|
"value": "function testFunc() {\n console.log('test func');\n}"
|
||||||
|
},
|
||||||
|
"onClick": {
|
||||||
|
"type": "JSFunction",
|
||||||
|
"value": "function onClick() {\n this.setState({\n isShowDialog: true\n });\n}"
|
||||||
|
},
|
||||||
|
"closeDialog": {
|
||||||
|
"type": "JSFunction",
|
||||||
|
"value": "function closeDialog() {\n this.setState({\n isShowDialog: false\n });\n}"
|
||||||
|
},
|
||||||
|
"getHelloWorldText": {
|
||||||
|
"type": "JSFunction",
|
||||||
|
"value": "function getHelloWorldText() {\n return this.i18n('i18n-jwg27yo4');\n}"
|
||||||
|
},
|
||||||
|
"getHelloWorldText2": {
|
||||||
|
"type": "JSFunction",
|
||||||
|
"value": "function getHelloWorldText2() {\n return this.i18n('i18n-jwg27yo3', {\n name: '絮黎'\n });\n}"
|
||||||
|
},
|
||||||
|
"onTestConstantsButtonClicked": {
|
||||||
|
"type": "JSFunction",
|
||||||
|
"value": "function onTestConstantsButtonClicked() {\n console.log('constants.ConstantA:', this.constants.ConstantA);\n console.log('constants.ConstantB:', this.constants.ConstantB);\n}"
|
||||||
|
},
|
||||||
|
"onTestUtilsButtonClicked": {
|
||||||
|
"type": "JSFunction",
|
||||||
|
"value": "function onTestUtilsButtonClicked() {\n this.utils.demoUtil('param1', 'param2');\n}"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"originCode": "class LowcodeComponent extends Component {\n state = {\n \"text\": \"outer\",\n \"isShowDialog\": false\n }\n componentDidMount() {\n console.log('did mount');\n }\n componentWillUnmount() {\n console.log('will unmount');\n }\n testFunc() {\n console.log('test func');\n }\n onClick() {\n this.setState({\n isShowDialog: true\n });\n }\n closeDialog() {\n this.setState({\n isShowDialog: false\n });\n }\n getHelloWorldText() {\n return this.i18n('i18n-jwg27yo4');\n }\n getHelloWorldText2() {\n return this.i18n('i18n-jwg27yo3', {\n name: '絮黎',\n });\n }\n onTestConstantsButtonClicked() {\n console.log('constants.ConstantA:', this.constants.ConstantA);\n console.log('constants.ConstantB:', this.constants.ConstantB);\n\t}\n\tonTestUtilsButtonClicked(){\n this.utils.demoUtil('param1', 'param2');\n\t}\n}",
|
||||||
|
"hidden": false,
|
||||||
|
"title": "",
|
||||||
|
"isLocked": false,
|
||||||
|
"condition": true,
|
||||||
|
"conditionGroup": "",
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"componentName": "FDPage",
|
||||||
|
"id": "node_oclfjpfqjy5",
|
||||||
|
"props": {
|
||||||
|
"contentProps": {
|
||||||
|
"style": {
|
||||||
|
"background": "rgba(255,255,255,0)"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ref": "fdpage-bb43fbb0"
|
||||||
|
},
|
||||||
|
"title": "页面",
|
||||||
|
"hidden": false,
|
||||||
|
"isLocked": false,
|
||||||
|
"condition": true,
|
||||||
|
"conditionGroup": "",
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"componentName": "FDSection",
|
||||||
|
"id": "node_oclfjpfqjy6",
|
||||||
|
"props": {
|
||||||
|
"style": {
|
||||||
|
"backgroundColor": "rgba(255,255,255,1)",
|
||||||
|
"minHeight": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"title": "区域",
|
||||||
|
"hidden": false,
|
||||||
|
"isLocked": false,
|
||||||
|
"condition": true,
|
||||||
|
"conditionGroup": "",
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"componentName": "FDBlock",
|
||||||
|
"id": "node_oclfjpfqjy7",
|
||||||
|
"props": {
|
||||||
|
"mode": "transparent",
|
||||||
|
"span": 12
|
||||||
|
},
|
||||||
|
"title": "区块",
|
||||||
|
"hidden": false,
|
||||||
|
"isLocked": false,
|
||||||
|
"condition": true,
|
||||||
|
"conditionGroup": "",
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"componentName": "FDCell",
|
||||||
|
"id": "node_oclfjpfqjy8",
|
||||||
|
"props": {
|
||||||
|
"align": "left",
|
||||||
|
"verAlign": "top",
|
||||||
|
"style": {
|
||||||
|
"backgroundColor": "rgba(255,255,255,1)"
|
||||||
|
},
|
||||||
|
"width": ""
|
||||||
|
},
|
||||||
|
"title": "容器",
|
||||||
|
"hidden": false,
|
||||||
|
"isLocked": false,
|
||||||
|
"condition": true,
|
||||||
|
"conditionGroup": "",
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"componentName": "FDP",
|
||||||
|
"id": "node_oclfjpfqjy10",
|
||||||
|
"props": {},
|
||||||
|
"title": "段落",
|
||||||
|
"hidden": false,
|
||||||
|
"isLocked": false,
|
||||||
|
"condition": true,
|
||||||
|
"conditionGroup": "",
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"componentName": "NextText",
|
||||||
|
"id": "node_oclfjpfqjyz",
|
||||||
|
"props": {
|
||||||
|
"type": "h1",
|
||||||
|
"children": "Home",
|
||||||
|
"mark": false,
|
||||||
|
"code": false,
|
||||||
|
"delete": false,
|
||||||
|
"underline": false,
|
||||||
|
"strong": false,
|
||||||
|
"prefix": "",
|
||||||
|
"classname": "",
|
||||||
|
"style": {
|
||||||
|
"fontSize": "25px"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"hidden": false,
|
||||||
|
"title": "",
|
||||||
|
"isLocked": false,
|
||||||
|
"condition": true,
|
||||||
|
"conditionGroup": ""
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"componentName": "FDBlock",
|
||||||
|
"id": "node_oclfjpfqjy9",
|
||||||
|
"props": {
|
||||||
|
"mode": "transparent",
|
||||||
|
"span": 12,
|
||||||
|
"style": {
|
||||||
|
"backgroundColor": "rgba(255,255,255,1)",
|
||||||
|
"minHeight": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"title": "区块",
|
||||||
|
"hidden": false,
|
||||||
|
"isLocked": false,
|
||||||
|
"condition": true,
|
||||||
|
"conditionGroup": "",
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"componentName": "FDRow",
|
||||||
|
"id": "node_oclfjpfqjy11",
|
||||||
|
"props": {
|
||||||
|
"style": {
|
||||||
|
"backgroundColor": "rgba(255,255,255,1)"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"title": "行容器",
|
||||||
|
"hidden": false,
|
||||||
|
"isLocked": false,
|
||||||
|
"condition": true,
|
||||||
|
"conditionGroup": "",
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"componentName": "FDCell",
|
||||||
|
"id": "node_oclfjpfqjya",
|
||||||
|
"props": {
|
||||||
|
"align": "left",
|
||||||
|
"verAlign": "top",
|
||||||
|
"style": {
|
||||||
|
"backgroundColor": "rgba(255,255,255,1)"
|
||||||
|
},
|
||||||
|
"width": ""
|
||||||
|
},
|
||||||
|
"title": "容器",
|
||||||
|
"hidden": false,
|
||||||
|
"isLocked": false,
|
||||||
|
"condition": true,
|
||||||
|
"conditionGroup": "",
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"componentName": "FDP",
|
||||||
|
"id": "node_oclfjqcdwn14",
|
||||||
|
"props": {},
|
||||||
|
"title": "段落",
|
||||||
|
"hidden": false,
|
||||||
|
"isLocked": false,
|
||||||
|
"condition": true,
|
||||||
|
"conditionGroup": "",
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"componentName": "NextText",
|
||||||
|
"id": "node_oclfjqcdwn13",
|
||||||
|
"props": {
|
||||||
|
"type": "h5",
|
||||||
|
"children": "多语言展示",
|
||||||
|
"mark": false,
|
||||||
|
"code": false,
|
||||||
|
"delete": false,
|
||||||
|
"underline": false,
|
||||||
|
"strong": false,
|
||||||
|
"prefix": "",
|
||||||
|
"classname": "",
|
||||||
|
"style": {
|
||||||
|
"fontSize": "18px"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"hidden": false,
|
||||||
|
"title": "",
|
||||||
|
"isLocked": false,
|
||||||
|
"condition": true,
|
||||||
|
"conditionGroup": ""
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"componentName": "FDP",
|
||||||
|
"id": "node_oclfjqcdwn2k",
|
||||||
|
"props": {},
|
||||||
|
"title": "段落",
|
||||||
|
"hidden": false,
|
||||||
|
"isLocked": false,
|
||||||
|
"condition": true,
|
||||||
|
"conditionGroup": "",
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"componentName": "NextText",
|
||||||
|
"id": "node_oclfjqcdwn2j",
|
||||||
|
"props": {
|
||||||
|
"type": "inherit",
|
||||||
|
"children": {
|
||||||
|
"type": "JSExpression",
|
||||||
|
"value": "this.getHelloWorldText()",
|
||||||
|
"mock": ""
|
||||||
|
},
|
||||||
|
"mark": false,
|
||||||
|
"code": false,
|
||||||
|
"delete": false,
|
||||||
|
"underline": false,
|
||||||
|
"strong": false,
|
||||||
|
"prefix": "",
|
||||||
|
"classname": ""
|
||||||
|
},
|
||||||
|
"hidden": false,
|
||||||
|
"title": "",
|
||||||
|
"isLocked": false,
|
||||||
|
"condition": true,
|
||||||
|
"conditionGroup": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"componentName": "NextText",
|
||||||
|
"id": "node_oclfjqcf7z15",
|
||||||
|
"props": {
|
||||||
|
"type": "inherit",
|
||||||
|
"children": {
|
||||||
|
"type": "JSExpression",
|
||||||
|
"value": "this.getHelloWorldText2()",
|
||||||
|
"mock": "基于 Ali-Lowcode-Engine 快速打造高生产力的低代码研发平台, 基于自然布局体系快速搭建页面"
|
||||||
|
},
|
||||||
|
"mark": false,
|
||||||
|
"code": false,
|
||||||
|
"delete": false,
|
||||||
|
"underline": false,
|
||||||
|
"strong": false,
|
||||||
|
"prefix": "",
|
||||||
|
"classname": ""
|
||||||
|
},
|
||||||
|
"hidden": false,
|
||||||
|
"title": "",
|
||||||
|
"isLocked": false,
|
||||||
|
"condition": true,
|
||||||
|
"conditionGroup": ""
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"componentName": "FDCell",
|
||||||
|
"id": "node_oclfjpfqjy12",
|
||||||
|
"props": {
|
||||||
|
"align": "left",
|
||||||
|
"verAlign": "top",
|
||||||
|
"style": {
|
||||||
|
"backgroundColor": "rgba(255,255,255,1)"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"title": "容器",
|
||||||
|
"hidden": false,
|
||||||
|
"isLocked": false,
|
||||||
|
"condition": true,
|
||||||
|
"conditionGroup": "",
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"componentName": "FDP",
|
||||||
|
"id": "node_oclfjqcf7z2h",
|
||||||
|
"props": {},
|
||||||
|
"title": "段落",
|
||||||
|
"hidden": false,
|
||||||
|
"isLocked": false,
|
||||||
|
"condition": true,
|
||||||
|
"conditionGroup": "",
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"componentName": "NextText",
|
||||||
|
"id": "node_oclfjqcf7z2g",
|
||||||
|
"props": {
|
||||||
|
"type": "h5",
|
||||||
|
"children": "交互展示",
|
||||||
|
"mark": false,
|
||||||
|
"code": false,
|
||||||
|
"delete": false,
|
||||||
|
"underline": false,
|
||||||
|
"strong": false,
|
||||||
|
"prefix": "",
|
||||||
|
"classname": "",
|
||||||
|
"style": {
|
||||||
|
"fontSize": "18px"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"hidden": false,
|
||||||
|
"title": "",
|
||||||
|
"isLocked": false,
|
||||||
|
"condition": true,
|
||||||
|
"conditionGroup": ""
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"componentName": "FDP",
|
||||||
|
"id": "node_oclfjqcf7z2l",
|
||||||
|
"props": {},
|
||||||
|
"title": "段落",
|
||||||
|
"hidden": false,
|
||||||
|
"isLocked": false,
|
||||||
|
"condition": true,
|
||||||
|
"conditionGroup": "",
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"componentName": "Button",
|
||||||
|
"id": "node_oclfjqcf7z2k",
|
||||||
|
"props": {
|
||||||
|
"prefix": "next-",
|
||||||
|
"type": "primary",
|
||||||
|
"size": "medium",
|
||||||
|
"htmlType": "button",
|
||||||
|
"component": "button",
|
||||||
|
"children": "constants",
|
||||||
|
"iconSize": "xxs",
|
||||||
|
"loading": false,
|
||||||
|
"text": false,
|
||||||
|
"warning": false,
|
||||||
|
"disabled": false,
|
||||||
|
"ref": "button-4951c2d3",
|
||||||
|
"__events": {
|
||||||
|
"eventDataList": [
|
||||||
|
{
|
||||||
|
"type": "componentEvent",
|
||||||
|
"name": "onClick",
|
||||||
|
"relatedEventName": "onTestConstantsButtonClicked"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"eventList": [
|
||||||
|
{
|
||||||
|
"name": "onClick",
|
||||||
|
"description": "点击按钮的回调\n@param {Object} e Event Object",
|
||||||
|
"disabled": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "onMouseUp",
|
||||||
|
"disabled": false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"onClick": {
|
||||||
|
"type": "JSFunction",
|
||||||
|
"value": "function(){this.onTestConstantsButtonClicked.apply(this,Array.prototype.slice.call(arguments).concat([])) }"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"docId": "doclawu71ac",
|
||||||
|
"hidden": false,
|
||||||
|
"title": "",
|
||||||
|
"isLocked": false,
|
||||||
|
"condition": true,
|
||||||
|
"conditionGroup": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"componentName": "Button",
|
||||||
|
"id": "node_oclfjqcf7z2o",
|
||||||
|
"props": {
|
||||||
|
"prefix": "next-",
|
||||||
|
"type": "primary",
|
||||||
|
"size": "medium",
|
||||||
|
"htmlType": "button",
|
||||||
|
"component": "button",
|
||||||
|
"children": "utils",
|
||||||
|
"iconSize": "xxs",
|
||||||
|
"loading": false,
|
||||||
|
"text": false,
|
||||||
|
"warning": false,
|
||||||
|
"disabled": false,
|
||||||
|
"__events": {
|
||||||
|
"eventDataList": [
|
||||||
|
{
|
||||||
|
"type": "componentEvent",
|
||||||
|
"name": "onClick",
|
||||||
|
"relatedEventName": "onTestUtilsButtonClicked"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"eventList": [
|
||||||
|
{
|
||||||
|
"name": "onClick",
|
||||||
|
"description": "点击按钮的回调\n@param {Object} e Event Object",
|
||||||
|
"disabled": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "onMouseUp",
|
||||||
|
"disabled": false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"onClick": {
|
||||||
|
"type": "JSFunction",
|
||||||
|
"value": "function(){this.onTestUtilsButtonClicked.apply(this,Array.prototype.slice.call(arguments).concat([])) }"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"docId": "doclawu71ac",
|
||||||
|
"hidden": false,
|
||||||
|
"title": "",
|
||||||
|
"isLocked": false,
|
||||||
|
"condition": true,
|
||||||
|
"conditionGroup": ""
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"componentName": "FDBlock",
|
||||||
|
"id": "node_oclfjqcf7z3g",
|
||||||
|
"props": {
|
||||||
|
"mode": "transparent",
|
||||||
|
"span": 12,
|
||||||
|
"style": {
|
||||||
|
"backgroundColor": "rgba(255,255,255,1)",
|
||||||
|
"minHeight": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"title": "区块",
|
||||||
|
"hidden": false,
|
||||||
|
"isLocked": false,
|
||||||
|
"condition": true,
|
||||||
|
"conditionGroup": "",
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"componentName": "FDCell",
|
||||||
|
"id": "node_oclfjqcf7z3h",
|
||||||
|
"props": {
|
||||||
|
"align": "left",
|
||||||
|
"verAlign": "top",
|
||||||
|
"style": {
|
||||||
|
"backgroundColor": "rgba(255,255,255,1)"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"title": "容器",
|
||||||
|
"hidden": false,
|
||||||
|
"isLocked": false,
|
||||||
|
"condition": true,
|
||||||
|
"conditionGroup": "",
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"componentName": "FDP",
|
||||||
|
"id": "node_oclfjqcf7z43",
|
||||||
|
"props": {},
|
||||||
|
"title": "段落",
|
||||||
|
"hidden": false,
|
||||||
|
"isLocked": false,
|
||||||
|
"condition": true,
|
||||||
|
"conditionGroup": "",
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"componentName": "NextText",
|
||||||
|
"id": "node_oclfjqcf7z42",
|
||||||
|
"props": {
|
||||||
|
"type": "inherit",
|
||||||
|
"children": "Powered By Lowcode Engine",
|
||||||
|
"mark": false,
|
||||||
|
"code": false,
|
||||||
|
"delete": false,
|
||||||
|
"underline": false,
|
||||||
|
"strong": false,
|
||||||
|
"prefix": "",
|
||||||
|
"classname": "",
|
||||||
|
"style": {
|
||||||
|
"height": "30px",
|
||||||
|
"lineHeight": "30px",
|
||||||
|
"fontSize": "20px"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"hidden": false,
|
||||||
|
"title": "",
|
||||||
|
"isLocked": false,
|
||||||
|
"condition": true,
|
||||||
|
"conditionGroup": ""
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
118
playground/engine/src/services/mockService.ts
Normal file
118
playground/engine/src/services/mockService.ts
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
import { material, project } from '@alilc/lowcode-engine';
|
||||||
|
// import { filterPackages } from '@alilc/lowcode-plugin-inject'
|
||||||
|
import { Message, Dialog } from '@alifd/next';
|
||||||
|
import { IPublicTypeProjectSchema, IPublicEnumTransformStage } from '@alilc/lowcode-types';
|
||||||
|
import DefaultPageSchema from './defaultPageSchema.json';
|
||||||
|
import DefaultI18nSchema from './defaultI18nSchema.json';
|
||||||
|
|
||||||
|
const generateProjectSchema = (pageSchema: any, i18nSchema: any): IPublicTypeProjectSchema => {
|
||||||
|
return {
|
||||||
|
componentsTree: [pageSchema],
|
||||||
|
componentsMap: material.componentsMap as any,
|
||||||
|
version: '1.0.0',
|
||||||
|
i18n: i18nSchema,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export const saveSchema = async (scenarioName: string = 'unknown') => {
|
||||||
|
setProjectSchemaToLocalStorage(scenarioName);
|
||||||
|
await setPackagesToLocalStorage(scenarioName);
|
||||||
|
Message.success('成功保存到本地');
|
||||||
|
};
|
||||||
|
|
||||||
|
export const resetSchema = async (scenarioName: string = 'unknown') => {
|
||||||
|
try {
|
||||||
|
await new Promise<void>((resolve, reject) => {
|
||||||
|
Dialog.confirm({
|
||||||
|
content: '确定要重置吗?您所有的修改都将消失!',
|
||||||
|
onOk: () => {
|
||||||
|
resolve();
|
||||||
|
},
|
||||||
|
onCancel: () => {
|
||||||
|
reject()
|
||||||
|
},
|
||||||
|
})
|
||||||
|
})
|
||||||
|
} catch(err) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const defaultSchema = generateProjectSchema(DefaultPageSchema, DefaultI18nSchema);
|
||||||
|
|
||||||
|
project.importSchema(defaultSchema as any);
|
||||||
|
project.simulatorHost?.rerender();
|
||||||
|
|
||||||
|
setProjectSchemaToLocalStorage(scenarioName);
|
||||||
|
await setPackagesToLocalStorage(scenarioName);
|
||||||
|
Message.success('成功重置页面');
|
||||||
|
}
|
||||||
|
|
||||||
|
const getLSName = (scenarioName: string, ns: string = 'projectSchema') => `${scenarioName}:${ns}`;
|
||||||
|
|
||||||
|
export const getProjectSchemaFromLocalStorage = (scenarioName: string) => {
|
||||||
|
if (!scenarioName) {
|
||||||
|
console.error('scenarioName is required!');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const localValue = window.localStorage.getItem(getLSName(scenarioName));
|
||||||
|
if (localValue) {
|
||||||
|
return JSON.parse(localValue);
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
const setProjectSchemaToLocalStorage = (scenarioName: string) => {
|
||||||
|
if (!scenarioName) {
|
||||||
|
console.error('scenarioName is required!');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
window.localStorage.setItem(
|
||||||
|
getLSName(scenarioName),
|
||||||
|
JSON.stringify(project.exportSchema(IPublicEnumTransformStage.Save))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const setPackagesToLocalStorage = async (scenarioName: string) => {
|
||||||
|
if (!scenarioName) {
|
||||||
|
console.error('scenarioName is required!');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// const packages = await filterPackages(material.getAssets().packages);
|
||||||
|
window.localStorage.setItem(
|
||||||
|
getLSName(scenarioName, 'packages'),
|
||||||
|
JSON.stringify({}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getPackagesFromLocalStorage = (scenarioName: string) => {
|
||||||
|
if (!scenarioName) {
|
||||||
|
console.error('scenarioName is required!');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
return JSON.parse(window.localStorage.getItem(getLSName(scenarioName, 'packages')) || '{}');
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getProjectSchema = async (scenarioName: string = 'unknown') : Promise<IPublicTypeProjectSchema> => {
|
||||||
|
const pageSchema = await getPageSchema(scenarioName);
|
||||||
|
return generateProjectSchema(pageSchema, DefaultI18nSchema);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getPageSchema = async (scenarioName: string = 'unknown') => {
|
||||||
|
const pageSchema = getProjectSchemaFromLocalStorage(scenarioName)?.componentsTree?.[0];
|
||||||
|
if (pageSchema) {
|
||||||
|
return pageSchema;
|
||||||
|
}
|
||||||
|
|
||||||
|
return DefaultPageSchema;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getPreviewLocale = (scenarioName: string) => {
|
||||||
|
const key = getLSName(scenarioName, 'previewLocale');
|
||||||
|
return window.localStorage.getItem(key) || 'zh-CN';
|
||||||
|
}
|
||||||
|
|
||||||
|
export const setPreviewLocale = (scenarioName: string, locale: string) => {
|
||||||
|
const key = getLSName(scenarioName, 'previewLocale');
|
||||||
|
window.localStorage.setItem(key, locale || 'zh-CN');
|
||||||
|
window.location.reload();
|
||||||
|
}
|
||||||
445
playground/engine/src/services/schema.json
Normal file
445
playground/engine/src/services/schema.json
Normal file
@ -0,0 +1,445 @@
|
|||||||
|
{
|
||||||
|
"componentName": "Page",
|
||||||
|
"id": "node_dockcviv8fo1",
|
||||||
|
"docId": "doclaqkk3b9",
|
||||||
|
"props": {
|
||||||
|
"ref": "outerView",
|
||||||
|
"style": {
|
||||||
|
"height": "100%"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"fileName": "/",
|
||||||
|
"dataSource": {
|
||||||
|
"list": [
|
||||||
|
{
|
||||||
|
"type": "fetch",
|
||||||
|
"isInit": true,
|
||||||
|
"options": {
|
||||||
|
"params": {},
|
||||||
|
"method": "GET",
|
||||||
|
"isCors": true,
|
||||||
|
"timeout": 5000,
|
||||||
|
"headers": {},
|
||||||
|
"uri": "mock/info.json"
|
||||||
|
},
|
||||||
|
"id": "info",
|
||||||
|
"shouldFetch": {
|
||||||
|
"type": "JSFunction",
|
||||||
|
"value": "function() { \n console.log('should fetch.....');\n return true; \n}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"state": {
|
||||||
|
"text": {
|
||||||
|
"type": "JSExpression",
|
||||||
|
"value": "\"outer\""
|
||||||
|
},
|
||||||
|
"isShowDialog": {
|
||||||
|
"type": "JSExpression",
|
||||||
|
"value": "false"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"css": "body {\n font-size: 12px;\n}\n\n.button {\n width: 100px;\n color: #ff00ff\n}",
|
||||||
|
"lifeCycles": {
|
||||||
|
"componentDidMount": {
|
||||||
|
"type": "JSFunction",
|
||||||
|
"value": "function componentDidMount() {\n console.log('did mount');\n}"
|
||||||
|
},
|
||||||
|
"componentWillUnmount": {
|
||||||
|
"type": "JSFunction",
|
||||||
|
"value": "function componentWillUnmount() {\n console.log('will unmount');\n}"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"methods": {
|
||||||
|
"testFunc": {
|
||||||
|
"type": "JSFunction",
|
||||||
|
"value": "function testFunc() {\n console.log('test func');\n}"
|
||||||
|
},
|
||||||
|
"onClick": {
|
||||||
|
"type": "JSFunction",
|
||||||
|
"value": "function onClick() {\n this.setState({\n isShowDialog: true\n });\n}"
|
||||||
|
},
|
||||||
|
"closeDialog": {
|
||||||
|
"type": "JSFunction",
|
||||||
|
"value": "function closeDialog() {\n this.setState({\n isShowDialog: false\n });\n}"
|
||||||
|
},
|
||||||
|
"onClickTestConstants": {
|
||||||
|
"type": "JSFunction",
|
||||||
|
"value": "function onClickTestConstants() {\n console.log('this.constants.ConstantA', this.constants.ConstantA);\n console.log('this.constants.ConstantB', this.constants.ConstantB);\n}"
|
||||||
|
},
|
||||||
|
"onClickTestUtils": {
|
||||||
|
"type": "JSFunction",
|
||||||
|
"value": "function onClickTestUtils() {\n this.utils.demoUtil('a', 'b');\n}"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"originCode": "class LowcodeComponent extends Component {\n state = {\n \"text\": \"outer\",\n \"isShowDialog\": false\n }\n componentDidMount() {\n console.log('did mount');\n }\n componentWillUnmount() {\n console.log('will unmount');\n }\n testFunc() {\n console.log('test func');\n }\n onClick() {\n this.setState({\n isShowDialog: true\n })\n }\n closeDialog() {\n this.setState({\n isShowDialog: false\n })\n }\n\tonClickTestConstants(){\n console.log('this.constants.ConstantA', this.constants.ConstantA);\n console.log('this.constants.ConstantB', this.constants.ConstantB);\n }\n onClickTestUtils() {\n this.utils.demoUtil('a', 'b');\n }\n}",
|
||||||
|
"hidden": false,
|
||||||
|
"title": "",
|
||||||
|
"isLocked": false,
|
||||||
|
"condition": true,
|
||||||
|
"conditionGroup": "",
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"componentName": "NextPage",
|
||||||
|
"id": "node_ockzs2vw431",
|
||||||
|
"docId": "doclaqkk3b9",
|
||||||
|
"props": {
|
||||||
|
"headerDivider": true,
|
||||||
|
"minHeight": "100vh",
|
||||||
|
"presetNav": true,
|
||||||
|
"presetAside": true,
|
||||||
|
"footer": false,
|
||||||
|
"nav": false,
|
||||||
|
"aside": false,
|
||||||
|
"placeholderStyle": {
|
||||||
|
"gridRowEnd": "span 1",
|
||||||
|
"gridColumnEnd": "span 12"
|
||||||
|
},
|
||||||
|
"headerProps": {
|
||||||
|
"background": "surface"
|
||||||
|
},
|
||||||
|
"header": {
|
||||||
|
"type": "JSSlot",
|
||||||
|
"value": {
|
||||||
|
"componentName": "NextPageHeader",
|
||||||
|
"id": "node_ockzs2vw433",
|
||||||
|
"docId": "doclaqkk3b9",
|
||||||
|
"props": {},
|
||||||
|
"title": "页面头部",
|
||||||
|
"hidden": false,
|
||||||
|
"isLocked": false,
|
||||||
|
"condition": true,
|
||||||
|
"conditionGroup": "",
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"componentName": "NextRowColContainer",
|
||||||
|
"id": "node_ockzs2vw434",
|
||||||
|
"docId": "doclaqkk3b9",
|
||||||
|
"props": {
|
||||||
|
"rowGap": 20,
|
||||||
|
"colGap": 20
|
||||||
|
},
|
||||||
|
"title": "行列容器",
|
||||||
|
"hidden": false,
|
||||||
|
"isLocked": false,
|
||||||
|
"condition": true,
|
||||||
|
"conditionGroup": "",
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"componentName": "NextRow",
|
||||||
|
"id": "node_ockzs2vw435",
|
||||||
|
"docId": "doclaqkk3b9",
|
||||||
|
"props": {},
|
||||||
|
"title": "行",
|
||||||
|
"hidden": false,
|
||||||
|
"isLocked": false,
|
||||||
|
"condition": true,
|
||||||
|
"conditionGroup": "",
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"componentName": "NextCol",
|
||||||
|
"id": "node_ockzs2vw436",
|
||||||
|
"docId": "doclaqkk3b9",
|
||||||
|
"props": {
|
||||||
|
"colSpan": 1
|
||||||
|
},
|
||||||
|
"title": "列",
|
||||||
|
"hidden": false,
|
||||||
|
"isLocked": false,
|
||||||
|
"condition": true,
|
||||||
|
"conditionGroup": "",
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"componentName": "NextP",
|
||||||
|
"id": "node_ockzvfoetv17",
|
||||||
|
"docId": "dockzvfoetv",
|
||||||
|
"props": {
|
||||||
|
"wrap": false,
|
||||||
|
"type": "body2",
|
||||||
|
"verAlign": "middle",
|
||||||
|
"textSpacing": true,
|
||||||
|
"align": "left"
|
||||||
|
},
|
||||||
|
"title": "段落",
|
||||||
|
"hidden": false,
|
||||||
|
"isLocked": false,
|
||||||
|
"condition": true,
|
||||||
|
"conditionGroup": "",
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"componentName": "NextText",
|
||||||
|
"id": "node_ockzvfoetv18",
|
||||||
|
"docId": "dockzvfoetv",
|
||||||
|
"props": {
|
||||||
|
"type": "h5",
|
||||||
|
"children": {
|
||||||
|
"type": "JSExpression",
|
||||||
|
"value": "this.state.info?.info",
|
||||||
|
"mock": "标题标题"
|
||||||
|
},
|
||||||
|
"mark": false,
|
||||||
|
"code": false,
|
||||||
|
"delete": false,
|
||||||
|
"underline": false,
|
||||||
|
"strong": false,
|
||||||
|
"prefix": "",
|
||||||
|
"classname": "",
|
||||||
|
"ref": "nexttext-3a39ea8b"
|
||||||
|
},
|
||||||
|
"hidden": false,
|
||||||
|
"title": "",
|
||||||
|
"isLocked": false,
|
||||||
|
"condition": true,
|
||||||
|
"conditionGroup": ""
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"isTab": false,
|
||||||
|
"contentAlignCenter": false,
|
||||||
|
"contentProps": {
|
||||||
|
"style": {
|
||||||
|
"background": "rgba(255,255,255,0)"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"navProps": {
|
||||||
|
"width": 200
|
||||||
|
},
|
||||||
|
"asideProps": {
|
||||||
|
"width": 200
|
||||||
|
},
|
||||||
|
"background": "lining",
|
||||||
|
"ref": "nextpage-3cc814e7"
|
||||||
|
},
|
||||||
|
"title": "页面",
|
||||||
|
"hidden": false,
|
||||||
|
"isLocked": false,
|
||||||
|
"condition": true,
|
||||||
|
"conditionGroup": "",
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"componentName": "NextBlock",
|
||||||
|
"id": "node_oclat5fpb6ga",
|
||||||
|
"docId": "doclat87b8r",
|
||||||
|
"props": {
|
||||||
|
"placeholderStyle": {
|
||||||
|
"height": "100%"
|
||||||
|
},
|
||||||
|
"noPadding": false,
|
||||||
|
"noBorder": false,
|
||||||
|
"title": "区域标题",
|
||||||
|
"rowGap": 20,
|
||||||
|
"colGap": 20,
|
||||||
|
"background": "surface",
|
||||||
|
"layoutmode": "O",
|
||||||
|
"strict": true,
|
||||||
|
"colSpan": 12,
|
||||||
|
"rowSpan": 1,
|
||||||
|
"mode": "transparent",
|
||||||
|
"childTotalColumns": 12
|
||||||
|
},
|
||||||
|
"title": "区域",
|
||||||
|
"hidden": false,
|
||||||
|
"isLocked": false,
|
||||||
|
"condition": true,
|
||||||
|
"conditionGroup": "",
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"componentName": "NextBlockCell",
|
||||||
|
"id": "node_oclat5fpb6gb",
|
||||||
|
"docId": "doclat87b8r",
|
||||||
|
"props": {
|
||||||
|
"colSpan": 12,
|
||||||
|
"rowSpan": 1,
|
||||||
|
"mode": "procard",
|
||||||
|
"isAutoContainer": true,
|
||||||
|
"title": "区块标题",
|
||||||
|
"hasDivider": true,
|
||||||
|
"loading": false,
|
||||||
|
"hasCollapse": false,
|
||||||
|
"text": true,
|
||||||
|
"isFillContainer": true,
|
||||||
|
"operations": []
|
||||||
|
},
|
||||||
|
"hidden": false,
|
||||||
|
"title": "",
|
||||||
|
"isLocked": false,
|
||||||
|
"condition": true,
|
||||||
|
"conditionGroup": "",
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"componentName": "NextRowColContainer",
|
||||||
|
"id": "node_oclat5fpb6gc",
|
||||||
|
"docId": "doclat87b8r",
|
||||||
|
"props": {
|
||||||
|
"rowGap": 20,
|
||||||
|
"colGap": 20
|
||||||
|
},
|
||||||
|
"title": "行列容器",
|
||||||
|
"hidden": false,
|
||||||
|
"isLocked": false,
|
||||||
|
"condition": true,
|
||||||
|
"conditionGroup": "",
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"componentName": "NextRow",
|
||||||
|
"id": "node_oclat5fpb6gd",
|
||||||
|
"docId": "doclat87b8r",
|
||||||
|
"props": {},
|
||||||
|
"title": "行",
|
||||||
|
"hidden": false,
|
||||||
|
"isLocked": false,
|
||||||
|
"condition": true,
|
||||||
|
"conditionGroup": "",
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"componentName": "NextCol",
|
||||||
|
"id": "node_oclat5fpb6ge",
|
||||||
|
"docId": "doclat87b8r",
|
||||||
|
"props": {
|
||||||
|
"colSpan": 1
|
||||||
|
},
|
||||||
|
"title": "列",
|
||||||
|
"hidden": false,
|
||||||
|
"isLocked": false,
|
||||||
|
"condition": true,
|
||||||
|
"conditionGroup": "",
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"componentName": "NextP",
|
||||||
|
"id": "node_oclat5fpb6gf",
|
||||||
|
"docId": "doclat87b8r",
|
||||||
|
"props": {
|
||||||
|
"wrap": false,
|
||||||
|
"type": "body2",
|
||||||
|
"verAlign": "middle",
|
||||||
|
"textSpacing": true,
|
||||||
|
"align": "left"
|
||||||
|
},
|
||||||
|
"title": "段落",
|
||||||
|
"hidden": false,
|
||||||
|
"isLocked": false,
|
||||||
|
"condition": true,
|
||||||
|
"conditionGroup": "",
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"componentName": "Button",
|
||||||
|
"id": "node_oclat5fpb6gg",
|
||||||
|
"docId": "doclat5fpb6",
|
||||||
|
"props": {
|
||||||
|
"prefix": "next-",
|
||||||
|
"type": "primary",
|
||||||
|
"size": "medium",
|
||||||
|
"htmlType": "button",
|
||||||
|
"component": "button",
|
||||||
|
"children": "测试constants",
|
||||||
|
"iconSize": "xxs",
|
||||||
|
"loading": false,
|
||||||
|
"text": false,
|
||||||
|
"warning": false,
|
||||||
|
"disabled": false,
|
||||||
|
"__events": {
|
||||||
|
"eventDataList": [
|
||||||
|
{
|
||||||
|
"type": "componentEvent",
|
||||||
|
"name": "onClick",
|
||||||
|
"relatedEventName": "onClickTestConstants"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"eventList": [
|
||||||
|
{
|
||||||
|
"name": "onClick",
|
||||||
|
"description": "点击按钮的回调\n@param {Object} e Event Object",
|
||||||
|
"disabled": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "onMouseUp",
|
||||||
|
"disabled": false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"onClick": {
|
||||||
|
"type": "JSFunction",
|
||||||
|
"value": "function(){this.onClickTestConstants.apply(this,Array.prototype.slice.call(arguments).concat([])) }"
|
||||||
|
},
|
||||||
|
"ghost": false
|
||||||
|
},
|
||||||
|
"hidden": false,
|
||||||
|
"title": "",
|
||||||
|
"isLocked": false,
|
||||||
|
"condition": true,
|
||||||
|
"conditionGroup": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"componentName": "Button",
|
||||||
|
"id": "node_oclat5fpb6gh",
|
||||||
|
"docId": "doclat5fpb6",
|
||||||
|
"props": {
|
||||||
|
"prefix": "next-",
|
||||||
|
"type": "primary",
|
||||||
|
"size": "medium",
|
||||||
|
"htmlType": "button",
|
||||||
|
"component": "button",
|
||||||
|
"children": "测试utils",
|
||||||
|
"iconSize": "xxs",
|
||||||
|
"loading": false,
|
||||||
|
"text": false,
|
||||||
|
"warning": false,
|
||||||
|
"disabled": false,
|
||||||
|
"ref": "button-0d20c188",
|
||||||
|
"__events": {
|
||||||
|
"eventDataList": [
|
||||||
|
{
|
||||||
|
"type": "componentEvent",
|
||||||
|
"name": "onClick",
|
||||||
|
"relatedEventName": "onClickTestUtils"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"eventList": [
|
||||||
|
{
|
||||||
|
"name": "onClick",
|
||||||
|
"description": "点击按钮的回调\n@param {Object} e Event Object",
|
||||||
|
"disabled": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "onMouseUp",
|
||||||
|
"disabled": false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"onClick": {
|
||||||
|
"type": "JSFunction",
|
||||||
|
"value": "function(){this.onClickTestUtils.apply(this,Array.prototype.slice.call(arguments).concat([])) }"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"hidden": false,
|
||||||
|
"title": "",
|
||||||
|
"isLocked": false,
|
||||||
|
"condition": true,
|
||||||
|
"conditionGroup": ""
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@ -7,6 +7,16 @@
|
|||||||
"dev": "vite"
|
"dev": "vite"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@alilc/lowcode-engine": "workspace:*"
|
"@alilc/lowcode-types": "workspace:*",
|
||||||
|
"@alilc/lowcode-engine": "workspace:*",
|
||||||
|
"@alilc/lowcode-react-renderer": "workspace:*",
|
||||||
|
"@alifd/next": "^1.27.10",
|
||||||
|
"react": "^18.2.0",
|
||||||
|
"react-dom": "^18.2.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/react": "^18.2.75",
|
||||||
|
"@types/react-dom": "^18.2.24",
|
||||||
|
"vite-plugin-external": "^4.3.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import { defineConfig } from 'vite'
|
import { defineConfig } from 'vite'
|
||||||
import { resolve } from 'node:path'
|
import { resolve } from 'node:path'
|
||||||
|
import createExternal from 'vite-plugin-external'
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
build: {
|
build: {
|
||||||
@ -9,5 +10,14 @@ export default defineConfig({
|
|||||||
renderer: resolve(import.meta.dirname, 'renderer/index.html')
|
renderer: resolve(import.meta.dirname, 'renderer/index.html')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
plugins: [
|
||||||
|
createExternal({
|
||||||
|
externals: {
|
||||||
|
react: 'React',
|
||||||
|
'react-dom': 'ReactDOM',
|
||||||
|
'@alifd/next': 'Next'
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
]
|
||||||
|
})
|
||||||
|
|||||||
@ -7,6 +7,7 @@ const args = minimist(argv.slice(2));
|
|||||||
const targets = args['_'];
|
const targets = args['_'];
|
||||||
const formatArgs = args['formats'];
|
const formatArgs = args['formats'];
|
||||||
const prod = args['prod'] || args['p'];
|
const prod = args['prod'] || args['p'];
|
||||||
|
const buildTypes = args['types'] || args['t']
|
||||||
|
|
||||||
async function run() {
|
async function run() {
|
||||||
const packages = await findWorkspacePackages(cwd());
|
const packages = await findWorkspacePackages(cwd());
|
||||||
@ -18,9 +19,15 @@ async function run() {
|
|||||||
await execa('pnpm', ['--filter', finalName[0], 'build:target'], {
|
await execa('pnpm', ['--filter', finalName[0], 'build:target'], {
|
||||||
stdio: 'inherit',
|
stdio: 'inherit',
|
||||||
env: {
|
env: {
|
||||||
FORMATS: !prod ? formatArgs : undefined,
|
FORMATS: formatArgs ? formatArgs : !prod ? 'es' : undefined,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (buildTypes) {
|
||||||
|
await execa('pnpm', ['--filter', finalName[0], 'build:dts'], {
|
||||||
|
stdio: 'inherit',
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
run();
|
run();
|
||||||
|
|||||||
@ -36,7 +36,8 @@
|
|||||||
// provide type friendly tips
|
// provide type friendly tips
|
||||||
"paths": {
|
"paths": {
|
||||||
"@alilc/lowcode-*": ["packages/*/src"]
|
"@alilc/lowcode-*": ["packages/*/src"]
|
||||||
}
|
},
|
||||||
|
"types": ["vitest/globals", "node"]
|
||||||
},
|
},
|
||||||
"exclude": ["**/dist", "node_modules"]
|
"exclude": ["**/dist", "node_modules"]
|
||||||
}
|
}
|
||||||
|
|||||||
13
vitest.workspace.ts
Normal file
13
vitest.workspace.ts
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import { defineWorkspace } from 'vitest/config';
|
||||||
|
|
||||||
|
export default defineWorkspace([
|
||||||
|
'packages/*/vitest.config.{e2e,unit}.ts',
|
||||||
|
{
|
||||||
|
test: {
|
||||||
|
include: ['**/__tests__/**/*.spec.{ts?(x),js?(x)}'],
|
||||||
|
name: 'unit test',
|
||||||
|
environment: 'jsdom',
|
||||||
|
globals: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
])
|
||||||
Loading…
x
Reference in New Issue
Block a user