@ticatec/dyna-js 0.0.2 → 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +32 -61
- package/README_CN.md +42 -71
- package/dist/DynaJs.d.ts +200 -7
- package/dist/DynaJs.d.ts.map +1 -1
- package/dist/DynaJs.esm.js +199 -64
- package/dist/DynaJs.js +205 -70
- package/dist/types.d.ts +0 -8
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -11,14 +11,12 @@ A TypeScript library for safe dynamic code execution using `new Function()` that
|
|
|
11
11
|
|
|
12
12
|
## Features
|
|
13
13
|
|
|
14
|
-
✅ **Universal Compatibility** - Works in both Node.js and browser environments
|
|
15
|
-
✅ **TypeScript Support** - Full type safety with comprehensive type definitions
|
|
16
|
-
✅ **Singleton Pattern** - Initialize once, use anywhere
|
|
17
|
-
✅ **Module Imports** - Pre-define classes and functions for dynamic code
|
|
18
|
-
✅ **
|
|
19
|
-
✅ **
|
|
20
|
-
✅ **Form Class Creation** - Special method for creating dynamic form classes
|
|
21
|
-
✅ **Multiple Build Formats** - CommonJS and ESM support
|
|
14
|
+
✅ **Universal Compatibility** - Works in both Node.js and browser environments
|
|
15
|
+
✅ **TypeScript Support** - Full type safety with comprehensive type definitions
|
|
16
|
+
✅ **Singleton Pattern** - Initialize once, use anywhere
|
|
17
|
+
✅ **Module Imports** - Pre-define classes and functions for dynamic code
|
|
18
|
+
✅ **Configurable Security** - Fine-grained control over allowed APIs and operations
|
|
19
|
+
✅ **Multiple Build Formats** - CommonJS and ESM support
|
|
22
20
|
✅ **Performance Monitoring** - Built-in execution time tracking
|
|
23
21
|
|
|
24
22
|
## Installation
|
|
@@ -44,8 +42,6 @@ initializeDynaJs({
|
|
|
44
42
|
FlexiContext: FlexiContextClass,
|
|
45
43
|
ModuleLoader: ModuleLoaderClass
|
|
46
44
|
},
|
|
47
|
-
defaultInjectedKeys: ['Dialog', 'MessageBox', 'Indicator', 'Toast'],
|
|
48
|
-
useProxyByDefault: true,
|
|
49
45
|
allowBrowserAPIs: false, // Secure by default
|
|
50
46
|
validateCode: true
|
|
51
47
|
});
|
|
@@ -59,18 +55,18 @@ import { getDynaJs } from '@ticatec/dyna-js';
|
|
|
59
55
|
// Get the initialized loader
|
|
60
56
|
const loader = getDynaJs();
|
|
61
57
|
|
|
62
|
-
// Create form classes
|
|
63
|
-
const MyFormClass = loader.
|
|
58
|
+
// Create form classes
|
|
59
|
+
const MyFormClass = loader.executeSync(`
|
|
64
60
|
class CustomForm extends FlexiForm {
|
|
65
61
|
constructor() {
|
|
66
62
|
super();
|
|
67
|
-
this.dialog = Dialog;
|
|
63
|
+
this.dialog = Dialog;
|
|
68
64
|
}
|
|
69
|
-
|
|
65
|
+
|
|
70
66
|
show() {
|
|
71
|
-
MessageBox.info('Form is ready!');
|
|
67
|
+
MessageBox.info('Form is ready!');
|
|
72
68
|
}
|
|
73
|
-
|
|
69
|
+
|
|
74
70
|
render() {
|
|
75
71
|
return new FlexiCard({
|
|
76
72
|
title: 'Dynamic Form',
|
|
@@ -90,51 +86,27 @@ form.show();
|
|
|
90
86
|
|
|
91
87
|
### Core Methods
|
|
92
88
|
|
|
93
|
-
#### `
|
|
89
|
+
#### `executeSync<T>(code: string, options?: ExecutionOptions): T`
|
|
94
90
|
|
|
95
|
-
|
|
91
|
+
Synchronously execute code and return the result directly.
|
|
96
92
|
|
|
97
93
|
```typescript
|
|
98
|
-
const
|
|
99
|
-
class MyForm extends FlexiForm {
|
|
100
|
-
constructor() {
|
|
101
|
-
super();
|
|
102
|
-
this.setupDialog();
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
setupDialog() {
|
|
106
|
-
this.dialog = new Dialog({
|
|
107
|
-
title: 'Dynamic Dialog'
|
|
108
|
-
});
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
return MyForm;
|
|
112
|
-
`, {
|
|
113
|
-
customData: 'additional context'
|
|
114
|
-
}, ['extraKey']);
|
|
115
|
-
```
|
|
116
|
-
|
|
117
|
-
#### `executeSync<T>(code: string, options?: ExecutionOptions): ExecutionResult<T>`
|
|
118
|
-
|
|
119
|
-
Synchronously execute code with result and timing information.
|
|
120
|
-
|
|
121
|
-
```typescript
|
|
122
|
-
const result = loader.executeSync(`
|
|
94
|
+
const form = loader.executeSync(`
|
|
123
95
|
const form = new FlexiForm();
|
|
124
96
|
form.setTitle('Dynamic Form');
|
|
125
97
|
return form;
|
|
126
98
|
`);
|
|
127
99
|
|
|
128
|
-
console.log(
|
|
129
|
-
|
|
100
|
+
console.log(form); // FlexiForm instance
|
|
101
|
+
// Execution time is logged to console automatically
|
|
130
102
|
```
|
|
131
103
|
|
|
132
|
-
#### `execute<T>(code: string, options?: ExecutionOptions): Promise<
|
|
104
|
+
#### `execute<T>(code: string, options?: ExecutionOptions): Promise<T>`
|
|
133
105
|
|
|
134
106
|
Asynchronously execute code with timeout support.
|
|
135
107
|
|
|
136
108
|
```typescript
|
|
137
|
-
const
|
|
109
|
+
const form = await loader.execute(`
|
|
138
110
|
return new Promise(resolve => {
|
|
139
111
|
const form = new FlexiForm();
|
|
140
112
|
resolve(form);
|
|
@@ -143,14 +115,16 @@ const result = await loader.execute(`
|
|
|
143
115
|
timeout: 3000,
|
|
144
116
|
context: { customVar: 'value' }
|
|
145
117
|
});
|
|
118
|
+
|
|
119
|
+
console.log(form); // FlexiForm instance
|
|
146
120
|
```
|
|
147
121
|
|
|
148
|
-
#### `executeWithImports<T>(code: string, imports: object, options?: ExecutionOptions):
|
|
122
|
+
#### `executeWithImports<T>(code: string, imports: object, options?: ExecutionOptions): T`
|
|
149
123
|
|
|
150
124
|
Execute code with additional temporary imports.
|
|
151
125
|
|
|
152
126
|
```typescript
|
|
153
|
-
const
|
|
127
|
+
const component = loader.executeWithImports(`
|
|
154
128
|
return new CustomComponent({
|
|
155
129
|
message: 'Hello from dynamic code!'
|
|
156
130
|
});
|
|
@@ -169,8 +143,6 @@ interface DynaJsConfig {
|
|
|
169
143
|
allowedGlobals?: string[]; // Whitelist of allowed global variables
|
|
170
144
|
blockedGlobals?: string[]; // Blacklist of blocked variables
|
|
171
145
|
defaultImports?: object; // Pre-imported classes/functions
|
|
172
|
-
defaultInjectedKeys?: string[]; // Auto-injected variable names
|
|
173
|
-
useProxyByDefault?: boolean; // Default: true
|
|
174
146
|
allowTimers?: boolean; // Allow setTimeout/setInterval (Default: false)
|
|
175
147
|
allowDynamicImports?: boolean; // Allow import()/require() (Default: false)
|
|
176
148
|
validateCode?: boolean; // Enable code validation (Default: true)
|
|
@@ -229,8 +201,7 @@ initializeDynaJs({
|
|
|
229
201
|
},
|
|
230
202
|
allowBrowserAPIs: false, // Still secure
|
|
231
203
|
allowTimers: false, // No timers needed for forms
|
|
232
|
-
validateCode: true
|
|
233
|
-
defaultInjectedKeys: ['window'] // Only inject window reference
|
|
204
|
+
validateCode: true // Keep validation
|
|
234
205
|
});
|
|
235
206
|
```
|
|
236
207
|
|
|
@@ -239,14 +210,14 @@ initializeDynaJs({
|
|
|
239
210
|
### Creating Dynamic Form Components
|
|
240
211
|
|
|
241
212
|
```typescript
|
|
242
|
-
const DynamicFormBuilder = loader.
|
|
213
|
+
const DynamicFormBuilder = loader.executeSync(`
|
|
243
214
|
class FormBuilder extends FlexiForm {
|
|
244
215
|
constructor(config) {
|
|
245
216
|
super();
|
|
246
217
|
this.config = config;
|
|
247
218
|
this.components = [];
|
|
248
219
|
}
|
|
249
|
-
|
|
220
|
+
|
|
250
221
|
addField(fieldConfig) {
|
|
251
222
|
const field = new FlexiCard({
|
|
252
223
|
title: fieldConfig.label,
|
|
@@ -255,7 +226,7 @@ const DynamicFormBuilder = loader.createFormClass(`
|
|
|
255
226
|
this.components.push(field);
|
|
256
227
|
return this;
|
|
257
228
|
}
|
|
258
|
-
|
|
229
|
+
|
|
259
230
|
createInput(type) {
|
|
260
231
|
switch(type) {
|
|
261
232
|
case 'text':
|
|
@@ -266,11 +237,11 @@ const DynamicFormBuilder = loader.createFormClass(`
|
|
|
266
237
|
return '<input type="text" />';
|
|
267
238
|
}
|
|
268
239
|
}
|
|
269
|
-
|
|
240
|
+
|
|
270
241
|
build() {
|
|
271
242
|
return this.components;
|
|
272
243
|
}
|
|
273
|
-
|
|
244
|
+
|
|
274
245
|
show() {
|
|
275
246
|
const dialog = new Dialog({
|
|
276
247
|
title: this.config.title,
|
|
@@ -278,12 +249,12 @@ const DynamicFormBuilder = loader.createFormClass(`
|
|
|
278
249
|
});
|
|
279
250
|
dialog.show();
|
|
280
251
|
}
|
|
281
|
-
|
|
252
|
+
|
|
282
253
|
render() {
|
|
283
254
|
return this.components.map(c => c.render()).join('');
|
|
284
255
|
}
|
|
285
256
|
}
|
|
286
|
-
|
|
257
|
+
|
|
287
258
|
return FormBuilder;
|
|
288
259
|
`);
|
|
289
260
|
|
|
@@ -337,7 +308,7 @@ try {
|
|
|
337
308
|
`);
|
|
338
309
|
} catch (error) {
|
|
339
310
|
console.error('Execution failed:', error.message);
|
|
340
|
-
// Error includes execution time and detailed error information
|
|
311
|
+
// Error message includes execution time and detailed error information
|
|
341
312
|
}
|
|
342
313
|
```
|
|
343
314
|
|
package/README_CN.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
[](https://badge.fury.io/js/@ticatec%2Fdyna-js)
|
|
4
4
|
[](https://opensource.org/licenses/MIT)
|
|
5
|
-
[](http://www.typescriptlang.org
|
|
5
|
+
[](http://www.typescriptlang.org())
|
|
6
6
|
[](https://nodejs.org/)
|
|
7
7
|
|
|
8
8
|
[English Documentation](README.md)
|
|
@@ -11,15 +11,13 @@
|
|
|
11
11
|
|
|
12
12
|
## 功能特性
|
|
13
13
|
|
|
14
|
-
✅ **通用兼容性** - 同时支持 Node.js 和浏览器环境
|
|
15
|
-
✅ **TypeScript 支持** - 完整的类型安全和类型定义
|
|
16
|
-
✅ **单例模式** - 一次初始化,全局使用
|
|
17
|
-
✅ **模块导入** - 为动态代码预定义类和函数
|
|
18
|
-
✅
|
|
19
|
-
✅
|
|
20
|
-
✅
|
|
21
|
-
✅ **多种构建格式** - 支持 CommonJS 和 ESM
|
|
22
|
-
✅ **性能监控** - 内置执行时间跟踪
|
|
14
|
+
✅ **通用兼容性** - 同时支持 Node.js 和浏览器环境
|
|
15
|
+
✅ **TypeScript 支持** - 完整的类型安全和类型定义
|
|
16
|
+
✅ **单例模式** - 一次初始化,全局使用
|
|
17
|
+
✅ **模块导入** - 为动态代码预定义类和函数
|
|
18
|
+
✅ **可配置安全性** - 对允许的 API 和操作进行细粒度控制
|
|
19
|
+
✅ **多种构建格式** - 支持 CommonJS 和 ESM
|
|
20
|
+
✅ **性能监控** - 内置执行时间跟踪
|
|
23
21
|
|
|
24
22
|
## 安装
|
|
25
23
|
|
|
@@ -44,8 +42,6 @@ initializeDynaJs({
|
|
|
44
42
|
FlexiContext: FlexiContextClass,
|
|
45
43
|
ModuleLoader: ModuleLoaderClass
|
|
46
44
|
},
|
|
47
|
-
defaultInjectedKeys: ['Dialog', 'MessageBox', 'Indicator', 'Toast'],
|
|
48
|
-
useProxyByDefault: true,
|
|
49
45
|
allowBrowserAPIs: false, // 默认安全
|
|
50
46
|
validateCode: true
|
|
51
47
|
});
|
|
@@ -60,17 +56,17 @@ import { getDynaJs } from '@ticatec/dyna-js';
|
|
|
60
56
|
const loader = getDynaJs();
|
|
61
57
|
|
|
62
58
|
// 创建表单类
|
|
63
|
-
const MyFormClass = loader.
|
|
59
|
+
const MyFormClass = loader.executeSync(`
|
|
64
60
|
class CustomForm extends FlexiForm {
|
|
65
61
|
constructor() {
|
|
66
62
|
super();
|
|
67
|
-
this.dialog = Dialog;
|
|
63
|
+
this.dialog = Dialog;
|
|
68
64
|
}
|
|
69
|
-
|
|
65
|
+
|
|
70
66
|
show() {
|
|
71
|
-
MessageBox.info('表单已就绪!');
|
|
67
|
+
MessageBox.info('表单已就绪!');
|
|
72
68
|
}
|
|
73
|
-
|
|
69
|
+
|
|
74
70
|
render() {
|
|
75
71
|
return new FlexiCard({
|
|
76
72
|
title: '动态表单',
|
|
@@ -90,51 +86,27 @@ form.show();
|
|
|
90
86
|
|
|
91
87
|
### 核心方法
|
|
92
88
|
|
|
93
|
-
#### `
|
|
94
|
-
|
|
95
|
-
使用基于代理的沙盒执行创建表单类。
|
|
96
|
-
|
|
97
|
-
```typescript
|
|
98
|
-
const FormClass = loader.createFormClass(`
|
|
99
|
-
class MyForm extends FlexiForm {
|
|
100
|
-
constructor() {
|
|
101
|
-
super();
|
|
102
|
-
this.setupDialog();
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
setupDialog() {
|
|
106
|
-
this.dialog = new Dialog({
|
|
107
|
-
title: '动态对话框'
|
|
108
|
-
});
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
return MyForm;
|
|
112
|
-
`, {
|
|
113
|
-
customData: '附加上下文'
|
|
114
|
-
}, ['extraKey']);
|
|
115
|
-
```
|
|
116
|
-
|
|
117
|
-
#### `executeSync<T>(code: string, options?: ExecutionOptions): ExecutionResult<T>`
|
|
89
|
+
#### `executeSync<T>(code: string, options?: ExecutionOptions): T`
|
|
118
90
|
|
|
119
|
-
|
|
91
|
+
同步执行代码并直接返回结果。
|
|
120
92
|
|
|
121
93
|
```typescript
|
|
122
|
-
const
|
|
94
|
+
const form = loader.executeSync(`
|
|
123
95
|
const form = new FlexiForm();
|
|
124
96
|
form.setTitle('动态表单');
|
|
125
97
|
return form;
|
|
126
98
|
`);
|
|
127
99
|
|
|
128
|
-
console.log(
|
|
129
|
-
|
|
100
|
+
console.log(form); // FlexiForm 实例
|
|
101
|
+
// 执行时间会自动记录到控制台
|
|
130
102
|
```
|
|
131
103
|
|
|
132
|
-
#### `execute<T>(code: string, options?: ExecutionOptions): Promise<
|
|
104
|
+
#### `execute<T>(code: string, options?: ExecutionOptions): Promise<T>`
|
|
133
105
|
|
|
134
106
|
异步执行代码,支持超时控制。
|
|
135
107
|
|
|
136
108
|
```typescript
|
|
137
|
-
const
|
|
109
|
+
const form = await loader.execute(`
|
|
138
110
|
return new Promise(resolve => {
|
|
139
111
|
const form = new FlexiForm();
|
|
140
112
|
resolve(form);
|
|
@@ -143,14 +115,16 @@ const result = await loader.execute(`
|
|
|
143
115
|
timeout: 3000,
|
|
144
116
|
context: { customVar: 'value' }
|
|
145
117
|
});
|
|
118
|
+
|
|
119
|
+
console.log(form); // FlexiForm 实例
|
|
146
120
|
```
|
|
147
121
|
|
|
148
|
-
#### `executeWithImports<T>(code: string, imports: object, options?: ExecutionOptions):
|
|
122
|
+
#### `executeWithImports<T>(code: string, imports: object, options?: ExecutionOptions): T`
|
|
149
123
|
|
|
150
124
|
使用额外的临时导入执行代码。
|
|
151
125
|
|
|
152
126
|
```typescript
|
|
153
|
-
const
|
|
127
|
+
const component = loader.executeWithImports(`
|
|
154
128
|
return new CustomComponent({
|
|
155
129
|
message: '来自动态代码的问候!'
|
|
156
130
|
});
|
|
@@ -169,8 +143,6 @@ interface DynaJsConfig {
|
|
|
169
143
|
allowedGlobals?: string[]; // 允许的全局变量白名单
|
|
170
144
|
blockedGlobals?: string[]; // 阻止的变量黑名单
|
|
171
145
|
defaultImports?: object; // 预导入的类/函数
|
|
172
|
-
defaultInjectedKeys?: string[]; // 自动注入的变量名
|
|
173
|
-
useProxyByDefault?: boolean; // 默认:true
|
|
174
146
|
allowTimers?: boolean; // 允许 setTimeout/setInterval(默认:false)
|
|
175
147
|
allowDynamicImports?: boolean; // 允许 import()/require()(默认:false)
|
|
176
148
|
validateCode?: boolean; // 启用代码验证(默认:true)
|
|
@@ -229,8 +201,7 @@ initializeDynaJs({
|
|
|
229
201
|
},
|
|
230
202
|
allowBrowserAPIs: false, // 仍然安全
|
|
231
203
|
allowTimers: false, // 表单不需要定时器
|
|
232
|
-
validateCode: true
|
|
233
|
-
defaultInjectedKeys: ['window'] // 只注入 window 引用
|
|
204
|
+
validateCode: true // 保持验证
|
|
234
205
|
});
|
|
235
206
|
```
|
|
236
207
|
|
|
@@ -239,14 +210,14 @@ initializeDynaJs({
|
|
|
239
210
|
### 创建动态表单组件
|
|
240
211
|
|
|
241
212
|
```typescript
|
|
242
|
-
const DynamicFormBuilder = loader.
|
|
213
|
+
const DynamicFormBuilder = loader.executeSync(`
|
|
243
214
|
class FormBuilder extends FlexiForm {
|
|
244
215
|
constructor(config) {
|
|
245
216
|
super();
|
|
246
217
|
this.config = config;
|
|
247
218
|
this.components = [];
|
|
248
219
|
}
|
|
249
|
-
|
|
220
|
+
|
|
250
221
|
addField(fieldConfig) {
|
|
251
222
|
const field = new FlexiCard({
|
|
252
223
|
title: fieldConfig.label,
|
|
@@ -255,7 +226,7 @@ const DynamicFormBuilder = loader.createFormClass(`
|
|
|
255
226
|
this.components.push(field);
|
|
256
227
|
return this;
|
|
257
228
|
}
|
|
258
|
-
|
|
229
|
+
|
|
259
230
|
createInput(type) {
|
|
260
231
|
switch(type) {
|
|
261
232
|
case 'text':
|
|
@@ -266,11 +237,11 @@ const DynamicFormBuilder = loader.createFormClass(`
|
|
|
266
237
|
return '<input type="text" />';
|
|
267
238
|
}
|
|
268
239
|
}
|
|
269
|
-
|
|
240
|
+
|
|
270
241
|
build() {
|
|
271
242
|
return this.components;
|
|
272
243
|
}
|
|
273
|
-
|
|
244
|
+
|
|
274
245
|
show() {
|
|
275
246
|
const dialog = new Dialog({
|
|
276
247
|
title: this.config.title,
|
|
@@ -278,12 +249,12 @@ const DynamicFormBuilder = loader.createFormClass(`
|
|
|
278
249
|
});
|
|
279
250
|
dialog.show();
|
|
280
251
|
}
|
|
281
|
-
|
|
252
|
+
|
|
282
253
|
render() {
|
|
283
254
|
return this.components.map(c => c.render()).join('');
|
|
284
255
|
}
|
|
285
256
|
}
|
|
286
|
-
|
|
257
|
+
|
|
287
258
|
return FormBuilder;
|
|
288
259
|
`);
|
|
289
260
|
|
|
@@ -304,15 +275,15 @@ formBuilder
|
|
|
304
275
|
const dynamicValidator = loader.createFunction(`
|
|
305
276
|
return function validateForm(formData) {
|
|
306
277
|
const errors = [];
|
|
307
|
-
|
|
278
|
+
|
|
308
279
|
if (!formData.name) {
|
|
309
280
|
errors.push('姓名是必填项');
|
|
310
281
|
}
|
|
311
|
-
|
|
282
|
+
|
|
312
283
|
if (!formData.email || !formData.email.includes('@')) {
|
|
313
284
|
errors.push('需要有效的邮箱地址');
|
|
314
285
|
}
|
|
315
|
-
|
|
286
|
+
|
|
316
287
|
return {
|
|
317
288
|
isValid: errors.length === 0,
|
|
318
289
|
errors: errors
|
|
@@ -337,7 +308,7 @@ try {
|
|
|
337
308
|
`);
|
|
338
309
|
} catch (error) {
|
|
339
310
|
console.error('执行失败:', error.message);
|
|
340
|
-
//
|
|
311
|
+
// 错误信息包含执行时间和详细的错误信息
|
|
341
312
|
}
|
|
342
313
|
```
|
|
343
314
|
|
|
@@ -354,11 +325,11 @@ try {
|
|
|
354
325
|
具有完整类型定义的 TypeScript 支持:
|
|
355
326
|
|
|
356
327
|
```typescript
|
|
357
|
-
import {
|
|
328
|
+
import {
|
|
358
329
|
DynaJs,
|
|
359
330
|
ExecutionResult,
|
|
360
331
|
ExecutionOptions,
|
|
361
|
-
ModuleImports
|
|
332
|
+
ModuleImports
|
|
362
333
|
} from '@ticatec/dyna-js';
|
|
363
334
|
```
|
|
364
335
|
|
|
@@ -395,9 +366,9 @@ MIT 许可证 - 详情请查看 [LICENSE](LICENSE) 文件。
|
|
|
395
366
|
### 动态表单创建
|
|
396
367
|
```typescript
|
|
397
368
|
// 适合创建各种动态表单组件
|
|
398
|
-
const ContactForm = loader.
|
|
399
|
-
const SurveyForm = loader.
|
|
400
|
-
const RegistrationForm = loader.
|
|
369
|
+
const ContactForm = loader.executeSync(`...`);
|
|
370
|
+
const SurveyForm = loader.executeSync(`...`);
|
|
371
|
+
const RegistrationForm = loader.executeSync(`...`);
|
|
401
372
|
```
|
|
402
373
|
|
|
403
374
|
### 业务规则执行
|
|
@@ -414,7 +385,7 @@ const businessRule = loader.executeSync(`
|
|
|
414
385
|
### 模板渲染
|
|
415
386
|
```typescript
|
|
416
387
|
// 动态模板处理
|
|
417
|
-
const templateEngine = loader.
|
|
388
|
+
const templateEngine = loader.executeSync(`
|
|
418
389
|
class TemplateEngine {
|
|
419
390
|
render(template, data) {
|
|
420
391
|
// 模板渲染逻辑
|