mm_eslint 1.4.2 → 1.4.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 +325 -0
- package/README_EN.md +325 -0
- package/config.js +588 -571
- package/corrector.js +323 -0
- package/detector.js +1239 -3638
- package/eslint.config.js +22 -0
- package/index.js +1045 -1297
- package/package.json +54 -49
- package/tip.js +71 -0
- package/util.js +241 -0
- package/validator.js +270 -0
package/corrector.js
ADDED
|
@@ -0,0 +1,323 @@
|
|
|
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
|
+
return error.prefix + word;
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* 缩写名称
|
|
51
|
+
* @param {string} name 名称
|
|
52
|
+
* @param {number} max_length 最大长度
|
|
53
|
+
* @returns {string} 缩写后的名称
|
|
54
|
+
*/
|
|
55
|
+
Corrector.prototype._abbreviateName = function (name, max_length) {
|
|
56
|
+
if (name.length <= max_length) {
|
|
57
|
+
return name;
|
|
58
|
+
}
|
|
59
|
+
// 先尝试推荐单词缩写,若失败则使用简单缩写策略
|
|
60
|
+
return this._abbreviateWord(name) || name.substring(0, max_length);
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* 推荐缩写单词
|
|
65
|
+
* @param {string} word 单词
|
|
66
|
+
* @returns {string} 缩写后的单词
|
|
67
|
+
*/
|
|
68
|
+
Corrector.prototype._abbreviateWord = function (word) {
|
|
69
|
+
// 智能缩写策略:优先使用常见缩写,其次使用截断
|
|
70
|
+
var common_abbreviations = {
|
|
71
|
+
'constants': 'const',
|
|
72
|
+
'configuration': 'config',
|
|
73
|
+
'application': 'app',
|
|
74
|
+
'information': 'info',
|
|
75
|
+
'temporary': 'temp',
|
|
76
|
+
'parameter': 'param',
|
|
77
|
+
'manager': 'mgr',
|
|
78
|
+
'processor': 'proc',
|
|
79
|
+
'controller': 'ctrl',
|
|
80
|
+
'handler': 'hdlr',
|
|
81
|
+
'service': 'svc',
|
|
82
|
+
'provider': 'prov',
|
|
83
|
+
'factory': 'fact',
|
|
84
|
+
'builder': 'bldr',
|
|
85
|
+
'adapter': 'adpt',
|
|
86
|
+
'decorator': 'deco',
|
|
87
|
+
'mediator': 'medi',
|
|
88
|
+
'observer': 'obs',
|
|
89
|
+
'strategy': 'strat',
|
|
90
|
+
'command': 'cmd',
|
|
91
|
+
'visitor': 'vis',
|
|
92
|
+
'iterator': 'iter',
|
|
93
|
+
'template': 'tmpl',
|
|
94
|
+
'interpreter': 'interp',
|
|
95
|
+
'component': 'comp',
|
|
96
|
+
'property': 'prop',
|
|
97
|
+
'entity': 'ent'
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
return common_abbreviations[word.toLowerCase()];
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* 转换命名风格
|
|
105
|
+
* @param {string} name 名称
|
|
106
|
+
* @param {string} target_style 目标风格
|
|
107
|
+
* @returns {string} 转换后的名称
|
|
108
|
+
*/
|
|
109
|
+
Corrector.prototype.convertStyle = function (name, target_style) {
|
|
110
|
+
var words = splitWords(name);
|
|
111
|
+
return this.fixName(words, target_style);
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* 修正名称风格
|
|
116
|
+
* @param {array} words 单词数组
|
|
117
|
+
* @param {string} style 命名风格
|
|
118
|
+
* @returns {string} 修正后的名称
|
|
119
|
+
*/
|
|
120
|
+
Corrector.prototype.fixName = function (words, style) {
|
|
121
|
+
let name = '';
|
|
122
|
+
switch (style) {
|
|
123
|
+
// 小写蛇形命名 (变量命名)
|
|
124
|
+
case 'snake_case':
|
|
125
|
+
for (let i = 0; i < words.length; i++) {
|
|
126
|
+
words[i] = words[i].toLowerCase();
|
|
127
|
+
}
|
|
128
|
+
name = words.join('_');
|
|
129
|
+
break;
|
|
130
|
+
// 小驼峰命名 (函数命名)
|
|
131
|
+
case 'camelCase':
|
|
132
|
+
for (let i = 0; i < words.length; i++) {
|
|
133
|
+
words[i] = words[i].toLowerCase();
|
|
134
|
+
if (i > 0) {
|
|
135
|
+
words[i] = words[i].charAt(0).toUpperCase() + words[i].substring(1);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
name = words.join('');
|
|
139
|
+
break;
|
|
140
|
+
// 大驼峰命名 (类命名)
|
|
141
|
+
case 'PascalCase':
|
|
142
|
+
for (let i = 0; i < words.length; i++) {
|
|
143
|
+
words[i] = words[i].toLowerCase();
|
|
144
|
+
words[i] = words[i].charAt(0).toUpperCase() + words[i].substring(1);
|
|
145
|
+
}
|
|
146
|
+
name = words.join('');
|
|
147
|
+
break;
|
|
148
|
+
// 大写蛇形命名 (常量命名)
|
|
149
|
+
case 'UPPER_SNAKE_CASE':
|
|
150
|
+
for (let i = 0; i < words.length; i++) {
|
|
151
|
+
words[i] = words[i].toUpperCase();
|
|
152
|
+
}
|
|
153
|
+
name = words.join('_');
|
|
154
|
+
break;
|
|
155
|
+
// 小写命名 (变量命名)
|
|
156
|
+
case 'lowercase':
|
|
157
|
+
for (let i = 0; i < words.length; i++) {
|
|
158
|
+
words[i] = words[i].toLowerCase();
|
|
159
|
+
}
|
|
160
|
+
name = words.join('');
|
|
161
|
+
break;
|
|
162
|
+
// 大写命名 (常量命名)
|
|
163
|
+
case 'UPPERCASE':
|
|
164
|
+
for (let i = 0; i < words.length; i++) {
|
|
165
|
+
words[i] = words[i].toUpperCase();
|
|
166
|
+
}
|
|
167
|
+
name = words.join('');
|
|
168
|
+
break;
|
|
169
|
+
// 短横线命名 (拨号命名)
|
|
170
|
+
case 'kebab-case':
|
|
171
|
+
for (let i = 0; i < words.length; i++) {
|
|
172
|
+
words[i] = words[i].toLowerCase();
|
|
173
|
+
}
|
|
174
|
+
name = words.join('-');
|
|
175
|
+
break;
|
|
176
|
+
// 大写短横线命名 (密钥命名)
|
|
177
|
+
case 'UPPER-KEBAB-CASE':
|
|
178
|
+
for (let i = 0; i < words.length; i++) {
|
|
179
|
+
words[i] = words[i].toUpperCase();
|
|
180
|
+
}
|
|
181
|
+
name = words.join('-');
|
|
182
|
+
break;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
return name;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* 修正命名风格
|
|
190
|
+
* @param {string[]} words 单词数组
|
|
191
|
+
* @param {object} rule 规则配置
|
|
192
|
+
* @returns {string} 修正后的命名风格
|
|
193
|
+
*/
|
|
194
|
+
Corrector.prototype.fixStyle = function (words, rule) {
|
|
195
|
+
var new_words = this._getNewWords(words, rule);
|
|
196
|
+
return this.fixName(new_words, rule.styles[0]);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* 修正名称长度
|
|
201
|
+
* @param {string[]} words 单词数组
|
|
202
|
+
* @param {object} rule 规则配置
|
|
203
|
+
* @returns {string} 修正后的名称长度
|
|
204
|
+
*/
|
|
205
|
+
Corrector.prototype.fixLength = function (words, rule) {
|
|
206
|
+
var new_words = this._getNewWords(words, rule);
|
|
207
|
+
new_words[0] = this._abbreviateName(new_words[0], rule.max);
|
|
208
|
+
return this.fixName(new_words, rule.styles[0]);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* 修正单词长度
|
|
213
|
+
* @param {string[]} words 单词数组
|
|
214
|
+
* @param {object} rule 规则配置
|
|
215
|
+
* @returns {string} 修正后的单词长度
|
|
216
|
+
*/
|
|
217
|
+
Corrector.prototype.fixWordLength = function (words, rule) {
|
|
218
|
+
var new_words = this._getNewWords(words, rule);
|
|
219
|
+
for (let i = 0; i < new_words.length; i++) {
|
|
220
|
+
if (new_words[i].length > rule.single_word_len) {
|
|
221
|
+
new_words[i] = new_words[i].substring(0, 4);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
return this.fixName(new_words, rule.styles[0]);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* 获取新的单词数组
|
|
229
|
+
* @param {string[]} words 单词数组
|
|
230
|
+
* @param {object} rule 规则配置
|
|
231
|
+
* @returns {string[]} 新的单词数组
|
|
232
|
+
*/
|
|
233
|
+
Corrector.prototype._getNewWords = function (words, rule) {
|
|
234
|
+
var new_words = this._filterForbiddenWord(words, rule.forbidden_words);
|
|
235
|
+
return this._toRecommendWords(new_words, rule.recommend_words, rule.single_word_len);
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* 修正禁止词汇
|
|
240
|
+
* @param {string[]} words 单词数组
|
|
241
|
+
* @param {object} rule 规则配置
|
|
242
|
+
* @returns {string} 修正后的禁止词汇
|
|
243
|
+
*/
|
|
244
|
+
Corrector.prototype.fixForbiddenWord = function (words, rule) {
|
|
245
|
+
var new_words = this._filterForbiddenWord(words, rule.forbidden_words);
|
|
246
|
+
return this.fixName(new_words, rule.styles[0]);
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* 是否禁止拼接词
|
|
251
|
+
* @param {string} word 单词
|
|
252
|
+
* @param {object} rule 规则配置
|
|
253
|
+
* @returns {boolean} 是否禁止拼接词
|
|
254
|
+
*/
|
|
255
|
+
Corrector.prototype._isForbiddenWord = function (word, forbidden_words) {
|
|
256
|
+
for (let i = 0; i < forbidden_words.length; i++) {
|
|
257
|
+
let forbidden_word = forbidden_words[i];
|
|
258
|
+
if (word.toLowerCase() === forbidden_word.toLowerCase()) {
|
|
259
|
+
return true;
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
return false;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
/**
|
|
266
|
+
* 过滤禁止拼接词
|
|
267
|
+
*/
|
|
268
|
+
Corrector.prototype._filterForbiddenWord = function (words, forbidden_words) {
|
|
269
|
+
var new_word = [];
|
|
270
|
+
for (let i = 0; i < words.length; i++) {
|
|
271
|
+
let word = words[i];
|
|
272
|
+
if (!this._isForbiddenWord(word, forbidden_words)) {
|
|
273
|
+
new_word.push(word);
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
return new_word;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
/**
|
|
280
|
+
* 获取推荐的单词
|
|
281
|
+
* @param {string[]} words 单词数组
|
|
282
|
+
* @param {object} recommend 推荐配置
|
|
283
|
+
* @param {number} single_word_len 单个单词长度
|
|
284
|
+
* @returns {string[]} 推荐的单词数组
|
|
285
|
+
*/
|
|
286
|
+
Corrector.prototype._toRecommendWords = function (words, recommend, single_word_len) {
|
|
287
|
+
// console.log('推荐单词', words, recommend, single_word_len);
|
|
288
|
+
let recommend_words = [];
|
|
289
|
+
for (let i = 0; i < words.length; i++) {
|
|
290
|
+
let word = words[i];
|
|
291
|
+
if (word.length > single_word_len) {
|
|
292
|
+
var recommend_word = this._getRecommendWord(word, recommend);
|
|
293
|
+
if (recommend_word) {
|
|
294
|
+
word = recommend_word;
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
recommend_words.push(word);
|
|
298
|
+
}
|
|
299
|
+
return recommend_words;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
/**
|
|
303
|
+
* 获取推荐的单词
|
|
304
|
+
* @param {string} word 单词
|
|
305
|
+
* @param {object} recommend 推荐配置
|
|
306
|
+
* @returns {string} 推荐的单词
|
|
307
|
+
*/
|
|
308
|
+
Corrector.prototype._getRecommendWord = function (word, recommend) {
|
|
309
|
+
var recommend_word = null;
|
|
310
|
+
for (var k in recommend) {
|
|
311
|
+
let arr = recommend[k];
|
|
312
|
+
for (let i = 0; i < arr.length; i++) {
|
|
313
|
+
let recommended = arr[i];
|
|
314
|
+
if (word.toLowerCase() === recommended.toLowerCase()) {
|
|
315
|
+
recommend_word = k;
|
|
316
|
+
continue;
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
return recommend_word;
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
module.exports = { Corrector };
|