@tntd/monaco-editor 1.0.1 → 1.0.3
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/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +2 -1
- package/src/BaseMonacoEditor.js +206 -0
- package/src/DiffEditor.js +72 -0
- package/src/FormulaEditor.js +235 -0
- package/src/I18N.js +7 -0
- package/src/core/BaseEditor.js +389 -0
- package/src/index.js +7 -0
- package/src/index.less +11 -0
- package/src/plugins/cascader/Cascader.js +148 -0
- package/src/plugins/cascader/Cascader.less +59 -0
- package/src/plugins/cascader/index.js +503 -0
- package/src/plugins/converter/index.js +606 -0
- package/src/plugins/suggestion/index.js +157 -0
- package/src/theme/defineScript.js +119 -0
- package/src/theme/defineTheme.js +30 -0
- package/src/utils/format.js +72 -0
- package/src/utils/index.js +91 -0
|
@@ -0,0 +1,606 @@
|
|
|
1
|
+
import { findNearestLeftParenthesisIndex } from '../../utils';
|
|
2
|
+
export class ConverterPlugin {
|
|
3
|
+
constructor(options = {}) {
|
|
4
|
+
this.name = 'converter';
|
|
5
|
+
this.options = options;
|
|
6
|
+
this.regExpState = '@[^\\+\\*\\/#%\\(\\),;\\!\\<\\>\\-=@]*';
|
|
7
|
+
this.regExps = {
|
|
8
|
+
field: null,
|
|
9
|
+
method: null,
|
|
10
|
+
methodGlobal: null,
|
|
11
|
+
normalGlobal: null
|
|
12
|
+
};
|
|
13
|
+
this.modeField = null;
|
|
14
|
+
this.baseEditor = null;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
apply(baseEditor) {
|
|
18
|
+
this.baseEditor = baseEditor;
|
|
19
|
+
|
|
20
|
+
// 1. 初始化正则和模式字段
|
|
21
|
+
this.initRegExps();
|
|
22
|
+
|
|
23
|
+
// 2. 更新编辑器语言配置
|
|
24
|
+
if (this.baseEditor.options.isFormula) {
|
|
25
|
+
this.baseEditor.updateLanguage(this.modeField);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// 3. 绑定方法到编辑器实例
|
|
29
|
+
Object.assign(this.baseEditor, {
|
|
30
|
+
CnCodeToEn: this.CnCodeToEn.bind(this),
|
|
31
|
+
EnCodeToCn: this.EnCodeToCn.bind(this),
|
|
32
|
+
getRegExps: this.getRegExps.bind(this),
|
|
33
|
+
getModeField: this.getModeField.bind(this),
|
|
34
|
+
updateRegExps: this.initRegExps.bind(this),
|
|
35
|
+
updateConverterData: this.updateData.bind(this)
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// 初始化各种正则表达式和模式字段
|
|
40
|
+
initRegExps() {
|
|
41
|
+
const { fieldList = [], methodList = [], normalList = [], keyWords = [], regExpState } = this.options;
|
|
42
|
+
|
|
43
|
+
// 处理字段列表
|
|
44
|
+
const fArr = fieldList.map((item) => `@${item.name.replace(/\[/g, '\\[').replace(/\]/g, '\\]')}`).sort(this.sortByLength);
|
|
45
|
+
|
|
46
|
+
// 处理方法列表
|
|
47
|
+
const mArr = methodList.map((item) => `#${item.name}`).sort(this.sortByLength);
|
|
48
|
+
|
|
49
|
+
// 处理普通列表(转义特殊字符)
|
|
50
|
+
const nArr = normalList.map((item) => item.name.replace(/[\\^$.*+?()[\]{}|]/g, '\\$&')).sort(this.sortByLength);
|
|
51
|
+
|
|
52
|
+
const pattern = `(^|['"][^'"]*)(${nArr.join('|')})`;
|
|
53
|
+
|
|
54
|
+
// 设置正则表达式
|
|
55
|
+
this.regExps = {
|
|
56
|
+
field: new RegExp(`(${fArr.join('|')})`),
|
|
57
|
+
method: new RegExp(`(${mArr.join('|')})`),
|
|
58
|
+
methodGlobal: new RegExp(`(${mArr.join('|')})`, 'g'),
|
|
59
|
+
// normal 不能以引号开头
|
|
60
|
+
// normalGlobal: new RegExp(`(?<!['"])(${nArr.join('|')})`, 'g')
|
|
61
|
+
normalGlobal: new RegExp(pattern, 'g')
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
if (regExpState) {
|
|
65
|
+
this.regExpState = regExpState;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// 设置模式字段(供分词高亮使用)
|
|
69
|
+
this.modeField = {
|
|
70
|
+
codemirrorFieldList: this.getLocalList(fieldList, '@'),
|
|
71
|
+
codemirrorMethodList: this.getLocalList(methodList, '#'),
|
|
72
|
+
codemirrorNormalList: this.getLocalList(normalList, ''),
|
|
73
|
+
codemirrorKeywordList: keyWords
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// 获取本地列表
|
|
78
|
+
getLocalList(list, type) {
|
|
79
|
+
if (!list?.length) return [];
|
|
80
|
+
|
|
81
|
+
let copyList = [...list];
|
|
82
|
+
if (type === '@') {
|
|
83
|
+
copyList = this.formatLocalFieldList(copyList, []);
|
|
84
|
+
}
|
|
85
|
+
const nameKey = this.options.fieldNames?.label || 'name';
|
|
86
|
+
// 排序,把长的放前面
|
|
87
|
+
return copyList.sort((a, b) => b[nameKey].length - a[nameKey].length).map((item) => `${type}${item[nameKey]}`);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// 获取正则表达式
|
|
91
|
+
getRegExps() {
|
|
92
|
+
return {
|
|
93
|
+
regExpState: this.regExpState,
|
|
94
|
+
...this.regExps
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// 获取模式字段
|
|
99
|
+
/**
|
|
100
|
+
* Gets the mode field value
|
|
101
|
+
* @returns {string} The current mode field value
|
|
102
|
+
*/
|
|
103
|
+
getModeField() {
|
|
104
|
+
return this.modeField;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// 提取所有[]内部的原始字符串(正则匹配)
|
|
108
|
+
extractBracketContent = (expr) => {
|
|
109
|
+
const results = [];
|
|
110
|
+
let bracketCount = 0;
|
|
111
|
+
let startIdx = -1;
|
|
112
|
+
for (let i = 0; i < expr.length; i++) {
|
|
113
|
+
const char = expr[i];
|
|
114
|
+
if (char === '[') {
|
|
115
|
+
bracketCount++;
|
|
116
|
+
if (startIdx === -1) startIdx = i + 1;
|
|
117
|
+
} else if (char === ']' && bracketCount > 0) {
|
|
118
|
+
bracketCount--;
|
|
119
|
+
if (bracketCount === 0) {
|
|
120
|
+
results.push(expr.slice(startIdx, i));
|
|
121
|
+
startIdx = -1;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
return results;
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
// 3. 步骤2:动态映射(支持多个动态索引源,自动分配别名)
|
|
129
|
+
mapBracketContent = (originalContents) => {
|
|
130
|
+
// 存储:别名 → 原始动态索引源(如 x1 → "@xxx.@年龄【整数】")
|
|
131
|
+
const aliasToSourceMap = new Map();
|
|
132
|
+
// 统计动态索引源数量,用于分配别名(x1、x2...)
|
|
133
|
+
let dynamicIndexCount = 0;
|
|
134
|
+
|
|
135
|
+
const mappedIndexes = originalContents.map((content) => {
|
|
136
|
+
// 规则1:匹配「@字段名【类型】」格式(动态索引源)
|
|
137
|
+
const isNumberStr = /^\d+$/.test(content);
|
|
138
|
+
if (!isNumberStr && content) {
|
|
139
|
+
dynamicIndexCount++;
|
|
140
|
+
const alias = `$x${dynamicIndexCount}$`; // 分配唯一别名 x1、x2...
|
|
141
|
+
aliasToSourceMap.set(alias, content); // 记录别名与原始路径的映射
|
|
142
|
+
return alias;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// 规则2:纯数字字符串 → 转为整数(固定索引)
|
|
146
|
+
if (isNumberStr) {
|
|
147
|
+
return parseInt(content, 10);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// 规则3:其他情况 → 保留原始值
|
|
151
|
+
return content;
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
return { mappedIndexes, aliasToSourceMap };
|
|
155
|
+
};
|
|
156
|
+
|
|
157
|
+
replaceBracketContent = (expr, replacements) => {
|
|
158
|
+
let result = '';
|
|
159
|
+
let bracketCount = 0;
|
|
160
|
+
let startPosInResult = -1; // 记录「[」在result中的位置(而非原始expr的索引)
|
|
161
|
+
let replaceIdx = 0; // 替换值的指针
|
|
162
|
+
|
|
163
|
+
for (let i = 0; i < expr.length; i++) {
|
|
164
|
+
const char = expr[i];
|
|
165
|
+
|
|
166
|
+
if (char === '[') {
|
|
167
|
+
bracketCount++;
|
|
168
|
+
if (startPosInResult === -1) {
|
|
169
|
+
// 记录「[」在result中的位置(此时还未拼接char,所以是当前result长度)
|
|
170
|
+
startPosInResult = result.length;
|
|
171
|
+
}
|
|
172
|
+
result += char; // 拼接「[」
|
|
173
|
+
} else if (char === ']' && bracketCount > 0) {
|
|
174
|
+
bracketCount--;
|
|
175
|
+
result += char; // 拼接「]」,此时result中已包含完整的「[]」
|
|
176
|
+
|
|
177
|
+
// 括号平衡 + 有对应替换值:执行替换
|
|
178
|
+
if (bracketCount === 0 && replaceIdx < replacements.length) {
|
|
179
|
+
const replacement = replacements[replaceIdx];
|
|
180
|
+
const replacementStr = typeof replacement === 'number' ? replacement.toString() : replacement;
|
|
181
|
+
|
|
182
|
+
// 关键:基于result自身的索引截取(而非原始expr的i)
|
|
183
|
+
const leftBracketPos = startPosInResult; // 「[」在result中的位置
|
|
184
|
+
const rightBracketPos = result.length - 1; // 「]」在result中的位置(刚拼接完「]」)
|
|
185
|
+
|
|
186
|
+
// 重构result:左括号前的内容 + [替换值] + 右括号后的内容
|
|
187
|
+
const before = result.slice(0, leftBracketPos + 1); // 包含「[」
|
|
188
|
+
const after = result.slice(rightBracketPos); // 包含「]」
|
|
189
|
+
result = before + replacementStr + after;
|
|
190
|
+
|
|
191
|
+
// 推进指针,重置状态
|
|
192
|
+
replaceIdx++;
|
|
193
|
+
startPosInResult = -1;
|
|
194
|
+
} else if (bracketCount === 0) {
|
|
195
|
+
// 无对应替换值,重置状态
|
|
196
|
+
startPosInResult = -1;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// 非括号字符:直接拼接
|
|
201
|
+
else {
|
|
202
|
+
result += char;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
return result;
|
|
207
|
+
};
|
|
208
|
+
|
|
209
|
+
// 还原[]内部
|
|
210
|
+
restoreToOriginalExpr = (replacedExpr, aliasToSourceMap) => {
|
|
211
|
+
let result = '';
|
|
212
|
+
let bracketCount = 0; // 括号平衡计数器
|
|
213
|
+
let startPosInResult = -1; // 记录「[」在result中的位置(避免索引错位)
|
|
214
|
+
|
|
215
|
+
for (let i = 0; i < replacedExpr.length; i++) {
|
|
216
|
+
const char = replacedExpr[i];
|
|
217
|
+
|
|
218
|
+
// 遇到左括号:计数+1,记录其在result中的位置
|
|
219
|
+
if (char === '[') {
|
|
220
|
+
bracketCount++;
|
|
221
|
+
if (startPosInResult === -1) {
|
|
222
|
+
// 此时未拼接当前char,result长度即为「[」即将插入的位置
|
|
223
|
+
startPosInResult = result.length;
|
|
224
|
+
}
|
|
225
|
+
result += char; // 拼接「[」
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// 遇到右括号:计数-1,拼接后检查是否平衡
|
|
229
|
+
else if (char === ']' && bracketCount > 0) {
|
|
230
|
+
bracketCount--;
|
|
231
|
+
result += char; // 拼接「]」,此时result中已包含完整「[]」
|
|
232
|
+
|
|
233
|
+
// 括号平衡:提取别名,执行还原
|
|
234
|
+
if (bracketCount === 0) {
|
|
235
|
+
const leftBracketPos = startPosInResult; // 「[」在result中的位置
|
|
236
|
+
const rightBracketPos = result.length - 1; // 「]」在result中的位置(刚拼接完)
|
|
237
|
+
|
|
238
|
+
// 提取当前[]内的别名(如$x1$)
|
|
239
|
+
const alias = result.slice(leftBracketPos + 1, rightBracketPos);
|
|
240
|
+
|
|
241
|
+
// 从映射表获取原始内容:有映射则还原,无映射则保留原别名
|
|
242
|
+
const originalContent = aliasToSourceMap.get(alias) || alias;
|
|
243
|
+
|
|
244
|
+
// 重构result:左括号前内容 + [原始内容] + 右括号后内容
|
|
245
|
+
const before = result.slice(0, leftBracketPos + 1); // 包含「[」
|
|
246
|
+
const after = result.slice(rightBracketPos); // 包含「]」
|
|
247
|
+
result = before + originalContent + after;
|
|
248
|
+
|
|
249
|
+
// 重置状态,准备下一个完整[]
|
|
250
|
+
startPosInResult = -1;
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
// 非括号字符:直接拼接
|
|
255
|
+
else {
|
|
256
|
+
result += char;
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
return result;
|
|
261
|
+
};
|
|
262
|
+
|
|
263
|
+
QuoteHandle(cnCode) {
|
|
264
|
+
// 执行提取
|
|
265
|
+
const originalBracketContents = this.extractBracketContent(cnCode);
|
|
266
|
+
// 转换成对应的标识
|
|
267
|
+
const { mappedIndexes, aliasToSourceMap } = this.mapBracketContent(originalBracketContents);
|
|
268
|
+
// 执行替换
|
|
269
|
+
const finalContent = this.replaceBracketContent(cnCode, mappedIndexes);
|
|
270
|
+
|
|
271
|
+
return { finalContent, aliasToSourceMap };
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
CnCodeToEnHandle(cnCode) {
|
|
275
|
+
const { finalContent, aliasToSourceMap } = this.QuoteHandle(cnCode);
|
|
276
|
+
const aliasQuote = Object.fromEntries(aliasToSourceMap);
|
|
277
|
+
|
|
278
|
+
Object.keys(aliasQuote).forEach((key) => {
|
|
279
|
+
const newCode = this.CnCodeToEn(aliasQuote[key], 'isSub');
|
|
280
|
+
aliasToSourceMap.set(key, newCode);
|
|
281
|
+
});
|
|
282
|
+
return {
|
|
283
|
+
finalContent,
|
|
284
|
+
aliasToSourceMap
|
|
285
|
+
};
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
// 英文转中文
|
|
289
|
+
EnCodeToCnHandle(enCode) {
|
|
290
|
+
const { finalContent, aliasToSourceMap } = this.QuoteHandle(enCode);
|
|
291
|
+
const aliasQuote = Object.fromEntries(aliasToSourceMap);
|
|
292
|
+
|
|
293
|
+
Object.keys(aliasQuote).forEach((key) => {
|
|
294
|
+
const newCode = this.EnCodeToCn(aliasQuote[key], 'isSub');
|
|
295
|
+
aliasToSourceMap.set(key, newCode);
|
|
296
|
+
});
|
|
297
|
+
return {
|
|
298
|
+
finalContent,
|
|
299
|
+
aliasToSourceMap
|
|
300
|
+
};
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
// 中文转英文
|
|
304
|
+
CnCodeToEn(cnCode, isSub) {
|
|
305
|
+
const { fieldList, methodList, normalList, cnCodeToEnExtraLogic, cnCodeToEnUniqueLogic } = this.options;
|
|
306
|
+
// 1. 处理字段转换
|
|
307
|
+
const reg = new RegExp(this.regExpState, 'g');
|
|
308
|
+
let [childList] = [];
|
|
309
|
+
|
|
310
|
+
// 统一处理[]中的对象
|
|
311
|
+
let aliasToSourceMap = new Set();
|
|
312
|
+
({ finalContent: cnCode, aliasToSourceMap } = this.CnCodeToEnHandle(cnCode));
|
|
313
|
+
|
|
314
|
+
let enCode = cnCode.replace(reg, (match, group1, group2) => {
|
|
315
|
+
const preStr = group2.substring(0, group1);
|
|
316
|
+
|
|
317
|
+
//[@ 获取 前序字符串没有以. 结尾 这种childList清空 重新从fieldList匹配
|
|
318
|
+
const endMatch = preStr.match(/\[[/s]*/);
|
|
319
|
+
if ((endMatch && preStr.endsWith(endMatch[0])) || !preStr?.endsWith('.')) {
|
|
320
|
+
childList = null;
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
let fList = childList || fieldList || [];
|
|
324
|
+
let { turnStr, leadingSpaces, trailingSpaces } = this.matchLetter(match, fList);
|
|
325
|
+
|
|
326
|
+
let fItem;
|
|
327
|
+
if (cnCodeToEnUniqueLogic) {
|
|
328
|
+
fItem = cnCodeToEnUniqueLogic({ group1, group2, fItem, list: fList, turnStr });
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
if (!fItem) {
|
|
332
|
+
fItem = fList.find((item) => `@${item.name}` === turnStr);
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
// group2 之前的字符串 group1 匹配的索引 [@a - 1]. 这种无法match到对应的 - 1]. 所以需要特殊处理
|
|
336
|
+
const specialMatch = preStr?.endsWith('].');
|
|
337
|
+
// 需要截取上一个@对象
|
|
338
|
+
if (specialMatch) {
|
|
339
|
+
if (childList?.length) {
|
|
340
|
+
fItem = childList.find((item) => `@${item.name}` === turnStr);
|
|
341
|
+
childList = fItem?.children || fItem?.data || null;
|
|
342
|
+
}
|
|
343
|
+
if (!fItem) {
|
|
344
|
+
const preIndex = findNearestLeftParenthesisIndex(preStr, preStr?.length - 2);
|
|
345
|
+
let parentObj = preStr.substring(0, preIndex);
|
|
346
|
+
parentObj = parentObj.substring(parentObj.lastIndexOf('@'), preIndex);
|
|
347
|
+
if (parentObj) {
|
|
348
|
+
const parentObjItem = (fieldList || []).find((item) => `@${item.name}` === parentObj);
|
|
349
|
+
if (parentObjItem) {
|
|
350
|
+
fItem = parentObjItem?.children?.find((item) => `@${item.name}` === turnStr);
|
|
351
|
+
childList = parentObjItem?.children ? parentObjItem?.children : parentObjItem?.data;
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
} else {
|
|
356
|
+
if (trailingSpaces?.includes('.')) {
|
|
357
|
+
childList = fItem?.children || fItem?.data || null;
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
if (fItem) {
|
|
361
|
+
turnStr = `@${fItem.value}`;
|
|
362
|
+
if (cnCodeToEnExtraLogic) {
|
|
363
|
+
const cnCodeTemp = cnCodeToEnExtraLogic(fItem);
|
|
364
|
+
if (cnCodeTemp) {
|
|
365
|
+
turnStr = cnCodeTemp + turnStr;
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
} else {
|
|
369
|
+
childList = null;
|
|
370
|
+
}
|
|
371
|
+
return leadingSpaces + turnStr + trailingSpaces;
|
|
372
|
+
});
|
|
373
|
+
|
|
374
|
+
enCode = enCode.replace(this.regExps?.methodGlobal, (match) => {
|
|
375
|
+
let turnStr = match;
|
|
376
|
+
const mItem = (methodList || []).find((item) => `#${item.name}` === match);
|
|
377
|
+
if (mItem) turnStr = `#${mItem.realValue}`;
|
|
378
|
+
return turnStr;
|
|
379
|
+
});
|
|
380
|
+
|
|
381
|
+
enCode = enCode.replace(this.regExps?.normalGlobal, (match) => {
|
|
382
|
+
let turnStr = match;
|
|
383
|
+
const nItem = (normalList || []).find((item) => item.name === match);
|
|
384
|
+
if (nItem) turnStr = nItem.value;
|
|
385
|
+
return turnStr;
|
|
386
|
+
});
|
|
387
|
+
|
|
388
|
+
const subInfo = Object.fromEntries(aliasToSourceMap);
|
|
389
|
+
if (!isSub && Object.keys(subInfo)?.length) {
|
|
390
|
+
enCode = this.restoreToOriginalExpr(enCode, aliasToSourceMap);
|
|
391
|
+
}
|
|
392
|
+
return enCode;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
// 英文转中文
|
|
396
|
+
EnCodeToCn(enCode, isSub) {
|
|
397
|
+
if (!enCode) {
|
|
398
|
+
return enCode;
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
// 统一处理[]中的对象
|
|
402
|
+
let aliasToSourceMap = new Set();
|
|
403
|
+
({ finalContent: enCode, aliasToSourceMap } = this.EnCodeToCnHandle(enCode));
|
|
404
|
+
|
|
405
|
+
let [childList] = [];
|
|
406
|
+
const reg = new RegExp(this.regExpState, 'g');
|
|
407
|
+
|
|
408
|
+
const { fieldList, methodList, normalList, enCodeToCnExtraLogic } = this.options;
|
|
409
|
+
|
|
410
|
+
const mValueArr = (methodList || []).map((item) => `#${item.realValue}`).sort(this.sortByLength);
|
|
411
|
+
const nValueArr = (normalList || []).map((item) => item.value).sort(this.sortByLength);
|
|
412
|
+
|
|
413
|
+
const keywords = [...mValueArr, ...nValueArr].join('|');
|
|
414
|
+
const curRegExp = new RegExp(`(${keywords})`, 'g');
|
|
415
|
+
|
|
416
|
+
let cnCode = enCode.replace(reg, (match, group1, group2) => {
|
|
417
|
+
let { turnStr, leadingSpaces, trailingSpaces } = this.matchLetter(match);
|
|
418
|
+
|
|
419
|
+
const preStr = group2.substring(0, group1);
|
|
420
|
+
//[αString 或者 没有以.αOBJECT 结尾的 重新设置子项目的列表
|
|
421
|
+
const endMatchNew = /\[\α?[a-zA-Z]*$/;
|
|
422
|
+
const endNormalMatchNew = /\.\α?[a-zA-Z]*$/;
|
|
423
|
+
if (endMatchNew?.test(preStr) || !endNormalMatchNew?.test(preStr)) {
|
|
424
|
+
childList = null;
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
let fItem = (childList || fieldList || []).find((item) => `@${item.value}` === turnStr);
|
|
428
|
+
|
|
429
|
+
// 特殊处理:处理 以 ].αString 结尾的情况
|
|
430
|
+
const regexEnd = /\]\.\α?[a-zA-Z]*$/;
|
|
431
|
+
const specialMatch = regexEnd.test(preStr);
|
|
432
|
+
if (specialMatch) {
|
|
433
|
+
const matchResult = preStr.match(regexEnd);
|
|
434
|
+
if (!matchResult) return null;
|
|
435
|
+
const preIndex = findNearestLeftParenthesisIndex(preStr, matchResult.index);
|
|
436
|
+
if (preIndex === -1) return null;
|
|
437
|
+
let parentObj = preStr.substring(0, preIndex);
|
|
438
|
+
parentObj = parentObj.substring(parentObj.lastIndexOf('@'), preIndex);
|
|
439
|
+
|
|
440
|
+
if (parentObj) {
|
|
441
|
+
if (childList?.length) {
|
|
442
|
+
fItem = childList.find((item) => `@${item.value}` === turnStr);
|
|
443
|
+
} else {
|
|
444
|
+
const parentObjItemArr = (fieldList || []).filter((item) => `@${item.value}` === parentObj);
|
|
445
|
+
|
|
446
|
+
parentObjItemArr?.forEach((parentObjItem) => {
|
|
447
|
+
if (!fItem) {
|
|
448
|
+
fItem = parentObjItem?.children?.find((item) => `@${item.value}` === turnStr);
|
|
449
|
+
}
|
|
450
|
+
});
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
// 更新子列表并替换字符串
|
|
456
|
+
if (fItem) {
|
|
457
|
+
if (trailingSpaces?.includes('.')) {
|
|
458
|
+
childList = fItem?.children || fItem?.data || null;
|
|
459
|
+
} else {
|
|
460
|
+
childList = null;
|
|
461
|
+
}
|
|
462
|
+
turnStr = `@${fItem.name}`;
|
|
463
|
+
} else {
|
|
464
|
+
childList = null;
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
return leadingSpaces + turnStr + trailingSpaces;
|
|
468
|
+
});
|
|
469
|
+
|
|
470
|
+
if (enCodeToCnExtraLogic) {
|
|
471
|
+
const cnCodeTemp = enCodeToCnExtraLogic(cnCode);
|
|
472
|
+
if (cnCodeTemp) {
|
|
473
|
+
cnCode = cnCodeTemp;
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
cnCode = cnCode.replace(curRegExp, (match) => {
|
|
478
|
+
let turnStr = match;
|
|
479
|
+
const mItem = (methodList || []).find((item) => `#${item.realValue}` === match);
|
|
480
|
+
if (mItem) turnStr = `#${mItem.name}`;
|
|
481
|
+
const nItem = (normalList || []).find((item) => item.value === match);
|
|
482
|
+
if (nItem) turnStr = nItem.name;
|
|
483
|
+
return turnStr;
|
|
484
|
+
});
|
|
485
|
+
|
|
486
|
+
const subInfo = Object.fromEntries(aliasToSourceMap);
|
|
487
|
+
if (!isSub && Object.keys(subInfo)?.length) {
|
|
488
|
+
cnCode = this.restoreToOriginalExpr(cnCode, aliasToSourceMap);
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
return cnCode;
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
// 工具方法:按长度排序(长的在前)
|
|
495
|
+
sortByLength(a, b) {
|
|
496
|
+
return b.length - a.length;
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
// 工具方法:处理空格
|
|
500
|
+
matchLetter(match) {
|
|
501
|
+
let turnStr = match.replace(/^\s*|\s*$/g, '');
|
|
502
|
+
|
|
503
|
+
const leadingSpacesMatch = match.match(/^\s*/);
|
|
504
|
+
let leadingSpaces = '';
|
|
505
|
+
if (leadingSpacesMatch && leadingSpacesMatch.length) {
|
|
506
|
+
leadingSpaces = leadingSpacesMatch[0];
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
const trailingSpacesMatch = match.match(/\s*$/);
|
|
510
|
+
let trailingSpaces = '';
|
|
511
|
+
if (trailingSpacesMatch && trailingSpacesMatch.length) {
|
|
512
|
+
trailingSpaces = trailingSpacesMatch[0];
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
// 解析存在[0-9],或者. 的场景
|
|
516
|
+
//中文(@a[0].@b)、(@a.@b)、(@a[@b])、
|
|
517
|
+
//英文 (αSTRING@a[0].αSTRING@b)、(αSTRING@a.αSTRING@b)、(αSTRIN@a[αSTRING@b])
|
|
518
|
+
if (turnStr) {
|
|
519
|
+
// 如果名称中就带点则直接返回
|
|
520
|
+
if (this.fieldList?.length && turnStr?.endsWith('.')) {
|
|
521
|
+
const findItem = this.fieldList.find((item) => `@${item.name}` === turnStr);
|
|
522
|
+
if (findItem && !findItem?.children) {
|
|
523
|
+
return {
|
|
524
|
+
turnStr,
|
|
525
|
+
leadingSpaces,
|
|
526
|
+
trailingSpaces
|
|
527
|
+
};
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
// turnStr?.includes('[α')
|
|
532
|
+
const regex1 = /\[[\s]*α?/;
|
|
533
|
+
const matched = turnStr.match(regex1);
|
|
534
|
+
|
|
535
|
+
if (turnStr?.endsWith('.') || turnStr?.endsWith(']') || turnStr?.endsWith('[') || turnStr?.includes('.α') || matched) {
|
|
536
|
+
const lastEndDot = turnStr.lastIndexOf('.');
|
|
537
|
+
const lastLQuote = turnStr.lastIndexOf('[');
|
|
538
|
+
const firstRQuote = turnStr.indexOf(']');
|
|
539
|
+
// [xxx]. [xx]
|
|
540
|
+
if ((lastLQuote > -1 && lastLQuote < lastEndDot) || (lastLQuote > -1 && lastEndDot < 0)) {
|
|
541
|
+
trailingSpaces = (turnStr.substring(lastLQuote) || '') + trailingSpaces;
|
|
542
|
+
turnStr = turnStr.substring(0, lastLQuote);
|
|
543
|
+
}
|
|
544
|
+
// ]. αSTRIN@a[αSTRING@b]
|
|
545
|
+
else if (firstRQuote > -1 && lastEndDot > -1 && firstRQuote < lastEndDot) {
|
|
546
|
+
trailingSpaces = (turnStr.substring(firstRQuote) || '') + trailingSpaces;
|
|
547
|
+
turnStr = turnStr.substring(0, firstRQuote);
|
|
548
|
+
} else if (lastEndDot > -1) {
|
|
549
|
+
trailingSpaces = (turnStr.substring(lastEndDot) || '') + trailingSpaces;
|
|
550
|
+
turnStr = turnStr.substring(0, lastEndDot);
|
|
551
|
+
} else if (firstRQuote > -1) {
|
|
552
|
+
trailingSpaces = (turnStr.substring(firstRQuote) || '') + trailingSpaces;
|
|
553
|
+
turnStr = turnStr.substring(0, firstRQuote);
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
return {
|
|
559
|
+
turnStr,
|
|
560
|
+
leadingSpaces,
|
|
561
|
+
trailingSpaces
|
|
562
|
+
};
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
// 工具方法:处理嵌套字段
|
|
566
|
+
formatLocalFieldList(list, newList = []) {
|
|
567
|
+
const { fieldNames } = this.options;
|
|
568
|
+
const { children, label = 'name', value = 'value' } = fieldNames || {};
|
|
569
|
+
|
|
570
|
+
list.forEach((item) => {
|
|
571
|
+
if (item?.[children]?.length) {
|
|
572
|
+
this.formatLocalFieldList(item[children], newList);
|
|
573
|
+
}
|
|
574
|
+
newList.push({
|
|
575
|
+
type: item.type,
|
|
576
|
+
[label]: item[label],
|
|
577
|
+
[value]: item[value]
|
|
578
|
+
});
|
|
579
|
+
});
|
|
580
|
+
|
|
581
|
+
return newList;
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
// 更新数据
|
|
585
|
+
updateData(newData = {}) {
|
|
586
|
+
// 1. 更新选项
|
|
587
|
+
this.options = {
|
|
588
|
+
...this.options,
|
|
589
|
+
...newData
|
|
590
|
+
};
|
|
591
|
+
|
|
592
|
+
// 2. 重新初始化
|
|
593
|
+
this.initRegExps();
|
|
594
|
+
|
|
595
|
+
// 3. 如果需要,更新编辑器语言配置
|
|
596
|
+
this.baseEditor.updateLanguage(this.modeField);
|
|
597
|
+
|
|
598
|
+
return this;
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
dispose() {
|
|
602
|
+
// 清理资源
|
|
603
|
+
this.regExps = null;
|
|
604
|
+
this.modeField = null;
|
|
605
|
+
}
|
|
606
|
+
}
|