mm_eslint 1.4.3 → 1.4.5

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/corrector.js ADDED
@@ -0,0 +1,375 @@
1
+ const { Config } = require('./config');
2
+ const { splitWords } = require('./util.js');
3
+ /**
4
+ * 命名规范修正器类
5
+ * 负责修正命名问题
6
+ */
7
+ class Corrector {
8
+ /**
9
+ * 构造函数
10
+ * @param {object} config 配置对象
11
+ */
12
+ constructor(config) {
13
+ this.config = config || new Config();
14
+ }
15
+ }
16
+
17
+ /**
18
+ * 获取修正建议
19
+ * @param {string} name 名称
20
+ * @param {object} error 错误信息
21
+ * @returns {string} 建议名称
22
+ */
23
+ Corrector.prototype.getSuggestion = function (error) {
24
+ var word = '';
25
+ try {
26
+ var { words, rule } = error;
27
+ switch (error.type) {
28
+ case 'style':
29
+ word = this.fixStyle(words, rule);
30
+ break;
31
+ case 'length':
32
+ word = this.fixLength(words, rule);
33
+ break;
34
+ case 'word_length':
35
+ word = this.fixWordLength(words, rule);
36
+ break;
37
+ case 'forbidden_word':
38
+ word = this.fixForbiddenWord(words, rule);
39
+ break;
40
+ default:
41
+ return error.name;
42
+ }
43
+ } catch {
44
+ return error.name;
45
+ }
46
+
47
+ var suggestion = error.prefix + word;
48
+
49
+ // 检查建议名称是否与原名称相同,如果相同则不显示建议
50
+ if (suggestion === error.name || word === error.name) {
51
+ return null;
52
+ }
53
+
54
+ return suggestion;
55
+ };
56
+
57
+ /**
58
+ * 缩写名称
59
+ * @param {string} name 名称
60
+ * @param {number} max_length 最大长度
61
+ * @returns {string} 缩写后的名称
62
+ */
63
+ Corrector.prototype._abbreviateName = function (name, max_length) {
64
+ if (name.length <= max_length) {
65
+ return name;
66
+ }
67
+ // 先尝试推荐单词缩写,若失败则使用简单缩写策略
68
+ return this._abbreviateWord(name) || name.substring(0, max_length);
69
+ };
70
+
71
+ /**
72
+ * 推荐缩写单词
73
+ * @param {string} word 单词
74
+ * @returns {string} 缩写后的单词
75
+ */
76
+ Corrector.prototype._abbreviateWord = function (word) {
77
+ // 智能缩写策略:优先使用常见缩写,其次使用截断
78
+ var common_abbreviations = {
79
+ 'constants': 'const',
80
+ 'configuration': 'config',
81
+ 'application': 'app',
82
+ 'information': 'info',
83
+ 'temporary': 'temp',
84
+ 'parameter': 'param',
85
+ 'manager': 'mgr',
86
+ 'processor': 'proc',
87
+ 'controller': 'ctrl',
88
+ 'handler': 'hdlr',
89
+ 'service': 'svc',
90
+ 'provider': 'prov',
91
+ 'factory': 'fact',
92
+ 'builder': 'bldr',
93
+ 'adapter': 'adpt',
94
+ 'decorator': 'deco',
95
+ 'mediator': 'medi',
96
+ 'observer': 'obs',
97
+ 'strategy': 'strat',
98
+ 'command': 'cmd',
99
+ 'visitor': 'vis',
100
+ 'iterator': 'iter',
101
+ 'template': 'tmpl',
102
+ 'interpreter': 'interp',
103
+ 'component': 'comp',
104
+ 'property': 'prop',
105
+ 'entity': 'ent'
106
+ };
107
+
108
+ return common_abbreviations[word.toLowerCase()];
109
+ };
110
+
111
+ /**
112
+ * 转换命名风格
113
+ * @param {string} name 名称
114
+ * @param {string} target_style 目标风格
115
+ * @returns {string} 转换后的名称
116
+ */
117
+ Corrector.prototype.convertStyle = function (name, target_style) {
118
+ var words = splitWords(name);
119
+ return this.fixName(words, target_style);
120
+ };
121
+
122
+ /**
123
+ * 修正名称风格
124
+ * @param {array} words 单词数组
125
+ * @param {string} style 命名风格
126
+ * @returns {string} 修正后的名称
127
+ */
128
+ Corrector.prototype.fixName = function (words, style) {
129
+ let name = '';
130
+ switch (style) {
131
+ // 小写蛇形命名 (变量命名)
132
+ case 'snake_case':
133
+ for (let i = 0; i < words.length; i++) {
134
+ words[i] = words[i].toLowerCase();
135
+ }
136
+ name = words.join('_');
137
+ break;
138
+ // 小驼峰命名 (函数命名)
139
+ case 'camelCase':
140
+ for (let i = 0; i < words.length; i++) {
141
+ words[i] = words[i].toLowerCase();
142
+ if (i > 0) {
143
+ words[i] = words[i].charAt(0).toUpperCase() + words[i].substring(1);
144
+ }
145
+ }
146
+ name = words.join('');
147
+ break;
148
+ // 大驼峰命名 (类命名)
149
+ case 'PascalCase':
150
+ for (let i = 0; i < words.length; i++) {
151
+ words[i] = words[i].toLowerCase();
152
+ words[i] = words[i].charAt(0).toUpperCase() + words[i].substring(1);
153
+ }
154
+ name = words.join('');
155
+ break;
156
+ // 大写蛇形命名 (常量命名)
157
+ case 'UPPER_SNAKE_CASE':
158
+ for (let i = 0; i < words.length; i++) {
159
+ words[i] = words[i].toUpperCase();
160
+ }
161
+ name = words.join('_');
162
+ break;
163
+ // 小写命名 (变量命名)
164
+ case 'lowercase':
165
+ for (let i = 0; i < words.length; i++) {
166
+ words[i] = words[i].toLowerCase();
167
+ }
168
+ name = words.join('');
169
+ break;
170
+ // 大写命名 (常量命名)
171
+ case 'UPPERCASE':
172
+ for (let i = 0; i < words.length; i++) {
173
+ words[i] = words[i].toUpperCase();
174
+ }
175
+ name = words.join('');
176
+ break;
177
+ // 短横线命名 (拨号命名)
178
+ case 'kebab-case':
179
+ for (let i = 0; i < words.length; i++) {
180
+ words[i] = words[i].toLowerCase();
181
+ }
182
+ name = words.join('-');
183
+ break;
184
+ // 大写短横线命名 (密钥命名)
185
+ case 'UPPER-KEBAB-CASE':
186
+ for (let i = 0; i < words.length; i++) {
187
+ words[i] = words[i].toUpperCase();
188
+ }
189
+ name = words.join('-');
190
+ break;
191
+ }
192
+
193
+ return name;
194
+ }
195
+
196
+ /**
197
+ * 修正命名风格
198
+ * @param {string[]} words 单词数组
199
+ * @param {object} rule 规则配置
200
+ * @returns {string} 修正后的命名风格
201
+ */
202
+ Corrector.prototype.fixStyle = function (words, rule) {
203
+ var new_words = this._getNewWords(words, rule);
204
+ return this.fixName(new_words, rule.styles[0]);
205
+ }
206
+
207
+ /**
208
+ * 修正名称长度
209
+ * @param {string[]} words 单词数组
210
+ * @param {object} rule 规则配置
211
+ * @returns {string} 修正后的名称长度
212
+ */
213
+ Corrector.prototype.fixLength = function (words, rule) {
214
+ var new_words = this._getNewWords(words, rule);
215
+ new_words[0] = this._abbreviateName(new_words[0], rule.max);
216
+ return this.fixName(new_words, rule.styles[0]);
217
+ }
218
+
219
+ /**
220
+ * 修正单词长度
221
+ * @param {string[]} words 单词数组
222
+ * @param {object} rule 规则配置
223
+ * @returns {string} 修正后的单词长度
224
+ */
225
+ Corrector.prototype.fixWordLength = function (words, rule) {
226
+ var new_words = this._getNewWords(words, rule);
227
+ for (let i = 0; i < new_words.length; i++) {
228
+ if (new_words[i].length > rule.single_word_len) {
229
+ new_words[i] = new_words[i].substring(0, 4);
230
+ }
231
+ }
232
+ return this.fixName(new_words, rule.styles[0]);
233
+ }
234
+
235
+ /**
236
+ * 获取新的单词数组
237
+ * @param {string[]} words 单词数组
238
+ * @param {object} rule 规则配置
239
+ * @returns {string[]} 新的单词数组
240
+ */
241
+ Corrector.prototype._getNewWords = function (words, rule) {
242
+ var new_words = this._filterForbiddenWord(words, rule.forbidden_words);
243
+ return this._toRecommendWords(new_words, rule.recommend_words, rule.single_word_len);
244
+ }
245
+
246
+ /**
247
+ * 修正禁止词汇
248
+ * @param {string[]} words 单词数组
249
+ * @param {object} rule 规则配置
250
+ * @returns {string} 修正后的禁止词汇
251
+ */
252
+ Corrector.prototype.fixForbiddenWord = function (words, rule) {
253
+ var new_words = this._filterForbiddenWord(words, rule.forbidden_words);
254
+ return this.fixName(new_words, rule.styles[0]);
255
+ }
256
+
257
+ /**
258
+ * 是否禁止拼接词
259
+ * @param {string} word 单词
260
+ * @param {object} rule 规则配置
261
+ * @returns {boolean} 是否禁止拼接词
262
+ */
263
+ Corrector.prototype._isForbiddenWord = function (word, forbidden_words) {
264
+ for (let i = 0; i < forbidden_words.length; i++) {
265
+ let forbidden_word = forbidden_words[i];
266
+ if (word.toLowerCase() === forbidden_word.toLowerCase()) {
267
+ return true;
268
+ }
269
+ }
270
+ return false;
271
+ }
272
+
273
+ /**
274
+ * 过滤禁止拼接词
275
+ */
276
+ Corrector.prototype._filterForbiddenWord = function (words, forbidden_words) {
277
+ var new_word = [];
278
+ for (let i = 0; i < words.length; i++) {
279
+ let word = words[i];
280
+ if (!this._isForbiddenWord(word, forbidden_words)) {
281
+ new_word.push(word);
282
+ }
283
+ }
284
+ if (new_word.length === 0) {
285
+ new_word.push(words[words.length - 1]);
286
+ }
287
+ return new_word;
288
+ }
289
+
290
+ /**
291
+ * 替换禁止词汇为推荐词汇
292
+ * @param {string[]} words 单词数组
293
+ * @param {Array} forbidden_words 禁止词列表
294
+ * @param {object} recommend_words 推荐词配置
295
+ * @returns {string[]} 替换后的单词数组
296
+ */
297
+ Corrector.prototype._replaceForbiddenWords = function (words, forbidden_words, recommend_words) {
298
+ var new_words = [];
299
+ for (let i = 0; i < words.length; i++) {
300
+ let word = words[i];
301
+ if (this._isForbiddenWord(word, forbidden_words)) {
302
+ // 尝试为禁用词找到替代建议
303
+ var replacement = this._getForbiddenWordReplacement(word, recommend_words);
304
+ if (replacement) {
305
+ new_words.push(replacement);
306
+ }
307
+ } else {
308
+ new_words.push(word);
309
+ }
310
+ }
311
+ return new_words;
312
+ }
313
+
314
+ /**
315
+ * 获取禁用词的替代建议
316
+ * @param {string} forbidden_word 禁用词
317
+ * @param {object} recommend_words 推荐词配置
318
+ * @returns {string} 替代建议词
319
+ */
320
+ Corrector.prototype._getForbiddenWordReplacement = function (forbidden_word, recommend_words) {
321
+ for (var replacement in recommend_words) {
322
+ var forbidden_list = recommend_words[replacement];
323
+ for (let i = 0; i < forbidden_list.length; i++) {
324
+ if (forbidden_word.toLowerCase() === forbidden_list[i].toLowerCase()) {
325
+ return replacement;
326
+ }
327
+ }
328
+ }
329
+ return null;
330
+ }
331
+
332
+ /**
333
+ * 获取推荐的单词
334
+ * @param {string[]} words 单词数组
335
+ * @param {object} recommend 推荐配置
336
+ * @param {number} single_word_len 单个单词长度
337
+ * @returns {string[]} 推荐的单词数组
338
+ */
339
+ Corrector.prototype._toRecommendWords = function (words, recommend, single_word_len) {
340
+ let recommend_words = [];
341
+ for (let i = 0; i < words.length; i++) {
342
+ let word = words[i];
343
+ if (word.length > single_word_len) {
344
+ var recommend_word = this._getRecommendWord(word, recommend);
345
+ if (recommend_word) {
346
+ word = recommend_word;
347
+ }
348
+ }
349
+ recommend_words.push(word);
350
+ }
351
+ return recommend_words;
352
+ }
353
+
354
+ /**
355
+ * 获取推荐的单词
356
+ * @param {string} word 单词
357
+ * @param {object} recommend 推荐配置
358
+ * @returns {string} 推荐的单词
359
+ */
360
+ Corrector.prototype._getRecommendWord = function (word, recommend) {
361
+ var recommend_word = null;
362
+ for (var k in recommend) {
363
+ let arr = recommend[k];
364
+ for (let i = 0; i < arr.length; i++) {
365
+ let recommended = arr[i];
366
+ if (word.toLowerCase() === recommended.toLowerCase()) {
367
+ recommend_word = k;
368
+ continue;
369
+ }
370
+ }
371
+ }
372
+ return recommend_word;
373
+ }
374
+
375
+ module.exports = { Corrector };