mirror of
https://github.com/Tencent/tmagic-editor.git
synced 2025-05-12 05:48:59 +08:00
feat(editor): 新增parseDSL配置,用于解析DSL,默认使用eval
This commit is contained in:
parent
1f5527270c
commit
2b881c3863
@ -33,7 +33,7 @@
|
|||||||
</TMagicCard>
|
</TMagicCard>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { inject, ref, watchEffect } from 'vue';
|
import { inject, provide, ref, watchEffect } from 'vue';
|
||||||
import { cloneDeep } from 'lodash-es';
|
import { cloneDeep } from 'lodash-es';
|
||||||
|
|
||||||
import { TMagicCard, TMagicInput, tMagicMessage } from '@tmagic/design';
|
import { TMagicCard, TMagicInput, tMagicMessage } from '@tmagic/design';
|
||||||
@ -41,6 +41,7 @@ import { ColumnConfig, TableConfig } from '@tmagic/form';
|
|||||||
import { CodeParam, Id } from '@tmagic/schema';
|
import { CodeParam, Id } from '@tmagic/schema';
|
||||||
|
|
||||||
import type { Services } from '@editor/type';
|
import type { Services } from '@editor/type';
|
||||||
|
import { getConfig } from '@editor/utils/config';
|
||||||
|
|
||||||
import CodeDraftEditor from './CodeDraftEditor.vue';
|
import CodeDraftEditor from './CodeDraftEditor.vue';
|
||||||
|
|
||||||
@ -48,6 +49,8 @@ defineOptions({
|
|||||||
name: 'MEditorFunctionEditor',
|
name: 'MEditorFunctionEditor',
|
||||||
});
|
});
|
||||||
|
|
||||||
|
provide('mForm', {});
|
||||||
|
|
||||||
const defaultParamColConfig: ColumnConfig = {
|
const defaultParamColConfig: ColumnConfig = {
|
||||||
type: 'row',
|
type: 'row',
|
||||||
label: '参数类型',
|
label: '参数类型',
|
||||||
@ -147,9 +150,8 @@ initTableModel();
|
|||||||
// 保存前钩子
|
// 保存前钩子
|
||||||
const beforeSave = (codeValue: string): boolean => {
|
const beforeSave = (codeValue: string): boolean => {
|
||||||
try {
|
try {
|
||||||
// eval检测js代码是否存在语法错误
|
// 检测js代码是否存在语法错误
|
||||||
// eslint-disable-next-line no-eval
|
getConfig('parseDSL')(codeValue);
|
||||||
eval(codeValue);
|
|
||||||
return true;
|
return true;
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
tMagicMessage.error(e.stack);
|
tMagicMessage.error(e.stack);
|
||||||
|
@ -6,6 +6,8 @@
|
|||||||
import { computed, reactive, watch } from 'vue';
|
import { computed, reactive, watch } from 'vue';
|
||||||
import serialize from 'serialize-javascript';
|
import serialize from 'serialize-javascript';
|
||||||
|
|
||||||
|
import { getConfig } from '@editor/utils/config';
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: 'MEditorCodeLink',
|
name: 'MEditorCodeLink',
|
||||||
});
|
});
|
||||||
@ -69,8 +71,8 @@ const changeHandler = (v: Record<string, any>) => {
|
|||||||
if (!props.name || !props.model) return;
|
if (!props.name || !props.model) return;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// eslint-disable-next-line no-eval
|
const parseDSL = getConfig('parseDSL');
|
||||||
props.model[props.name] = eval(`(${v[props.name]})`);
|
props.model[props.name] = parseDSL(`(${v[props.name]})`);
|
||||||
emit('change', props.model[props.name]);
|
emit('change', props.model[props.name]);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e);
|
console.error(e);
|
||||||
|
@ -64,11 +64,12 @@ export { default as LayoutContainer } from './components/SplitView.vue';
|
|||||||
export { default as SplitView } from './components/SplitView.vue';
|
export { default as SplitView } from './components/SplitView.vue';
|
||||||
|
|
||||||
const defaultInstallOpt: InstallOptions = {
|
const defaultInstallOpt: InstallOptions = {
|
||||||
// @todo, 自定义图片上传方法等编辑器依赖的外部选项
|
// eslint-disable-next-line no-eval
|
||||||
|
parseDSL: (dsl: string) => eval(dsl),
|
||||||
};
|
};
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
install: (app: App, opt?: InstallOptions): void => {
|
install: (app: App, opt?: Partial<InstallOptions>): void => {
|
||||||
const option = Object.assign(defaultInstallOpt, opt || {});
|
const option = Object.assign(defaultInstallOpt, opt || {});
|
||||||
|
|
||||||
// eslint-disable-next-line no-param-reassign
|
// eslint-disable-next-line no-param-reassign
|
||||||
|
@ -52,6 +52,7 @@ import { TMagicScrollbar } from '@tmagic/design';
|
|||||||
|
|
||||||
import SplitView from '@editor/components/SplitView.vue';
|
import SplitView from '@editor/components/SplitView.vue';
|
||||||
import type { GetColumnWidth, Services } from '@editor/type';
|
import type { GetColumnWidth, Services } from '@editor/type';
|
||||||
|
import { getConfig } from '@editor/utils/config';
|
||||||
|
|
||||||
import AddPageBox from './AddPageBox.vue';
|
import AddPageBox from './AddPageBox.vue';
|
||||||
import CodeEditor from './CodeEditor.vue';
|
import CodeEditor from './CodeEditor.vue';
|
||||||
@ -131,8 +132,8 @@ const columnWidthChange = (columnW: GetColumnWidth) => {
|
|||||||
|
|
||||||
const saveCode = (value: string) => {
|
const saveCode = (value: string) => {
|
||||||
try {
|
try {
|
||||||
// eslint-disable-next-line no-eval
|
const parseDSL = getConfig('parseDSL');
|
||||||
editorService?.set('root', eval(value));
|
editorService?.set('root', parseDSL(value));
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
console.error(e);
|
console.error(e);
|
||||||
}
|
}
|
||||||
|
@ -36,6 +36,7 @@ import StageCore, { calcValueByFontsize, getOffset, Runtime } from '@tmagic/stag
|
|||||||
|
|
||||||
import ScrollViewer from '@editor/components/ScrollViewer.vue';
|
import ScrollViewer from '@editor/components/ScrollViewer.vue';
|
||||||
import { Layout, MenuButton, MenuComponent, Services, StageOptions } from '@editor/type';
|
import { Layout, MenuButton, MenuComponent, Services, StageOptions } from '@editor/type';
|
||||||
|
import { getConfig } from '@editor/utils/config';
|
||||||
import { useStage } from '@editor/utils/stage';
|
import { useStage } from '@editor/utils/stage';
|
||||||
|
|
||||||
import ViewerMenu from './ViewerMenu.vue';
|
import ViewerMenu from './ViewerMenu.vue';
|
||||||
@ -162,8 +163,8 @@ const dropHandler = async (e: DragEvent) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (e.dataTransfer && parent && stageContainer.value && stage) {
|
if (e.dataTransfer && parent && stageContainer.value && stage) {
|
||||||
// eslint-disable-next-line no-eval
|
const parseDSL = getConfig('parseDSL');
|
||||||
const config = eval(`(${e.dataTransfer.getData('data')})`);
|
const config = parseDSL(`(${e.dataTransfer.getData('data')})`);
|
||||||
const layout = await services?.editorService.getLayout(parent);
|
const layout = await services?.editorService.getLayout(parent);
|
||||||
|
|
||||||
const containerRect = stageContainer.value.getBoundingClientRect();
|
const containerRect = stageContainer.value.getBoundingClientRect();
|
||||||
|
@ -23,6 +23,7 @@ import { CodeBlockContent, CodeBlockDSL, Id } from '@tmagic/schema';
|
|||||||
|
|
||||||
import type { CodeState } from '@editor/type';
|
import type { CodeState } from '@editor/type';
|
||||||
import { CODE_DRAFT_STORAGE_KEY } from '@editor/type';
|
import { CODE_DRAFT_STORAGE_KEY } from '@editor/type';
|
||||||
|
import { getConfig } from '@editor/utils/config';
|
||||||
|
|
||||||
import BaseService from './BaseService';
|
import BaseService from './BaseService';
|
||||||
|
|
||||||
@ -95,8 +96,8 @@ class CodeBlock extends BaseService {
|
|||||||
const codeConfigProcessed = codeConfig;
|
const codeConfigProcessed = codeConfig;
|
||||||
if (codeConfig.content) {
|
if (codeConfig.content) {
|
||||||
// 在保存的时候转换代码内容
|
// 在保存的时候转换代码内容
|
||||||
// eslint-disable-next-line no-eval
|
const parseDSL = getConfig('parseDSL');
|
||||||
codeConfigProcessed.content = eval(codeConfig.content);
|
codeConfigProcessed.content = parseDSL(codeConfig.content);
|
||||||
}
|
}
|
||||||
|
|
||||||
const existContent = codeDsl[id] || {};
|
const existContent = codeDsl[id] || {};
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
import serialize from 'serialize-javascript';
|
import serialize from 'serialize-javascript';
|
||||||
|
|
||||||
|
import { getConfig } from '@editor/utils/config';
|
||||||
|
|
||||||
import BaseService from './BaseService';
|
import BaseService from './BaseService';
|
||||||
|
|
||||||
interface Options {
|
interface Options {
|
||||||
@ -64,8 +66,7 @@ export class WebStorage extends BaseService {
|
|||||||
|
|
||||||
switch (protocol) {
|
switch (protocol) {
|
||||||
case Protocol.OBJECT:
|
case Protocol.OBJECT:
|
||||||
// eslint-disable-next-line no-eval
|
return getConfig('parseDSL')(`(${item})`);
|
||||||
return eval(`(${item})`);
|
|
||||||
case Protocol.JSON:
|
case Protocol.JSON:
|
||||||
return JSON.parse(item);
|
return JSON.parse(item);
|
||||||
case Protocol.NUMBER:
|
case Protocol.NUMBER:
|
||||||
|
@ -45,6 +45,7 @@ export type BeforeAdd = (config: MNode, parent: MContainer) => Promise<MNode> |
|
|||||||
export type GetConfig = (config: FormConfig) => Promise<FormConfig> | FormConfig;
|
export type GetConfig = (config: FormConfig) => Promise<FormConfig> | FormConfig;
|
||||||
|
|
||||||
export interface InstallOptions {
|
export interface InstallOptions {
|
||||||
|
parseDSL: (dsl: string) => MApp;
|
||||||
[key: string]: any;
|
[key: string]: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,6 +24,6 @@ const setConfig = (option: InstallOptions): void => {
|
|||||||
$TMAGIC_EDITOR = option;
|
$TMAGIC_EDITOR = option;
|
||||||
};
|
};
|
||||||
|
|
||||||
const getConfig = (key: keyof InstallOptions): unknown => $TMAGIC_EDITOR[key];
|
const getConfig = <K extends keyof InstallOptions>(key: K): InstallOptions[K] => $TMAGIC_EDITOR[key];
|
||||||
|
|
||||||
export { getConfig, setConfig };
|
export { getConfig, setConfig };
|
||||||
|
@ -25,7 +25,12 @@ import { NodeType } from '@tmagic/schema';
|
|||||||
import editorService from '@editor/services/editor';
|
import editorService from '@editor/services/editor';
|
||||||
import historyService from '@editor/services/history';
|
import historyService from '@editor/services/history';
|
||||||
import storageService from '@editor/services/storage';
|
import storageService from '@editor/services/storage';
|
||||||
import { COPY_STORAGE_KEY } from '@editor/utils';
|
import { COPY_STORAGE_KEY, setConfig } from '@editor/utils';
|
||||||
|
|
||||||
|
setConfig({
|
||||||
|
// eslint-disable-next-line no-eval
|
||||||
|
parseDSL: (dsl: string) => eval(dsl),
|
||||||
|
});
|
||||||
|
|
||||||
// mock window.localStage
|
// mock window.localStage
|
||||||
class LocalStorageMock {
|
class LocalStorageMock {
|
||||||
@ -306,7 +311,7 @@ describe('update', () => {
|
|||||||
test('没有id', async () => {
|
test('没有id', async () => {
|
||||||
try {
|
try {
|
||||||
await editorService.update({ type: 'text', text: 'text', id: '' });
|
await editorService.update({ type: 'text', text: 'text', id: '' });
|
||||||
} catch (e: InstanceType<Error>) {
|
} catch (e: any) {
|
||||||
expect(e.message).toBe('没有配置或者配置缺少id值');
|
expect(e.message).toBe('没有配置或者配置缺少id值');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -315,7 +320,7 @@ describe('update', () => {
|
|||||||
// 一般可能出现在外边扩展功能
|
// 一般可能出现在外边扩展功能
|
||||||
try {
|
try {
|
||||||
await editorService.update({ type: '', text: 'text', id: NodeId.NODE_ID });
|
await editorService.update({ type: '', text: 'text', id: NodeId.NODE_ID });
|
||||||
} catch (e: InstanceType<Error>) {
|
} catch (e: any) {
|
||||||
expect(e.message).toBe('配置缺少type值');
|
expect(e.message).toBe('配置缺少type值');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -325,7 +330,7 @@ describe('update', () => {
|
|||||||
// 设置当前编辑的页面
|
// 设置当前编辑的页面
|
||||||
await editorService.select(NodeId.PAGE_ID);
|
await editorService.select(NodeId.PAGE_ID);
|
||||||
await editorService.update({ type: 'text', text: 'text', id: NodeId.ERROR_NODE_ID });
|
await editorService.update({ type: 'text', text: 'text', id: NodeId.ERROR_NODE_ID });
|
||||||
} catch (e: InstanceType<Error>) {
|
} catch (e: any) {
|
||||||
expect(e.message).toBe(`获取不到id为${NodeId.ERROR_NODE_ID}的节点`);
|
expect(e.message).toBe(`获取不到id为${NodeId.ERROR_NODE_ID}的节点`);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
Loading…
x
Reference in New Issue
Block a user