@agilebot/eslint-plugin 0.3.6 → 0.3.8
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.d.ts +6 -3
- package/dist/index.js +223 -7
- package/package.json +3 -4
package/dist/index.d.ts
CHANGED
@@ -1,10 +1,11 @@
|
|
1
|
-
|
1
|
+
import * as eslint from 'eslint';
|
2
|
+
|
2
3
|
declare namespace plugin {
|
3
|
-
let rules:
|
4
|
+
let rules: eslint.Linter.RulesRecord;
|
4
5
|
namespace configs {
|
5
6
|
namespace recommended {
|
6
7
|
export let plugins: string[];
|
7
|
-
let rules_1:
|
8
|
+
let rules_1: eslint.Linter.RulesRecord;
|
8
9
|
export { rules_1 as rules };
|
9
10
|
export namespace settings {
|
10
11
|
namespace react {
|
@@ -14,3 +15,5 @@ declare namespace plugin {
|
|
14
15
|
}
|
15
16
|
}
|
16
17
|
}
|
18
|
+
|
19
|
+
export { plugin as default };
|
package/dist/index.js
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
/**
|
2
|
-
* @license @agilebot/eslint-plugin v0.3.
|
2
|
+
* @license @agilebot/eslint-plugin v0.3.8
|
3
3
|
*
|
4
4
|
* Copyright (c) Agilebot, Inc. and its affiliates.
|
5
5
|
*
|
@@ -8,9 +8,9 @@
|
|
8
8
|
*/
|
9
9
|
'use strict';
|
10
10
|
|
11
|
+
var eslintUtils = require('@agilebot/eslint-utils');
|
11
12
|
var fs = require('node:fs');
|
12
13
|
var path = require('node:path');
|
13
|
-
var eslintUtils = require('@agilebot/eslint-utils');
|
14
14
|
var utils = require('@typescript-eslint/utils');
|
15
15
|
|
16
16
|
function _interopNamespaceDefault(e) {
|
@@ -72,11 +72,136 @@ var enforceMuiIconAlias = {
|
|
72
72
|
}
|
73
73
|
};
|
74
74
|
|
75
|
+
var funcNaming = {
|
76
|
+
meta: {
|
77
|
+
docs: {
|
78
|
+
description: 'Enforce function naming convention'
|
79
|
+
},
|
80
|
+
schema: [{
|
81
|
+
type: 'object',
|
82
|
+
properties: {
|
83
|
+
format: {
|
84
|
+
"enum": ['camelCase', 'PascalCase']
|
85
|
+
}
|
86
|
+
}
|
87
|
+
}],
|
88
|
+
messages: {
|
89
|
+
invalidFuncNaming: 'Invalid function naming for non-React component, expected {{format}}',
|
90
|
+
invalidReactFCNaming: 'Invalid naming convention for React functional component, expected PascalCase'
|
91
|
+
}
|
92
|
+
},
|
93
|
+
create(context) {
|
94
|
+
if (!context.options[0]) {
|
95
|
+
throw new Error('Missing options');
|
96
|
+
}
|
97
|
+
const format = context.options[0].format;
|
98
|
+
function validate({
|
99
|
+
node,
|
100
|
+
fnName
|
101
|
+
}) {
|
102
|
+
let isPass;
|
103
|
+
switch (format) {
|
104
|
+
case 'camelCase':
|
105
|
+
if (!eslintUtils.isCamelCase(fnName)) {
|
106
|
+
isPass = false;
|
107
|
+
}
|
108
|
+
break;
|
109
|
+
case 'PascalCase':
|
110
|
+
if (!eslintUtils.isPascalCase(fnName)) {
|
111
|
+
isPass = false;
|
112
|
+
}
|
113
|
+
break;
|
114
|
+
}
|
115
|
+
if (isPass === false) {
|
116
|
+
context.report({
|
117
|
+
node: node,
|
118
|
+
messageId: 'invalidFuncNaming',
|
119
|
+
data: {
|
120
|
+
format
|
121
|
+
}
|
122
|
+
});
|
123
|
+
}
|
124
|
+
}
|
125
|
+
function checkJSXElement(node) {
|
126
|
+
if (!node) {
|
127
|
+
return false;
|
128
|
+
}
|
129
|
+
if (node.type === 'JSXElement' || node.type === 'JSXFragment') {
|
130
|
+
return true;
|
131
|
+
}
|
132
|
+
if (node.type === 'BlockStatement') {
|
133
|
+
for (const statement of node.body) {
|
134
|
+
if (statement.type === 'ReturnStatement') {
|
135
|
+
if (checkJSXElement(statement.argument)) {
|
136
|
+
return true;
|
137
|
+
}
|
138
|
+
} else if (checkJSXElement(statement)) {
|
139
|
+
return true;
|
140
|
+
}
|
141
|
+
}
|
142
|
+
}
|
143
|
+
if (node.type === 'ArrowFunctionExpression' || node.type === 'FunctionExpression') {
|
144
|
+
return checkJSXElement(node.body);
|
145
|
+
}
|
146
|
+
return false;
|
147
|
+
}
|
148
|
+
return {
|
149
|
+
MethodDefinition(node) {
|
150
|
+
if (node.kind === 'method') ;
|
151
|
+
},
|
152
|
+
FunctionDeclaration(node) {
|
153
|
+
if (node.type === 'FunctionDeclaration' && node.id) {
|
154
|
+
const fnName = node.id.name;
|
155
|
+
const isReactComponent = checkJSXElement(node.body);
|
156
|
+
if (!isReactComponent) {
|
157
|
+
validate({
|
158
|
+
node,
|
159
|
+
fnName
|
160
|
+
});
|
161
|
+
}
|
162
|
+
}
|
163
|
+
},
|
164
|
+
VariableDeclarator(node) {
|
165
|
+
if (node.init && ['FunctionExpression', 'ArrowFunctionExpression'].includes(node.init.type)) {
|
166
|
+
const fnName = node.id.name;
|
167
|
+
let isReactComponent = checkJSXElement(node.init.body);
|
168
|
+
if (node.id.typeAnnotation && node.id.typeAnnotation.typeAnnotation) {
|
169
|
+
const typeAnnotation = node.id.typeAnnotation.typeAnnotation;
|
170
|
+
if (typeAnnotation.type === 'TSTypeReference' && typeAnnotation.typeName.type === 'Identifier') {
|
171
|
+
const typeName = typeAnnotation.typeName.name;
|
172
|
+
if (['FC', 'React.FC', 'FunctionComponent', 'React.FunctionComponent'].includes(typeName)) {
|
173
|
+
isReactComponent = true;
|
174
|
+
}
|
175
|
+
}
|
176
|
+
}
|
177
|
+
if (!isReactComponent) {
|
178
|
+
validate({
|
179
|
+
node,
|
180
|
+
fnName
|
181
|
+
});
|
182
|
+
}
|
183
|
+
}
|
184
|
+
},
|
185
|
+
Property(node) {
|
186
|
+
if (node.value.type === 'FunctionExpression') ;
|
187
|
+
}
|
188
|
+
};
|
189
|
+
}
|
190
|
+
};
|
191
|
+
|
75
192
|
function getSetting(context, name) {
|
76
193
|
return context.settings["agilebot/".concat(name)];
|
77
194
|
}
|
78
195
|
|
79
|
-
|
196
|
+
const warned = new Set();
|
197
|
+
function warnOnce(message) {
|
198
|
+
if (warned.has(message)) {
|
199
|
+
return;
|
200
|
+
}
|
201
|
+
warned.add(message);
|
202
|
+
console.warn("Warning: ".concat(message));
|
203
|
+
}
|
204
|
+
|
80
205
|
var importMonorepo = {
|
81
206
|
meta: {
|
82
207
|
type: 'problem',
|
@@ -95,10 +220,7 @@ var importMonorepo = {
|
|
95
220
|
ImportDeclaration(node) {
|
96
221
|
let prefix = getSetting(context, 'monorepo-scope');
|
97
222
|
if (!prefix) {
|
98
|
-
|
99
|
-
console.error('Warning: agilebot/monorepo-scope is not set.');
|
100
|
-
warnedForMissingPrefix = true;
|
101
|
-
}
|
223
|
+
warnOnce('agilebot/monorepo-scope is not set.');
|
102
224
|
return;
|
103
225
|
}
|
104
226
|
prefix = "".concat(prefix, "/");
|
@@ -269,6 +391,98 @@ var intlIdMissing = {
|
|
269
391
|
}
|
270
392
|
};
|
271
393
|
|
394
|
+
var intlIdNaming = {
|
395
|
+
meta: {
|
396
|
+
docs: {
|
397
|
+
description: 'Validates intl message ids naming convention',
|
398
|
+
category: 'Intl'
|
399
|
+
},
|
400
|
+
fixable: undefined,
|
401
|
+
schema: [{
|
402
|
+
type: 'object',
|
403
|
+
properties: {
|
404
|
+
format: {
|
405
|
+
"enum": ['camelCase', 'PascalCase']
|
406
|
+
}
|
407
|
+
}
|
408
|
+
}],
|
409
|
+
messages: {
|
410
|
+
invalidIdNaming: "Invalid id naming, expected {{format}}"
|
411
|
+
}
|
412
|
+
},
|
413
|
+
create: function (context) {
|
414
|
+
if (!context.options[0]) {
|
415
|
+
throw new Error('Missing options');
|
416
|
+
}
|
417
|
+
const format = context.options[0].format;
|
418
|
+
function report(node, value) {
|
419
|
+
const values = value.split('.');
|
420
|
+
let isPass;
|
421
|
+
for (const v of values) {
|
422
|
+
switch (format) {
|
423
|
+
case 'camelCase':
|
424
|
+
if (!eslintUtils.isCamelCase(v)) {
|
425
|
+
isPass = false;
|
426
|
+
}
|
427
|
+
break;
|
428
|
+
case 'PascalCase':
|
429
|
+
if (!eslintUtils.isPascalCase(v)) {
|
430
|
+
isPass = false;
|
431
|
+
}
|
432
|
+
break;
|
433
|
+
}
|
434
|
+
}
|
435
|
+
if (isPass === false) {
|
436
|
+
context.report({
|
437
|
+
node: node,
|
438
|
+
messageId: 'invalidIdNaming',
|
439
|
+
data: {
|
440
|
+
format
|
441
|
+
}
|
442
|
+
});
|
443
|
+
}
|
444
|
+
}
|
445
|
+
function processLiteral(node) {
|
446
|
+
report(node, node.value);
|
447
|
+
}
|
448
|
+
function processTemplateLiteral(node) {
|
449
|
+
const displayStr = templateLiteralDisplayStr(node);
|
450
|
+
report(node, displayStr);
|
451
|
+
}
|
452
|
+
function processAttrNode(node) {
|
453
|
+
if (node.value.type === 'Literal') {
|
454
|
+
return processLiteral(node.value);
|
455
|
+
}
|
456
|
+
if (node.value.type === 'JSXExpressionContainer' && node.value.expression.type === 'TemplateLiteral') {
|
457
|
+
return processTemplateLiteral(node.value.expression);
|
458
|
+
}
|
459
|
+
if (node.value.type === 'TemplateLiteral') {
|
460
|
+
return processTemplateLiteral(node.value);
|
461
|
+
}
|
462
|
+
}
|
463
|
+
return {
|
464
|
+
JSXIdentifier: function (node) {
|
465
|
+
const attrNode = findFormattedMessageAttrNode(node, 'id');
|
466
|
+
if (attrNode) {
|
467
|
+
return processAttrNode(attrNode);
|
468
|
+
}
|
469
|
+
},
|
470
|
+
CallExpression: function (node) {
|
471
|
+
const attrNode = findFormatMessageAttrNode(node, 'id');
|
472
|
+
if (attrNode) {
|
473
|
+
return processAttrNode(attrNode);
|
474
|
+
}
|
475
|
+
},
|
476
|
+
Property: function (node) {
|
477
|
+
const attrNode = findAttrNodeInDefineMessages(node, 'id') || findAttrNodeInDefineMessage(node, 'id');
|
478
|
+
if (attrNode) {
|
479
|
+
return processAttrNode(attrNode);
|
480
|
+
}
|
481
|
+
}
|
482
|
+
};
|
483
|
+
}
|
484
|
+
};
|
485
|
+
|
272
486
|
var intlIdPrefix = {
|
273
487
|
meta: {
|
274
488
|
docs: {
|
@@ -2414,8 +2628,10 @@ var tssUnusedClasses = {
|
|
2414
2628
|
var ruleFiles = /*#__PURE__*/Object.freeze({
|
2415
2629
|
__proto__: null,
|
2416
2630
|
rules_enforce_mui_icon_alias: enforceMuiIconAlias,
|
2631
|
+
rules_func_naming: funcNaming,
|
2417
2632
|
rules_import_monorepo: importMonorepo,
|
2418
2633
|
rules_intl_id_missing: intlIdMissing,
|
2634
|
+
rules_intl_id_naming: intlIdNaming,
|
2419
2635
|
rules_intl_id_prefix: intlIdPrefix,
|
2420
2636
|
rules_intl_id_unused: intlIdUnused,
|
2421
2637
|
rules_intl_no_default: intlNoDefault,
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@agilebot/eslint-plugin",
|
3
|
-
"version": "0.3.
|
3
|
+
"version": "0.3.8",
|
4
4
|
"description": "Agilebot's ESLint plugin",
|
5
5
|
"main": "dist/index.js",
|
6
6
|
"types": "dist/index.d.ts",
|
@@ -20,7 +20,7 @@
|
|
20
20
|
"dependencies": {
|
21
21
|
"@typescript-eslint/utils": "~7.9.0",
|
22
22
|
"eslint-plugin-react": "^7.34.1",
|
23
|
-
"@agilebot/eslint-utils": "0.3.
|
23
|
+
"@agilebot/eslint-utils": "0.3.8"
|
24
24
|
},
|
25
25
|
"peerDependencies": {
|
26
26
|
"eslint": "^7.0.0 || ^8.0.0"
|
@@ -35,8 +35,7 @@
|
|
35
35
|
"eslint-vitest-rule-tester": "^0.3.2"
|
36
36
|
},
|
37
37
|
"scripts": {
|
38
|
-
"build": "rollup -c rollup.config.mjs
|
39
|
-
"dts": "tsc -p tsconfig.dts.json",
|
38
|
+
"build": "rollup -c rollup.config.mjs",
|
40
39
|
"lint": "eslint src --fix"
|
41
40
|
}
|
42
41
|
}
|